From 4f9f821a9c4842827cba3bacb7aebcf65336107d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manw=C3=AB?= Date: Sat, 5 Oct 2024 01:06:19 -0300 Subject: [PATCH] update formats json --- public/cards-worker/index.js | 2 +- public/tooldb-worker/index.js | 73828 ++++++++++++++-------------- src/assets/resources/formats.json | 1998 +- src/cards-worker/allFormats.ts | 3713 +- src/info.json | 2 +- 5 files changed, 40473 insertions(+), 39070 deletions(-) diff --git a/public/cards-worker/index.js b/public/cards-worker/index.js index 44dd412..e360027 100644 --- a/public/cards-worker/index.js +++ b/public/cards-worker/index.js @@ -1 +1 @@ -!function(f){"object"==typeof exports&&"undefined"!=typeof module?module.exports=f():"function"==typeof define&&define.amd?define([],f):("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).cardsworker=f()}(function(){return function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);throw(f=new Error("Cannot find module '"+i+"'")).code="MODULE_NOT_FOUND",f}c=n[i]={exports:{}},e[i][0].call(c.exports,function(r){return o(e[i][1][r]||r)},c,c.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i{allFormats[format.name]=format}),exports.default=allFormats},{}],2:[function(require,module,exports){"use strict";var __importDefault=this&&this.__importDefault||function(mod){return mod&&mod.__esModule?mod:{default:mod}};Object.defineProperty(exports,"__esModule",{value:!0});const getCollectionData_1=__importDefault(require("./getCollectionData"));self.onmessage=e=>{var{cards:e,cardsList,allCards,setNames,sets}=e.data,e=(0,getCollectionData_1.default)(e,cardsList,allCards,setNames,sets);self.postMessage(e)}},{"./getCollectionData":10}],3:[function(require,module,exports){"use strict";Object.defineProperty(exports,"__esModule",{value:!0});const colorFlags={NONE:0,W:1,U:2,B:4,R:8,G:16,C:32};exports.default=class{constructor(){return this.w=!1,this.u=!1,this.b=!1,this.r=!1,this.g=!1,this.c=!1,this}get(){const _arr=[];return this.w&&_arr.push(1),this.u&&_arr.push(2),this.b&&_arr.push(3),this.r&&_arr.push(4),this.g&&_arr.push(5),this.c&&_arr.push(6),_arr}getBits(){let bits=0;return this.w&&(bits|=colorFlags.W),this.u&&(bits|=colorFlags.U),this.b&&(bits|=colorFlags.B),this.r&&(bits|=colorFlags.R),this.g&&(bits|=colorFlags.G),this.c&&(bits|=colorFlags.C),bits}getBaseColor(){var bits=this.getBits();if(bits===colorFlags.C||bits===colorFlags.NONE)return 6;bits=326!==c)[0]:7}get length(){let ret=0;return this.w&&(ret+=1),this.u&&(ret+=1),this.b&&(ret+=1),this.r&&(ret+=1),this.g&&(ret+=1),this.c&&(ret+=1),ret}addFromCost(cost){return 0===cost.length&&(this.c=!0),cost.forEach(symbol=>{for(const c of symbol)switch(c){case"w":this.w=!0;break;case"u":this.u=!0;break;case"b":this.b=!0;break;case"r":this.r=!0;break;case"g":this.g=!0;break;case"x":case"1":case"2":case"3":case"4":case"5":case"6":case"7":case"8":case"9":case"10":case"11":case"12":case"13":case"14":case"15":case"16":case"17":this.c=!0}}),this}addFromArray(cost){return cost.forEach(color=>{switch(color){case 1:this.w=!0;break;case 2:this.u=!0;break;case 3:this.b=!0;break;case 4:this.r=!0;break;case 5:this.g=!0;break;case 6:this.c=!0}}),this}addFromColor(color){return this.w=color.w,this.u=color.u,this.b=color.b,this.r=color.r,this.g=color.g,this.c=color.c,this}addFromBits(colorBits){return this.w=!!(colorBits&colorFlags.W),this.u=!!(colorBits&colorFlags.U),this.b=!!(colorBits&colorFlags.B),this.r=!!(colorBits&colorFlags.R),this.g=!!(colorBits&colorFlags.G),this.c=!!(colorBits&colorFlags.C),this}equalTo(color){return this.w==color.w&&this.u==color.u&&this.b==color.b&&this.r==color.r&&this.g==color.g&&this.c==color.c}getColorArchetype(){let currentColorFlags=colorFlags.NONE;switch(this.w&&(currentColorFlags|=colorFlags.W),this.u&&(currentColorFlags|=colorFlags.U),this.b&&(currentColorFlags|=colorFlags.B),this.r&&(currentColorFlags|=colorFlags.R),this.g&&(currentColorFlags|=colorFlags.G),currentColorFlags=32{const format=allFormats_1.default[name];format.bannedTitleIds.includes(card.TitleId)&&banned.push(name)}),banned}},{"./allFormats":1}],6:[function(require,module,exports){"use strict";var __importDefault=this&&this.__importDefault||function(mod){return mod&&mod.__esModule?mod:{default:mod}};Object.defineProperty(exports,"__esModule",{value:!0});const allFormats_1=__importDefault(require("./allFormats")),findSetByCode_1=__importDefault(require("./findSetByCode"));exports.default=function(card,allCards,setNames,sets){const allowed=[],arenaSetCode=[card.Set.toLowerCase()];return card.DigitalSet&&arenaSetCode.push(card.DigitalSet.toLowerCase()),card.Reprints.forEach(cid=>{var cid=allCards[cid];cid&&(cid=(0,findSetByCode_1.default)(null===cid.DigitalSet||""===cid.DigitalSet?cid.Set:cid.DigitalSet,setNames,sets))&&arenaSetCode.push(cid.arenacode)}),Object.keys(allFormats_1.default).forEach(name=>{const format=allFormats_1.default[name];!format.allowedTitleIds.includes(card.TitleId)&&!format.legalSets.some(set=>0<=arenaSetCode.indexOf(set.toLowerCase()))||format.bannedTitleIds.includes(card.TitleId)||("Pauper"!=name&&"HistoricPauper"!=name||"common"==card.Rarity)&&allowed.push(name)}),allowed}},{"./allFormats":1,"./findSetByCode":4}],7:[function(require,module,exports){"use strict";var __importDefault=this&&this.__importDefault||function(mod){return mod&&mod.__esModule?mod:{default:mod}};Object.defineProperty(exports,"__esModule",{value:!0});const findSetByCode_1=__importDefault(require("./findSetByCode"));exports.default=function(card,setNames,sets){return setNames=(0,findSetByCode_1.default)(null===card.DigitalSet||""===card.DigitalSet?card.Set:card.DigitalSet,setNames,sets),!card.IsToken&&(-1!==(null==setNames?void 0:setNames.collation)&&(11!==card.LinkedFaceType&&!!card.IsPrimaryCard))}},{"./findSetByCode":4}],8:[function(require,module,exports){"use strict";var __importDefault=this&&this.__importDefault||function(mod){return mod&&mod.__esModule?mod:{default:mod}};Object.defineProperty(exports,"__esModule",{value:!0});const getCardFormats_1=__importDefault(require("./getCardFormats"));exports.default=function(card,cards,setNames,sets){if("land"===card.Rarity||!card.IsToken)return!1;if(11===card.LinkedFaceType)return!1;const formats=(0,getCardFormats_1.default)(card,cards,setNames,sets);return!!(formats.includes("Standard")||formats.includes("Historic")||formats.includes("Alchemy")||formats.includes("Explorer")||formats.includes("Timeless")||formats.includes("Singleton"))}},{"./getCardFormats":6}],9:[function(require,module,exports){"use strict";var __importDefault=this&&this.__importDefault||function(mod){return mod&&mod.__esModule?mod:{default:mod}};Object.defineProperty(exports,"__esModule",{value:!0});const allFormats_1=__importDefault(require("./allFormats"));exports.default=function(card){const suspended=[];return Object.keys(allFormats_1.default).forEach(name=>{const format=allFormats_1.default[name];format.suspendedTitleIds.includes(card.TitleId)&&suspended.push(name)}),suspended}},{"./allFormats":1}],10:[function(require,module,exports){"use strict";var __importDefault=this&&this.__importDefault||function(mod){return mod&&mod.__esModule?mod:{default:mod}};Object.defineProperty(exports,"__esModule",{value:!0});const colors_1=__importDefault(require("./colors")),getCardBanned_1=__importDefault(require("./getCardBanned")),getCardFormats_1=__importDefault(require("./getCardFormats")),getCardInBoosters_1=__importDefault(require("./getCardInBoosters")),getCardIsCraftable_1=__importDefault(require("./getCardIsCraftable")),getCardSuspended_1=__importDefault(require("./getCardSuspended")),getRarityFilterVal_1=__importDefault(require("./getRarityFilterVal")),DRAFT_RANKS=["F","D-","D","D+","C-","C","C+","B-","B","B+","A-","A","A+"],DRAFT_RANKS_LOLA=["","A+","A","A-","B+","B","B-","C+","C","C-","D+","D","D-","F"],FACE_SPECIALIZE_BACK=11,FACE_ADVENTURE=7,FACE_MODAL_BACK=9,FACE_DFC_BACK=1,FACE_SPLIT=5;exports.default=function(cards,cardsList,allCards,setNames,sets){return cardsList.filter(card=>card.LinkedFaceType!==FACE_DFC_BACK&&3!==card.LinkedFaceType&&card.LinkedFaceType!==FACE_ADVENTURE&&card.LinkedFaceType!==FACE_SPLIT&&card.LinkedFaceType!==FACE_MODAL_BACK&&card.LinkedFaceType!==FACE_SPECIALIZE_BACK).map(card=>{var RANK_SOURCE=0==card.RankData.rankSource?DRAFT_RANKS:DRAFT_RANKS_LOLA;const dfc=allCards[0{allFormats[format.name]=format}),exports.default=allFormats},{}],2:[function(require,module,exports){var __importDefault=this&&this.__importDefault||function(mod){return mod&&mod.__esModule?mod:{default:mod}};Object.defineProperty(exports,"__esModule",{value:!0});let getCollectionData_1=__importDefault(require("./getCollectionData"));self.onmessage=e=>{var{cards:e,cardsList,allCards,setNames,sets}=e.data,e=(0,getCollectionData_1.default)(e,cardsList,allCards,setNames,sets);self.postMessage(e)}},{"./getCollectionData":10}],3:[function(require,module,exports){Object.defineProperty(exports,"__esModule",{value:!0});let colorFlags={NONE:0,W:1,U:2,B:4,R:8,G:16,C:32};exports.default=class{constructor(){return this.w=!1,this.u=!1,this.b=!1,this.r=!1,this.g=!1,this.c=!1,this}get(){var _arr=[];return this.w&&_arr.push(1),this.u&&_arr.push(2),this.b&&_arr.push(3),this.r&&_arr.push(4),this.g&&_arr.push(5),this.c&&_arr.push(6),_arr}getBits(){let bits=0;return this.w&&(bits|=colorFlags.W),this.u&&(bits|=colorFlags.U),this.b&&(bits|=colorFlags.B),this.r&&(bits|=colorFlags.R),this.g&&(bits|=colorFlags.G),this.c&&(bits|=colorFlags.C),bits}getBaseColor(){var bits=this.getBits();return bits===colorFlags.C||bits===colorFlags.NONE?6:(bits=326!==c)[0]:7}get length(){let ret=0;return this.w&&(ret+=1),this.u&&(ret+=1),this.b&&(ret+=1),this.r&&(ret+=1),this.g&&(ret+=1),this.c&&(ret+=1),ret}addFromCost(cost){return 0===cost.length&&(this.c=!0),cost.forEach(symbol=>{for(var c of symbol)switch(c){case"w":this.w=!0;break;case"u":this.u=!0;break;case"b":this.b=!0;break;case"r":this.r=!0;break;case"g":this.g=!0;break;case"x":case"1":case"2":case"3":case"4":case"5":case"6":case"7":case"8":case"9":case"10":case"11":case"12":case"13":case"14":case"15":case"16":case"17":this.c=!0}}),this}addFromArray(cost){return cost.forEach(color=>{switch(color){case 1:this.w=!0;break;case 2:this.u=!0;break;case 3:this.b=!0;break;case 4:this.r=!0;break;case 5:this.g=!0;break;case 6:this.c=!0}}),this}addFromColor(color){return this.w=color.w,this.u=color.u,this.b=color.b,this.r=color.r,this.g=color.g,this.c=color.c,this}addFromBits(colorBits){return this.w=!!(colorBits&colorFlags.W),this.u=!!(colorBits&colorFlags.U),this.b=!!(colorBits&colorFlags.B),this.r=!!(colorBits&colorFlags.R),this.g=!!(colorBits&colorFlags.G),this.c=!!(colorBits&colorFlags.C),this}equalTo(color){return this.w==color.w&&this.u==color.u&&this.b==color.b&&this.r==color.r&&this.g==color.g&&this.c==color.c}getColorArchetype(){let currentColorFlags=colorFlags.NONE;switch(this.w&&(currentColorFlags|=colorFlags.W),this.u&&(currentColorFlags|=colorFlags.U),this.b&&(currentColorFlags|=colorFlags.B),this.r&&(currentColorFlags|=colorFlags.R),this.g&&(currentColorFlags|=colorFlags.G),currentColorFlags=32{allFormats_1.default[name].bannedTitleIds.includes(card.TitleId)&&banned.push(name)}),banned}},{"./allFormats":1}],6:[function(require,module,exports){var __importDefault=this&&this.__importDefault||function(mod){return mod&&mod.__esModule?mod:{default:mod}};Object.defineProperty(exports,"__esModule",{value:!0});let allFormats_1=__importDefault(require("./allFormats")),findSetByCode_1=__importDefault(require("./findSetByCode"));exports.default=function(card,allCards,setNames,sets){let allowed=[],arenaSetCode=[card.Set.toLowerCase()];return card.DigitalSet&&arenaSetCode.push(card.DigitalSet.toLowerCase()),card.Reprints.forEach(cid=>{var cid=allCards[cid];cid&&(cid=(0,findSetByCode_1.default)(null===cid.DigitalSet||""===cid.DigitalSet?cid.Set:cid.DigitalSet,setNames,sets))&&arenaSetCode.push(cid.arenacode)}),Object.keys(allFormats_1.default).forEach(name=>{var format=allFormats_1.default[name];!format.allowedTitleIds.includes(card.TitleId)&&!format.legalSets.some(set=>0<=arenaSetCode.indexOf(set.toLowerCase()))||format.bannedTitleIds.includes(card.TitleId)||("Pauper"!=name&&"HistoricPauper"!=name||"common"==card.Rarity)&&allowed.push(name)}),allowed}},{"./allFormats":1,"./findSetByCode":4}],7:[function(require,module,exports){var __importDefault=this&&this.__importDefault||function(mod){return mod&&mod.__esModule?mod:{default:mod}};Object.defineProperty(exports,"__esModule",{value:!0});let findSetByCode_1=__importDefault(require("./findSetByCode"));exports.default=function(card,setNames,sets){return setNames=(0,findSetByCode_1.default)(null===card.DigitalSet||""===card.DigitalSet?card.Set:card.DigitalSet,setNames,sets),!card.IsToken&&-1!==(null==setNames?void 0:setNames.collation)&&11!==card.LinkedFaceType&&!!card.IsPrimaryCard}},{"./findSetByCode":4}],8:[function(require,module,exports){var __importDefault=this&&this.__importDefault||function(mod){return mod&&mod.__esModule?mod:{default:mod}};Object.defineProperty(exports,"__esModule",{value:!0});let getCardFormats_1=__importDefault(require("./getCardFormats"));exports.default=function(card,cards,setNames,sets){return!("land"===card.Rarity||!card.IsToken||11===card.LinkedFaceType||!((card=(0,getCardFormats_1.default)(card,cards,setNames,sets)).includes("Standard")||card.includes("Historic")||card.includes("Alchemy")||card.includes("Explorer")||card.includes("Timeless")||card.includes("Singleton")))}},{"./getCardFormats":6}],9:[function(require,module,exports){var __importDefault=this&&this.__importDefault||function(mod){return mod&&mod.__esModule?mod:{default:mod}};Object.defineProperty(exports,"__esModule",{value:!0});let allFormats_1=__importDefault(require("./allFormats"));exports.default=function(card){let suspended=[];return Object.keys(allFormats_1.default).forEach(name=>{allFormats_1.default[name].suspendedTitleIds.includes(card.TitleId)&&suspended.push(name)}),suspended}},{"./allFormats":1}],10:[function(require,module,exports){var __importDefault=this&&this.__importDefault||function(mod){return mod&&mod.__esModule?mod:{default:mod}};Object.defineProperty(exports,"__esModule",{value:!0});let colors_1=__importDefault(require("./colors")),getCardBanned_1=__importDefault(require("./getCardBanned")),getCardFormats_1=__importDefault(require("./getCardFormats")),getCardInBoosters_1=__importDefault(require("./getCardInBoosters")),getCardIsCraftable_1=__importDefault(require("./getCardIsCraftable")),getCardSuspended_1=__importDefault(require("./getCardSuspended")),getRarityFilterVal_1=__importDefault(require("./getRarityFilterVal")),DRAFT_RANKS=["F","D-","D","D+","C-","C","C+","B-","B","B+","A-","A","A+"],DRAFT_RANKS_LOLA=["","A+","A","A-","B+","B","B-","C+","C","C-","D+","D","D-","F"],FACE_SPECIALIZE_BACK=11,FACE_ADVENTURE=7,FACE_MODAL_BACK=9,FACE_DFC_BACK=1,FACE_SPLIT=5;exports.default=function(cards,cardsList,allCards,setNames,sets){return cardsList.filter(card=>card.LinkedFaceType!==FACE_DFC_BACK&&3!==card.LinkedFaceType&&card.LinkedFaceType!==FACE_ADVENTURE&&card.LinkedFaceType!==FACE_SPLIT&&card.LinkedFaceType!==FACE_MODAL_BACK&&card.LinkedFaceType!==FACE_SPECIALIZE_BACK).map(card=>{var RANK_SOURCE=0==card.RankData.rankSource?DRAFT_RANKS:DRAFT_RANKS_LOLA,dfc=allCards[0 { } }; -},{"./addHost":1,"./addKeyListener":2,"./constants":4,"./doFunction":5,"./exploreAggregation":6,"./getConnectionData":7,"./getCrdt":8,"./getData":9,"./getDataLocal":10,"./getMatchesData":11,"./getSaveKeysJson":13,"./handleMatchesIndex":16,"./keysLogin":17,"./login":18,"./pushToExplore":19,"./pushToLivefeed":20,"./queryKeys":21,"./reduxAction":22,"./removeHost":23,"./setPassword":24,"./signup":25,"mtgatool-db":304}],27:[function(require,module,exports){ +},{"./addHost":1,"./addKeyListener":2,"./constants":4,"./doFunction":5,"./exploreAggregation":6,"./getConnectionData":7,"./getCrdt":8,"./getData":9,"./getDataLocal":10,"./getMatchesData":11,"./getSaveKeysJson":13,"./handleMatchesIndex":16,"./keysLogin":17,"./login":18,"./pushToExplore":19,"./pushToLivefeed":20,"./queryKeys":21,"./reduxAction":22,"./removeHost":23,"./setPassword":24,"./signup":25,"mtgatool-db":262}],27:[function(require,module,exports){ 'use strict' const emptyOptions = Object.freeze({}) @@ -1712,7 +1712,7 @@ function maybeError (db, callback) { return false } -},{"./abstract-chained-batch":27,"./abstract-iterator":28,"./lib/common":31,"./next-tick":32,"catering":159,"is-buffer":259,"level-supports":290}],30:[function(require,module,exports){ +},{"./abstract-chained-batch":27,"./abstract-iterator":28,"./lib/common":31,"./next-tick":32,"catering":122,"is-buffer":33,"level-supports":233}],30:[function(require,module,exports){ 'use strict' exports.AbstractLevelDOWN = require('./abstract-leveldown') @@ -1743,10 +1743,21 @@ module.exports = function (fn, ...args) { } } -},{"queue-microtask":399}],33:[function(require,module,exports){ -'use strict'; +},{"queue-microtask":357}],33:[function(require,module,exports){ +/*! + * Determine if an object is a Buffer + * + * @author Feross Aboukhadijeh + * @license MIT + */ + +module.exports = function isBuffer (obj) { + return obj != null && obj.constructor != null && + typeof obj.constructor.isBuffer === 'function' && obj.constructor.isBuffer(obj) +} -const asn1 = exports; +},{}],34:[function(require,module,exports){ +var asn1 = exports; asn1.bignum = require('bn.js'); @@ -1756,14 +1767,11 @@ asn1.constants = require('./asn1/constants'); asn1.decoders = require('./asn1/decoders'); asn1.encoders = require('./asn1/encoders'); -},{"./asn1/api":34,"./asn1/base":36,"./asn1/constants":40,"./asn1/decoders":42,"./asn1/encoders":45,"bn.js":47}],34:[function(require,module,exports){ -'use strict'; - -const encoders = require('./encoders'); -const decoders = require('./decoders'); -const inherits = require('inherits'); +},{"./asn1/api":35,"./asn1/base":37,"./asn1/constants":41,"./asn1/decoders":43,"./asn1/encoders":46,"bn.js":86}],35:[function(require,module,exports){ +var asn1 = require('../asn1'); +var inherits = require('inherits'); -const api = exports; +var api = exports; api.define = function define(name, body) { return new Entity(name, body); @@ -1775,27 +1783,34 @@ function Entity(name, body) { this.decoders = {}; this.encoders = {}; -} - -Entity.prototype._createNamed = function createNamed(Base) { - const name = this.name; +}; - function Generated(entity) { - this._initNamed(entity, name); +Entity.prototype._createNamed = function createNamed(base) { + var named; + try { + named = require('vm').runInThisContext( + '(function ' + this.name + '(entity) {\n' + + ' this._initNamed(entity);\n' + + '})' + ); + } catch (e) { + named = function (entity) { + this._initNamed(entity); + }; } - inherits(Generated, Base); - Generated.prototype._initNamed = function _initNamed(entity, name) { - Base.call(this, entity, name); + inherits(named, base); + named.prototype._initNamed = function initnamed(entity) { + base.call(this, entity); }; - return new Generated(this); + return new named(this); }; Entity.prototype._getDecoder = function _getDecoder(enc) { enc = enc || 'der'; // Lazily create decoder if (!this.decoders.hasOwnProperty(enc)) - this.decoders[enc] = this._createNamed(decoders[enc]); + this.decoders[enc] = this._createNamed(asn1.decoders[enc]); return this.decoders[enc]; }; @@ -1807,7 +1822,7 @@ Entity.prototype._getEncoder = function _getEncoder(enc) { enc = enc || 'der'; // Lazily create encoder if (!this.encoders.hasOwnProperty(enc)) - this.encoders[enc] = this._createNamed(encoders[enc]); + this.encoders[enc] = this._createNamed(asn1.encoders[enc]); return this.encoders[enc]; }; @@ -1815,12 +1830,10 @@ Entity.prototype.encode = function encode(data, enc, /* internal */ reporter) { return this._getEncoder(enc).encode(data, reporter); }; -},{"./decoders":42,"./encoders":45,"inherits":256}],35:[function(require,module,exports){ -'use strict'; - -const inherits = require('inherits'); -const Reporter = require('../base/reporter').Reporter; -const Buffer = require('safer-buffer').Buffer; +},{"../asn1":34,"inherits":200,"vm":426}],36:[function(require,module,exports){ +var inherits = require('inherits'); +var Reporter = require('../base').Reporter; +var Buffer = require('buffer').Buffer; function DecoderBuffer(base, options) { Reporter.call(this, options); @@ -1836,34 +1849,13 @@ function DecoderBuffer(base, options) { inherits(DecoderBuffer, Reporter); exports.DecoderBuffer = DecoderBuffer; -DecoderBuffer.isDecoderBuffer = function isDecoderBuffer(data) { - if (data instanceof DecoderBuffer) { - return true; - } - - // Or accept compatible API - const isCompatible = typeof data === 'object' && - Buffer.isBuffer(data.base) && - data.constructor.name === 'DecoderBuffer' && - typeof data.offset === 'number' && - typeof data.length === 'number' && - typeof data.save === 'function' && - typeof data.restore === 'function' && - typeof data.isEmpty === 'function' && - typeof data.readUInt8 === 'function' && - typeof data.skip === 'function' && - typeof data.raw === 'function'; - - return isCompatible; -}; - DecoderBuffer.prototype.save = function save() { return { offset: this.offset, reporter: Reporter.prototype.save.call(this) }; }; DecoderBuffer.prototype.restore = function restore(save) { // Return skipped data - const res = new DecoderBuffer(this.base); + var res = new DecoderBuffer(this.base); res.offset = save.offset; res.length = this.offset; @@ -1882,13 +1874,13 @@ DecoderBuffer.prototype.readUInt8 = function readUInt8(fail) { return this.base.readUInt8(this.offset++, true); else return this.error(fail || 'DecoderBuffer overrun'); -}; +} DecoderBuffer.prototype.skip = function skip(bytes, fail) { if (!(this.offset + bytes <= this.length)) return this.error(fail || 'DecoderBuffer overrun'); - const res = new DecoderBuffer(this.base); + var res = new DecoderBuffer(this.base); // Share reporter state res._reporterState = this._reporterState; @@ -1897,17 +1889,17 @@ DecoderBuffer.prototype.skip = function skip(bytes, fail) { res.length = this.offset + bytes; this.offset += bytes; return res; -}; +} DecoderBuffer.prototype.raw = function raw(save) { return this.base.slice(save ? save.offset : this.offset, this.length); -}; +} function EncoderBuffer(value, reporter) { if (Array.isArray(value)) { this.length = 0; this.value = value.map(function(item) { - if (!EncoderBuffer.isEncoderBuffer(item)) + if (!(item instanceof EncoderBuffer)) item = new EncoderBuffer(item, reporter); this.length += item.length; return item; @@ -1929,23 +1921,9 @@ function EncoderBuffer(value, reporter) { } exports.EncoderBuffer = EncoderBuffer; -EncoderBuffer.isEncoderBuffer = function isEncoderBuffer(data) { - if (data instanceof EncoderBuffer) { - return true; - } - - // Or accept compatible API - const isCompatible = typeof data === 'object' && - data.constructor.name === 'EncoderBuffer' && - typeof data.length === 'number' && - typeof data.join === 'function'; - - return isCompatible; -}; - EncoderBuffer.prototype.join = function join(out, offset) { if (!out) - out = Buffer.alloc(this.length); + out = new Buffer(this.length); if (!offset) offset = 0; @@ -1970,26 +1948,22 @@ EncoderBuffer.prototype.join = function join(out, offset) { return out; }; -},{"../base/reporter":38,"inherits":256,"safer-buffer":405}],36:[function(require,module,exports){ -'use strict'; - -const base = exports; +},{"../base":37,"buffer":118,"inherits":200}],37:[function(require,module,exports){ +var base = exports; base.Reporter = require('./reporter').Reporter; base.DecoderBuffer = require('./buffer').DecoderBuffer; base.EncoderBuffer = require('./buffer').EncoderBuffer; base.Node = require('./node'); -},{"./buffer":35,"./node":37,"./reporter":38}],37:[function(require,module,exports){ -'use strict'; - -const Reporter = require('../base/reporter').Reporter; -const EncoderBuffer = require('../base/buffer').EncoderBuffer; -const DecoderBuffer = require('../base/buffer').DecoderBuffer; -const assert = require('minimalistic-assert'); +},{"./buffer":36,"./node":38,"./reporter":39}],38:[function(require,module,exports){ +var Reporter = require('../base').Reporter; +var EncoderBuffer = require('../base').EncoderBuffer; +var DecoderBuffer = require('../base').DecoderBuffer; +var assert = require('minimalistic-assert'); // Supported tags -const tags = [ +var tags = [ 'seq', 'seqof', 'set', 'setof', 'objid', 'bool', 'gentime', 'utctime', 'null_', 'enum', 'int', 'objDesc', 'bitstr', 'bmpstr', 'charstr', 'genstr', 'graphstr', 'ia5str', 'iso646str', @@ -1997,13 +1971,13 @@ const tags = [ ]; // Public methods list -const methods = [ +var methods = [ 'key', 'obj', 'use', 'optional', 'explicit', 'implicit', 'def', 'choice', 'any', 'contains' ].concat(tags); // Overrided methods list -const overrided = [ +var overrided = [ '_peekTag', '_decodeTag', '_use', '_decodeStr', '_decodeObjid', '_decodeTime', '_decodeNull', '_decodeInt', '_decodeBool', '_decodeList', @@ -2012,11 +1986,10 @@ const overrided = [ '_encodeNull', '_encodeInt', '_encodeBool' ]; -function Node(enc, parent, name) { - const state = {}; +function Node(enc, parent) { + var state = {}; this._baseState = state; - state.name = name; state.enc = enc; state.parent = parent || null; @@ -2046,28 +2019,28 @@ function Node(enc, parent, name) { } module.exports = Node; -const stateProps = [ +var stateProps = [ 'enc', 'parent', 'children', 'tag', 'args', 'reverseArgs', 'choice', 'optional', 'any', 'obj', 'use', 'alteredUse', 'key', 'default', 'explicit', 'implicit', 'contains' ]; Node.prototype.clone = function clone() { - const state = this._baseState; - const cstate = {}; + var state = this._baseState; + var cstate = {}; stateProps.forEach(function(prop) { cstate[prop] = state[prop]; }); - const res = new this.constructor(cstate.parent); + var res = new this.constructor(cstate.parent); res._baseState = cstate; return res; }; Node.prototype._wrap = function wrap() { - const state = this._baseState; + var state = this._baseState; methods.forEach(function(method) { this[method] = function _wrappedMethod() { - const clone = new this.constructor(this); + var clone = new this.constructor(this); state.children.push(clone); return clone[method].apply(clone, arguments); }; @@ -2075,7 +2048,7 @@ Node.prototype._wrap = function wrap() { }; Node.prototype._init = function init(body) { - const state = this._baseState; + var state = this._baseState; assert(state.parent === null); body.call(this); @@ -2088,10 +2061,10 @@ Node.prototype._init = function init(body) { }; Node.prototype._useArgs = function useArgs(args) { - const state = this._baseState; + var state = this._baseState; // Filter children and args - const children = args.filter(function(arg) { + var children = args.filter(function(arg) { return arg instanceof this.constructor; }, this); args = args.filter(function(arg) { @@ -2114,11 +2087,11 @@ Node.prototype._useArgs = function useArgs(args) { if (typeof arg !== 'object' || arg.constructor !== Object) return arg; - const res = {}; + var res = {}; Object.keys(arg).forEach(function(key) { if (key == (key | 0)) key |= 0; - const value = arg[key]; + var value = arg[key]; res[value] = key; }); return res; @@ -2132,7 +2105,7 @@ Node.prototype._useArgs = function useArgs(args) { overrided.forEach(function(method) { Node.prototype[method] = function _overrided() { - const state = this._baseState; + var state = this._baseState; throw new Error(method + ' not implemented for encoding: ' + state.enc); }; }); @@ -2143,8 +2116,8 @@ overrided.forEach(function(method) { tags.forEach(function(tag) { Node.prototype[tag] = function _tagMethod() { - const state = this._baseState; - const args = Array.prototype.slice.call(arguments); + var state = this._baseState; + var args = Array.prototype.slice.call(arguments); assert(state.tag === null); state.tag = tag; @@ -2157,7 +2130,7 @@ tags.forEach(function(tag) { Node.prototype.use = function use(item) { assert(item); - const state = this._baseState; + var state = this._baseState; assert(state.use === null); state.use = item; @@ -2166,7 +2139,7 @@ Node.prototype.use = function use(item) { }; Node.prototype.optional = function optional() { - const state = this._baseState; + var state = this._baseState; state.optional = true; @@ -2174,7 +2147,7 @@ Node.prototype.optional = function optional() { }; Node.prototype.def = function def(val) { - const state = this._baseState; + var state = this._baseState; assert(state['default'] === null); state['default'] = val; @@ -2184,7 +2157,7 @@ Node.prototype.def = function def(val) { }; Node.prototype.explicit = function explicit(num) { - const state = this._baseState; + var state = this._baseState; assert(state.explicit === null && state.implicit === null); state.explicit = num; @@ -2193,7 +2166,7 @@ Node.prototype.explicit = function explicit(num) { }; Node.prototype.implicit = function implicit(num) { - const state = this._baseState; + var state = this._baseState; assert(state.explicit === null && state.implicit === null); state.implicit = num; @@ -2202,8 +2175,8 @@ Node.prototype.implicit = function implicit(num) { }; Node.prototype.obj = function obj() { - const state = this._baseState; - const args = Array.prototype.slice.call(arguments); + var state = this._baseState; + var args = Array.prototype.slice.call(arguments); state.obj = true; @@ -2214,7 +2187,7 @@ Node.prototype.obj = function obj() { }; Node.prototype.key = function key(newKey) { - const state = this._baseState; + var state = this._baseState; assert(state.key === null); state.key = newKey; @@ -2223,7 +2196,7 @@ Node.prototype.key = function key(newKey) { }; Node.prototype.any = function any() { - const state = this._baseState; + var state = this._baseState; state.any = true; @@ -2231,7 +2204,7 @@ Node.prototype.any = function any() { }; Node.prototype.choice = function choice(obj) { - const state = this._baseState; + var state = this._baseState; assert(state.choice === null); state.choice = obj; @@ -2243,7 +2216,7 @@ Node.prototype.choice = function choice(obj) { }; Node.prototype.contains = function contains(item) { - const state = this._baseState; + var state = this._baseState; assert(state.use === null); state.contains = item; @@ -2256,22 +2229,22 @@ Node.prototype.contains = function contains(item) { // Node.prototype._decode = function decode(input, options) { - const state = this._baseState; + var state = this._baseState; // Decode root node if (state.parent === null) return input.wrapResult(state.children[0]._decode(input, options)); - let result = state['default']; - let present = true; + var result = state['default']; + var present = true; - let prevKey = null; + var prevKey = null; if (state.key !== null) prevKey = input.enterKey(state.key); // Check if tag is there if (state.optional) { - let tag = null; + var tag = null; if (state.explicit !== null) tag = state.explicit; else if (state.implicit !== null) @@ -2281,7 +2254,7 @@ Node.prototype._decode = function decode(input, options) { if (tag === null && !state.any) { // Trial and Error - const save = input.save(); + var save = input.save(); try { if (state.choice === null) this._decodeGeneric(state.tag, input, options); @@ -2301,27 +2274,26 @@ Node.prototype._decode = function decode(input, options) { } // Push object on stack - let prevObj; + var prevObj; if (state.obj && present) prevObj = input.enterObject(); if (present) { // Unwrap explicit values if (state.explicit !== null) { - const explicit = this._decodeTag(input, state.explicit); + var explicit = this._decodeTag(input, state.explicit); if (input.isError(explicit)) return explicit; input = explicit; } - const start = input.offset; + var start = input.offset; // Unwrap implicit and normal values if (state.use === null && state.choice === null) { - let save; if (state.any) - save = input.save(); - const body = this._decodeTag( + var save = input.save(); + var body = this._decodeTag( input, state.implicit !== null ? state.implicit : state.tag, state.any @@ -2342,13 +2314,12 @@ Node.prototype._decode = function decode(input, options) { options.track(input.path(), input.offset, input.length, 'content'); // Select proper method for tag - if (state.any) { - // no-op - } else if (state.choice === null) { + if (state.any) + result = result; + else if (state.choice === null) result = this._decodeGeneric(state.tag, input, options); - } else { + else result = this._decodeChoice(input, options); - } if (input.isError(result)) return result; @@ -2364,9 +2335,9 @@ Node.prototype._decode = function decode(input, options) { // Decode contained/encoded by schema, only in bit or octet strings if (state.contains && (state.tag === 'octstr' || state.tag === 'bitstr')) { - const data = new DecoderBuffer(result); + var data = new DecoderBuffer(result); result = this._getUse(state.contains, input._reporterState.obj) - ._decode(data, options); + ._decode(data, options); } } @@ -2384,7 +2355,7 @@ Node.prototype._decode = function decode(input, options) { }; Node.prototype._decodeGeneric = function decodeGeneric(tag, input, options) { - const state = this._baseState; + var state = this._baseState; if (tag === 'seq' || tag === 'set') return null; @@ -2409,7 +2380,7 @@ Node.prototype._decodeGeneric = function decodeGeneric(tag, input, options) { if (state.use !== null) { return this._getUse(state.use, input._reporterState.obj) - ._decode(input, options); + ._decode(input, options); } else { return input.error('unknown tag: ' + tag); } @@ -2417,7 +2388,7 @@ Node.prototype._decodeGeneric = function decodeGeneric(tag, input, options) { Node.prototype._getUse = function _getUse(entity, obj) { - const state = this._baseState; + var state = this._baseState; // Create altered use decoder if implicit is set state.useDecoder = this._use(entity, obj); assert(state.useDecoder._baseState.parent === null); @@ -2430,15 +2401,15 @@ Node.prototype._getUse = function _getUse(entity, obj) { }; Node.prototype._decodeChoice = function decodeChoice(input, options) { - const state = this._baseState; - let result = null; - let match = false; + var state = this._baseState; + var result = null; + var match = false; Object.keys(state.choice).some(function(key) { - const save = input.save(); - const node = state.choice[key]; + var save = input.save(); + var node = state.choice[key]; try { - const value = node._decode(input, options); + var value = node._decode(input, options); if (input.isError(value)) return false; @@ -2466,11 +2437,11 @@ Node.prototype._createEncoderBuffer = function createEncoderBuffer(data) { }; Node.prototype._encode = function encode(data, reporter, parent) { - const state = this._baseState; + var state = this._baseState; if (state['default'] !== null && state['default'] === data) return; - const result = this._encodeValue(data, reporter, parent); + var result = this._encodeValue(data, reporter, parent); if (result === undefined) return; @@ -2481,13 +2452,13 @@ Node.prototype._encode = function encode(data, reporter, parent) { }; Node.prototype._encodeValue = function encode(data, reporter, parent) { - const state = this._baseState; + var state = this._baseState; // Decode root node if (state.parent === null) return state.children[0]._encode(data, reporter || new Reporter()); - let result = null; + var result = null; // Set reporter to share it with a child class this.reporter = reporter; @@ -2495,14 +2466,14 @@ Node.prototype._encodeValue = function encode(data, reporter, parent) { // Check if data is there if (state.optional && data === undefined) { if (state['default'] !== null) - data = state['default']; + data = state['default'] else return; } // Encode children first - let content = null; - let primitive = false; + var content = null; + var primitive = false; if (state.any) { // Anything that was given is translated to buffer result = this._createEncoderBuffer(data); @@ -2518,12 +2489,12 @@ Node.prototype._encodeValue = function encode(data, reporter, parent) { if (child._baseState.key === null) return reporter.error('Child should have a key'); - const prevKey = reporter.enterKey(child._baseState.key); + var prevKey = reporter.enterKey(child._baseState.key); if (typeof data !== 'object') return reporter.error('Child expected, but input is not object'); - const res = child._encode(data[child._baseState.key], reporter, data); + var res = child._encode(data[child._baseState.key], reporter, data); reporter.leaveKey(prevKey); return res; @@ -2540,10 +2511,10 @@ Node.prototype._encodeValue = function encode(data, reporter, parent) { if (!Array.isArray(data)) return reporter.error('seqof/setof, but data is not Array'); - const child = this.clone(); + var child = this.clone(); child._baseState.implicit = null; content = this._createEncoderBuffer(data.map(function(item) { - const state = this._baseState; + var state = this._baseState; return this._getUse(state.args[0], data)._encode(item, reporter); }, child)); @@ -2556,9 +2527,10 @@ Node.prototype._encodeValue = function encode(data, reporter, parent) { } // Encode data itself + var result; if (!state.any && state.choice === null) { - const tag = state.implicit !== null ? state.implicit : state.tag; - const cls = state.implicit === null ? 'universal' : 'context'; + var tag = state.implicit !== null ? state.implicit : state.tag; + var cls = state.implicit === null ? 'universal' : 'context'; if (tag === null) { if (state.use === null) @@ -2577,20 +2549,20 @@ Node.prototype._encodeValue = function encode(data, reporter, parent) { }; Node.prototype._encodeChoice = function encodeChoice(data, reporter) { - const state = this._baseState; + var state = this._baseState; - const node = state.choice[data.type]; + var node = state.choice[data.type]; if (!node) { assert( - false, - data.type + ' not found in ' + + false, + data.type + ' not found in ' + JSON.stringify(Object.keys(state.choice))); } return node._encode(data.value, reporter); }; Node.prototype._encodePrimitive = function encodePrimitive(tag, data) { - const state = this._baseState; + var state = this._baseState; if (/str$/.test(tag)) return this._encodeStr(data, tag); @@ -2617,13 +2589,11 @@ Node.prototype._isNumstr = function isNumstr(str) { }; Node.prototype._isPrintstr = function isPrintstr(str) { - return /^[A-Za-z0-9 '()+,-./:=?]*$/.test(str); + return /^[A-Za-z0-9 '\(\)\+,\-\.\/:=\?]*$/.test(str); }; -},{"../base/buffer":35,"../base/reporter":38,"minimalistic-assert":301}],38:[function(require,module,exports){ -'use strict'; - -const inherits = require('inherits'); +},{"../base":37,"minimalistic-assert":259}],39:[function(require,module,exports){ +var inherits = require('inherits'); function Reporter(options) { this._reporterState = { @@ -2640,13 +2610,13 @@ Reporter.prototype.isError = function isError(obj) { }; Reporter.prototype.save = function save() { - const state = this._reporterState; + var state = this._reporterState; return { obj: state.obj, pathLen: state.path.length }; }; Reporter.prototype.restore = function restore(data) { - const state = this._reporterState; + var state = this._reporterState; state.obj = data.obj; state.path = state.path.slice(0, data.pathLen); @@ -2657,13 +2627,13 @@ Reporter.prototype.enterKey = function enterKey(key) { }; Reporter.prototype.exitKey = function exitKey(index) { - const state = this._reporterState; + var state = this._reporterState; state.path = state.path.slice(0, index - 1); }; Reporter.prototype.leaveKey = function leaveKey(index, key, value) { - const state = this._reporterState; + var state = this._reporterState; this.exitKey(index); if (state.obj !== null) @@ -2675,26 +2645,26 @@ Reporter.prototype.path = function path() { }; Reporter.prototype.enterObject = function enterObject() { - const state = this._reporterState; + var state = this._reporterState; - const prev = state.obj; + var prev = state.obj; state.obj = {}; return prev; }; Reporter.prototype.leaveObject = function leaveObject(prev) { - const state = this._reporterState; + var state = this._reporterState; - const now = state.obj; + var now = state.obj; state.obj = prev; return now; }; Reporter.prototype.error = function error(msg) { - let err; - const state = this._reporterState; + var err; + var state = this._reporterState; - const inherited = msg instanceof ReporterError; + var inherited = msg instanceof ReporterError; if (inherited) { err = msg; } else { @@ -2713,7 +2683,7 @@ Reporter.prototype.error = function error(msg) { }; Reporter.prototype.wrapResult = function wrapResult(result) { - const state = this._reporterState; + var state = this._reporterState; if (!state.options.partial) return result; @@ -2726,7 +2696,7 @@ Reporter.prototype.wrapResult = function wrapResult(result) { function ReporterError(path, msg) { this.path = path; this.rethrow(msg); -} +}; inherits(ReporterError, Error); ReporterError.prototype.rethrow = function rethrow(msg) { @@ -2745,24 +2715,8 @@ ReporterError.prototype.rethrow = function rethrow(msg) { return this; }; -},{"inherits":256}],39:[function(require,module,exports){ -'use strict'; - -// Helper -function reverse(map) { - const res = {}; - - Object.keys(map).forEach(function(key) { - // Convert key to integer if it is stringified - if ((key | 0) == key) - key = key | 0; - - const value = map[key]; - res[value] = key; - }); - - return res; -} +},{"inherits":200}],40:[function(require,module,exports){ +var constants = require('../constants'); exports.tagClass = { 0: 'universal', @@ -2770,7 +2724,7 @@ exports.tagClass = { 2: 'context', 3: 'private' }; -exports.tagClassByName = reverse(exports.tagClass); +exports.tagClassByName = constants._reverse(exports.tagClass); exports.tag = { 0x00: 'end', @@ -2803,23 +2757,21 @@ exports.tag = { 0x1d: 'charstr', 0x1e: 'bmpstr' }; -exports.tagByName = reverse(exports.tag); - -},{}],40:[function(require,module,exports){ -'use strict'; +exports.tagByName = constants._reverse(exports.tag); -const constants = exports; +},{"../constants":41}],41:[function(require,module,exports){ +var constants = exports; // Helper constants._reverse = function reverse(map) { - const res = {}; + var res = {}; Object.keys(map).forEach(function(key) { // Convert key to integer if it is stringified if ((key | 0) == key) key = key | 0; - const value = map[key]; + var value = map[key]; res[value] = key; }); @@ -2828,17 +2780,15 @@ constants._reverse = function reverse(map) { constants.der = require('./der'); -},{"./der":39}],41:[function(require,module,exports){ -'use strict'; - -const inherits = require('inherits'); +},{"./der":40}],42:[function(require,module,exports){ +var inherits = require('inherits'); -const bignum = require('bn.js'); -const DecoderBuffer = require('../base/buffer').DecoderBuffer; -const Node = require('../base/node'); +var asn1 = require('../../asn1'); +var base = asn1.base; +var bignum = asn1.bignum; // Import DER constants -const der = require('../constants/der'); +var der = asn1.constants.der; function DERDecoder(entity) { this.enc = 'der'; @@ -2848,13 +2798,12 @@ function DERDecoder(entity) { // Construct base tree this.tree = new DERNode(); this.tree._init(entity.body); -} +}; module.exports = DERDecoder; DERDecoder.prototype.decode = function decode(data, options) { - if (!DecoderBuffer.isDecoderBuffer(data)) { - data = new DecoderBuffer(data, options); - } + if (!(data instanceof base.DecoderBuffer)) + data = new base.DecoderBuffer(data, options); return this.tree._decode(data, options); }; @@ -2862,16 +2811,16 @@ DERDecoder.prototype.decode = function decode(data, options) { // Tree methods function DERNode(parent) { - Node.call(this, 'der', parent); + base.Node.call(this, 'der', parent); } -inherits(DERNode, Node); +inherits(DERNode, base.Node); DERNode.prototype._peekTag = function peekTag(buffer, tag, any) { if (buffer.isEmpty()) return false; - const state = buffer.save(); - const decodedTag = derDecodeTag(buffer, 'Failed to peek tag: "' + tag + '"'); + var state = buffer.save(); + var decodedTag = derDecodeTag(buffer, 'Failed to peek tag: "' + tag + '"'); if (buffer.isError(decodedTag)) return decodedTag; @@ -2882,14 +2831,14 @@ DERNode.prototype._peekTag = function peekTag(buffer, tag, any) { }; DERNode.prototype._decodeTag = function decodeTag(buffer, tag, any) { - const decodedTag = derDecodeTag(buffer, - 'Failed to decode tag of "' + tag + '"'); + var decodedTag = derDecodeTag(buffer, + 'Failed to decode tag of "' + tag + '"'); if (buffer.isError(decodedTag)) return decodedTag; - let len = derDecodeLen(buffer, - decodedTag.primitive, - 'Failed to get length of "' + tag + '"'); + var len = derDecodeLen(buffer, + decodedTag.primitive, + 'Failed to get length of "' + tag + '"'); // Failure if (buffer.isError(len)) @@ -2906,10 +2855,10 @@ DERNode.prototype._decodeTag = function decodeTag(buffer, tag, any) { return buffer.skip(len, 'Failed to match body of: "' + tag + '"'); // Indefinite length... find END tag - const state = buffer.save(); - const res = this._skipUntilEnd( - buffer, - 'Failed to skip indefinite length body: "' + this.tag + '"'); + var state = buffer.save(); + var res = this._skipUntilEnd( + buffer, + 'Failed to skip indefinite length body: "' + this.tag + '"'); if (buffer.isError(res)) return res; @@ -2919,17 +2868,17 @@ DERNode.prototype._decodeTag = function decodeTag(buffer, tag, any) { }; DERNode.prototype._skipUntilEnd = function skipUntilEnd(buffer, fail) { - for (;;) { - const tag = derDecodeTag(buffer, fail); + while (true) { + var tag = derDecodeTag(buffer, fail); if (buffer.isError(tag)) return tag; - const len = derDecodeLen(buffer, tag.primitive, fail); + var len = derDecodeLen(buffer, tag.primitive, fail); if (buffer.isError(len)) return len; - let res; + var res; if (tag.primitive || len !== null) - res = buffer.skip(len); + res = buffer.skip(len) else res = this._skipUntilEnd(buffer, fail); @@ -2943,14 +2892,14 @@ DERNode.prototype._skipUntilEnd = function skipUntilEnd(buffer, fail) { }; DERNode.prototype._decodeList = function decodeList(buffer, tag, decoder, - options) { - const result = []; + options) { + var result = []; while (!buffer.isEmpty()) { - const possibleEnd = this._peekTag(buffer, 'end'); + var possibleEnd = this._peekTag(buffer, 'end'); if (buffer.isError(possibleEnd)) return possibleEnd; - const res = decoder.decode(buffer, 'der', options); + var res = decoder.decode(buffer, 'der', options); if (buffer.isError(res) && possibleEnd) break; result.push(res); @@ -2960,22 +2909,22 @@ DERNode.prototype._decodeList = function decodeList(buffer, tag, decoder, DERNode.prototype._decodeStr = function decodeStr(buffer, tag) { if (tag === 'bitstr') { - const unused = buffer.readUInt8(); + var unused = buffer.readUInt8(); if (buffer.isError(unused)) return unused; return { unused: unused, data: buffer.raw() }; } else if (tag === 'bmpstr') { - const raw = buffer.raw(); + var raw = buffer.raw(); if (raw.length % 2 === 1) return buffer.error('Decoding of string type: bmpstr length mismatch'); - let str = ''; - for (let i = 0; i < raw.length / 2; i++) { + var str = ''; + for (var i = 0; i < raw.length / 2; i++) { str += String.fromCharCode(raw.readUInt16BE(i * 2)); } return str; } else if (tag === 'numstr') { - const numstr = buffer.raw().toString('ascii'); + var numstr = buffer.raw().toString('ascii'); if (!this._isNumstr(numstr)) { return buffer.error('Decoding of string type: ' + 'numstr unsupported characters'); @@ -2986,7 +2935,7 @@ DERNode.prototype._decodeStr = function decodeStr(buffer, tag) { } else if (tag === 'objDesc') { return buffer.raw(); } else if (tag === 'printstr') { - const printstr = buffer.raw().toString('ascii'); + var printstr = buffer.raw().toString('ascii'); if (!this._isPrintstr(printstr)) { return buffer.error('Decoding of string type: ' + 'printstr unsupported characters'); @@ -3000,12 +2949,11 @@ DERNode.prototype._decodeStr = function decodeStr(buffer, tag) { }; DERNode.prototype._decodeObjid = function decodeObjid(buffer, values, relative) { - let result; - const identifiers = []; - let ident = 0; - let subident = 0; + var result; + var identifiers = []; + var ident = 0; while (!buffer.isEmpty()) { - subident = buffer.readUInt8(); + var subident = buffer.readUInt8(); ident <<= 7; ident |= subident & 0x7f; if ((subident & 0x80) === 0) { @@ -3016,8 +2964,8 @@ DERNode.prototype._decodeObjid = function decodeObjid(buffer, values, relative) if (subident & 0x80) identifiers.push(ident); - const first = (identifiers[0] / 40) | 0; - const second = identifiers[0] % 40; + var first = (identifiers[0] / 40) | 0; + var second = identifiers[0] % 40; if (relative) result = identifiers; @@ -3025,7 +2973,7 @@ DERNode.prototype._decodeObjid = function decodeObjid(buffer, values, relative) result = [first, second].concat(identifiers.slice(1)); if (values) { - let tmp = values[result.join(' ')]; + var tmp = values[result.join(' ')]; if (tmp === undefined) tmp = values[result.join('.')]; if (tmp !== undefined) @@ -3036,28 +2984,21 @@ DERNode.prototype._decodeObjid = function decodeObjid(buffer, values, relative) }; DERNode.prototype._decodeTime = function decodeTime(buffer, tag) { - const str = buffer.raw().toString(); - - let year; - let mon; - let day; - let hour; - let min; - let sec; + var str = buffer.raw().toString(); if (tag === 'gentime') { - year = str.slice(0, 4) | 0; - mon = str.slice(4, 6) | 0; - day = str.slice(6, 8) | 0; - hour = str.slice(8, 10) | 0; - min = str.slice(10, 12) | 0; - sec = str.slice(12, 14) | 0; + var year = str.slice(0, 4) | 0; + var mon = str.slice(4, 6) | 0; + var day = str.slice(6, 8) | 0; + var hour = str.slice(8, 10) | 0; + var min = str.slice(10, 12) | 0; + var sec = str.slice(12, 14) | 0; } else if (tag === 'utctime') { - year = str.slice(0, 2) | 0; - mon = str.slice(2, 4) | 0; - day = str.slice(4, 6) | 0; - hour = str.slice(6, 8) | 0; - min = str.slice(8, 10) | 0; - sec = str.slice(10, 12) | 0; + var year = str.slice(0, 2) | 0; + var mon = str.slice(2, 4) | 0; + var day = str.slice(4, 6) | 0; + var hour = str.slice(6, 8) | 0; + var min = str.slice(8, 10) | 0; + var sec = str.slice(10, 12) | 0; if (year < 70) year = 2000 + year; else @@ -3069,12 +3010,12 @@ DERNode.prototype._decodeTime = function decodeTime(buffer, tag) { return Date.UTC(year, mon - 1, day, hour, min, sec, 0); }; -DERNode.prototype._decodeNull = function decodeNull() { +DERNode.prototype._decodeNull = function decodeNull(buffer) { return null; }; DERNode.prototype._decodeBool = function decodeBool(buffer) { - const res = buffer.readUInt8(); + var res = buffer.readUInt8(); if (buffer.isError(res)) return res; else @@ -3083,8 +3024,8 @@ DERNode.prototype._decodeBool = function decodeBool(buffer) { DERNode.prototype._decodeInt = function decodeInt(buffer, values) { // Bigint, return as it is (assume big endian) - const raw = buffer.raw(); - let res = new bignum(raw); + var raw = buffer.raw(); + var res = new bignum(raw); if (values) res = values[res.toString(10)] || res; @@ -3101,16 +3042,16 @@ DERNode.prototype._use = function use(entity, obj) { // Utility methods function derDecodeTag(buf, fail) { - let tag = buf.readUInt8(fail); + var tag = buf.readUInt8(fail); if (buf.isError(tag)) return tag; - const cls = der.tagClass[tag >> 6]; - const primitive = (tag & 0x20) === 0; + var cls = der.tagClass[tag >> 6]; + var primitive = (tag & 0x20) === 0; // Multi-octet tag - load if ((tag & 0x1f) === 0x1f) { - let oct = tag; + var oct = tag; tag = 0; while ((oct & 0x80) === 0x80) { oct = buf.readUInt8(fail); @@ -3123,7 +3064,7 @@ function derDecodeTag(buf, fail) { } else { tag &= 0x1f; } - const tagStr = der.tag[tag]; + var tagStr = der.tag[tag]; return { cls: cls, @@ -3134,7 +3075,7 @@ function derDecodeTag(buf, fail) { } function derDecodeLen(buf, primitive, fail) { - let len = buf.readUInt8(fail); + var len = buf.readUInt8(fail); if (buf.isError(len)) return len; @@ -3149,14 +3090,14 @@ function derDecodeLen(buf, primitive, fail) { } // Long form - const num = len & 0x7f; + var num = len & 0x7f; if (num > 4) return buf.error('length octect is too long'); len = 0; - for (let i = 0; i < num; i++) { + for (var i = 0; i < num; i++) { len <<= 8; - const j = buf.readUInt8(fail); + var j = buf.readUInt8(fail); if (buf.isError(j)) return j; len |= j; @@ -3165,39 +3106,35 @@ function derDecodeLen(buf, primitive, fail) { return len; } -},{"../base/buffer":35,"../base/node":37,"../constants/der":39,"bn.js":47,"inherits":256}],42:[function(require,module,exports){ -'use strict'; - -const decoders = exports; +},{"../../asn1":34,"inherits":200}],43:[function(require,module,exports){ +var decoders = exports; decoders.der = require('./der'); decoders.pem = require('./pem'); -},{"./der":41,"./pem":43}],43:[function(require,module,exports){ -'use strict'; - -const inherits = require('inherits'); -const Buffer = require('safer-buffer').Buffer; +},{"./der":42,"./pem":44}],44:[function(require,module,exports){ +var inherits = require('inherits'); +var Buffer = require('buffer').Buffer; -const DERDecoder = require('./der'); +var DERDecoder = require('./der'); function PEMDecoder(entity) { DERDecoder.call(this, entity); this.enc = 'pem'; -} +}; inherits(PEMDecoder, DERDecoder); module.exports = PEMDecoder; PEMDecoder.prototype.decode = function decode(data, options) { - const lines = data.toString().split(/[\r\n]+/g); + var lines = data.toString().split(/[\r\n]+/g); - const label = options.label.toUpperCase(); + var label = options.label.toUpperCase(); - const re = /^-----(BEGIN|END) ([^-]+)-----$/; - let start = -1; - let end = -1; - for (let i = 0; i < lines.length; i++) { - const match = lines[i].match(re); + var re = /^-----(BEGIN|END) ([^-]+)-----$/; + var start = -1; + var end = -1; + for (var i = 0; i < lines.length; i++) { + var match = lines[i].match(re); if (match === null) continue; @@ -3218,23 +3155,23 @@ PEMDecoder.prototype.decode = function decode(data, options) { if (start === -1 || end === -1) throw new Error('PEM section not found for: ' + label); - const base64 = lines.slice(start + 1, end).join(''); + var base64 = lines.slice(start + 1, end).join(''); // Remove excessive symbols - base64.replace(/[^a-z0-9+/=]+/gi, ''); + base64.replace(/[^a-z0-9\+\/=]+/gi, ''); - const input = Buffer.from(base64, 'base64'); + var input = new Buffer(base64, 'base64'); return DERDecoder.prototype.decode.call(this, input, options); }; -},{"./der":41,"inherits":256,"safer-buffer":405}],44:[function(require,module,exports){ -'use strict'; +},{"./der":42,"buffer":118,"inherits":200}],45:[function(require,module,exports){ +var inherits = require('inherits'); +var Buffer = require('buffer').Buffer; -const inherits = require('inherits'); -const Buffer = require('safer-buffer').Buffer; -const Node = require('../base/node'); +var asn1 = require('../../asn1'); +var base = asn1.base; // Import DER constants -const der = require('../constants/der'); +var der = asn1.constants.der; function DEREncoder(entity) { this.enc = 'der'; @@ -3244,7 +3181,7 @@ function DEREncoder(entity) { // Construct base tree this.tree = new DERNode(); this.tree._init(entity.body); -} +}; module.exports = DEREncoder; DEREncoder.prototype.encode = function encode(data, reporter) { @@ -3254,19 +3191,19 @@ DEREncoder.prototype.encode = function encode(data, reporter) { // Tree methods function DERNode(parent) { - Node.call(this, 'der', parent); + base.Node.call(this, 'der', parent); } -inherits(DERNode, Node); +inherits(DERNode, base.Node); DERNode.prototype._encodeComposite = function encodeComposite(tag, - primitive, - cls, - content) { - const encodedTag = encodeTag(tag, primitive, cls, this.reporter); + primitive, + cls, + content) { + var encodedTag = encodeTag(tag, primitive, cls, this.reporter); // Short form if (content.length < 0x80) { - const header = Buffer.alloc(2); + var header = new Buffer(2); header[0] = encodedTag; header[1] = content.length; return this._createEncoderBuffer([ header, content ]); @@ -3274,15 +3211,15 @@ DERNode.prototype._encodeComposite = function encodeComposite(tag, // Long form // Count octets required to store length - let lenOctets = 1; - for (let i = content.length; i >= 0x100; i >>= 8) + var lenOctets = 1; + for (var i = content.length; i >= 0x100; i >>= 8) lenOctets++; - const header = Buffer.alloc(1 + 1 + lenOctets); + var header = new Buffer(1 + 1 + lenOctets); header[0] = encodedTag; header[1] = 0x80 | lenOctets; - for (let i = 1 + lenOctets, j = content.length; j > 0; i--, j >>= 8) + for (var i = 1 + lenOctets, j = content.length; j > 0; i--, j >>= 8) header[i] = j & 0xff; return this._createEncoderBuffer([ header, content ]); @@ -3292,8 +3229,8 @@ DERNode.prototype._encodeStr = function encodeStr(str, tag) { if (tag === 'bitstr') { return this._createEncoderBuffer([ str.unused | 0, str.data ]); } else if (tag === 'bmpstr') { - const buf = Buffer.alloc(str.length * 2); - for (let i = 0; i < str.length; i++) { + var buf = new Buffer(str.length * 2); + for (var i = 0; i < str.length; i++) { buf.writeUInt16BE(str.charCodeAt(i), i * 2); } return this._createEncoderBuffer(buf); @@ -3329,12 +3266,12 @@ DERNode.prototype._encodeObjid = function encodeObjid(id, values, relative) { return this.reporter.error('string objid given, but no values map found'); if (!values.hasOwnProperty(id)) return this.reporter.error('objid not found in values map'); - id = values[id].split(/[\s.]+/g); - for (let i = 0; i < id.length; i++) + id = values[id].split(/[\s\.]+/g); + for (var i = 0; i < id.length; i++) id[i] |= 0; } else if (Array.isArray(id)) { id = id.slice(); - for (let i = 0; i < id.length; i++) + for (var i = 0; i < id.length; i++) id[i] |= 0; } @@ -3350,17 +3287,17 @@ DERNode.prototype._encodeObjid = function encodeObjid(id, values, relative) { } // Count number of octets - let size = 0; - for (let i = 0; i < id.length; i++) { - let ident = id[i]; + var size = 0; + for (var i = 0; i < id.length; i++) { + var ident = id[i]; for (size++; ident >= 0x80; ident >>= 7) size++; } - const objid = Buffer.alloc(size); - let offset = objid.length - 1; - for (let i = id.length - 1; i >= 0; i--) { - let ident = id[i]; + var objid = new Buffer(size); + var offset = objid.length - 1; + for (var i = id.length - 1; i >= 0; i--) { + var ident = id[i]; objid[offset--] = ident & 0x7f; while ((ident >>= 7) > 0) objid[offset--] = 0x80 | (ident & 0x7f); @@ -3377,12 +3314,12 @@ function two(num) { } DERNode.prototype._encodeTime = function encodeTime(time, tag) { - let str; - const date = new Date(time); + var str; + var date = new Date(time); if (tag === 'gentime') { str = [ - two(date.getUTCFullYear()), + two(date.getFullYear()), two(date.getUTCMonth() + 1), two(date.getUTCDate()), two(date.getUTCHours()), @@ -3392,7 +3329,7 @@ DERNode.prototype._encodeTime = function encodeTime(time, tag) { ].join(''); } else if (tag === 'utctime') { str = [ - two(date.getUTCFullYear() % 100), + two(date.getFullYear() % 100), two(date.getUTCMonth() + 1), two(date.getUTCDate()), two(date.getUTCHours()), @@ -3424,22 +3361,22 @@ DERNode.prototype._encodeInt = function encodeInt(num, values) { // Bignum, assume big endian if (typeof num !== 'number' && !Buffer.isBuffer(num)) { - const numArray = num.toArray(); + var numArray = num.toArray(); if (!num.sign && numArray[0] & 0x80) { numArray.unshift(0); } - num = Buffer.from(numArray); + num = new Buffer(numArray); } if (Buffer.isBuffer(num)) { - let size = num.length; + var size = num.length; if (num.length === 0) size++; - const out = Buffer.alloc(size); + var out = new Buffer(size); num.copy(out); if (num.length === 0) - out[0] = 0; + out[0] = 0 return this._createEncoderBuffer(out); } @@ -3449,12 +3386,12 @@ DERNode.prototype._encodeInt = function encodeInt(num, values) { if (num < 0x100) return this._createEncoderBuffer([0, num]); - let size = 1; - for (let i = num; i >= 0x100; i >>= 8) + var size = 1; + for (var i = num; i >= 0x100; i >>= 8) size++; - const out = new Array(size); - for (let i = out.length - 1; i >= 0; i--) { + var out = new Array(size); + for (var i = out.length - 1; i >= 0; i--) { out[i] = num & 0xff; num >>= 8; } @@ -3462,7 +3399,7 @@ DERNode.prototype._encodeInt = function encodeInt(num, values) { out.unshift(0); } - return this._createEncoderBuffer(Buffer.from(out)); + return this._createEncoderBuffer(new Buffer(out)); }; DERNode.prototype._encodeBool = function encodeBool(value) { @@ -3476,12 +3413,12 @@ DERNode.prototype._use = function use(entity, obj) { }; DERNode.prototype._skipDefault = function skipDefault(dataBuffer, reporter, parent) { - const state = this._baseState; - let i; + var state = this._baseState; + var i; if (state['default'] === null) return false; - const data = dataBuffer.join(); + var data = dataBuffer.join(); if (state.defaultBuffer === undefined) state.defaultBuffer = this._encodeValue(state['default'], reporter, parent).join(); @@ -3498,7 +3435,7 @@ DERNode.prototype._skipDefault = function skipDefault(dataBuffer, reporter, pare // Utility methods function encodeTag(tag, primitive, cls, reporter) { - let res; + var res; if (tag === 'seqof') tag = 'seq'; @@ -3523,13878 +3460,14210 @@ function encodeTag(tag, primitive, cls, reporter) { return res; } -},{"../base/node":37,"../constants/der":39,"inherits":256,"safer-buffer":405}],45:[function(require,module,exports){ -'use strict'; - -const encoders = exports; +},{"../../asn1":34,"buffer":118,"inherits":200}],46:[function(require,module,exports){ +var encoders = exports; encoders.der = require('./der'); encoders.pem = require('./pem'); -},{"./der":44,"./pem":46}],46:[function(require,module,exports){ -'use strict'; - -const inherits = require('inherits'); +},{"./der":45,"./pem":47}],47:[function(require,module,exports){ +var inherits = require('inherits'); -const DEREncoder = require('./der'); +var DEREncoder = require('./der'); function PEMEncoder(entity) { DEREncoder.call(this, entity); this.enc = 'pem'; -} +}; inherits(PEMEncoder, DEREncoder); module.exports = PEMEncoder; PEMEncoder.prototype.encode = function encode(data, options) { - const buf = DEREncoder.prototype.encode.call(this, data); + var buf = DEREncoder.prototype.encode.call(this, data); - const p = buf.toString('base64'); - const out = [ '-----BEGIN ' + options.label + '-----' ]; - for (let i = 0; i < p.length; i += 64) + var p = buf.toString('base64'); + var out = [ '-----BEGIN ' + options.label + '-----' ]; + for (var i = 0; i < p.length; i += 64) out.push(p.slice(i, i + 64)); out.push('-----END ' + options.label + '-----'); return out.join('\n'); }; -},{"./der":44,"inherits":256}],47:[function(require,module,exports){ -(function (module, exports) { - 'use strict'; - - // Utils - function assert (val, msg) { - if (!val) throw new Error(msg || 'Assertion failed'); - } - - // Could use `inherits` module, but don't want to move from single file - // architecture yet. - function inherits (ctor, superCtor) { - ctor.super_ = superCtor; - var TempCtor = function () {}; - TempCtor.prototype = superCtor.prototype; - ctor.prototype = new TempCtor(); - ctor.prototype.constructor = ctor; - } - - // BN +},{"./der":45,"inherits":200}],48:[function(require,module,exports){ +const { encodeChange } = require('./columnar') +const { BackendDoc } = require('./new') +const { backendState } = require('./util') - function BN (number, base, endian) { - if (BN.isBN(number)) { - return number; - } +/** + * Returns an empty node state. + */ +function init() { + return {state: new BackendDoc(), heads: []} +} - this.negative = 0; - this.words = null; - this.length = 0; +function clone(backend) { + return {state: backendState(backend).clone(), heads: backend.heads} +} - // Reduction context - this.red = null; +function free(backend) { + backend.state = null + backend.frozen = true +} - if (number !== null) { - if (base === 'le' || base === 'be') { - endian = base; - base = 10; - } +/** + * Applies a list of `changes` from remote nodes to the node state `backend`. + * Returns a two-element array `[state, patch]` where `state` is the updated + * node state, and `patch` describes the modifications that need to be made + * to the document objects to reflect these changes. + */ +function applyChanges(backend, changes) { + const state = backendState(backend) + const patch = state.applyChanges(changes) + backend.frozen = true + return [{state, heads: state.heads}, patch] +} - this._init(number || 0, base || 10, endian || 'be'); - } +function hashByActor(state, actorId, index) { + if (state.hashesByActor[actorId] && state.hashesByActor[actorId][index]) { + return state.hashesByActor[actorId][index] } - if (typeof module === 'object') { - module.exports = BN; - } else { - exports.BN = BN; + if (!state.haveHashGraph) { + state.computeHashGraph() + if (state.hashesByActor[actorId] && state.hashesByActor[actorId][index]) { + return state.hashesByActor[actorId][index] + } } + throw new RangeError(`Unknown change: actorId = ${actorId}, seq = ${index + 1}`) +} - BN.BN = BN; - BN.wordSize = 26; +/** + * Takes a single change request `request` made by the local user, and applies + * it to the node state `backend`. Returns a three-element array `[backend, patch, binaryChange]` + * where `backend` is the updated node state,`patch` confirms the + * modifications to the document objects, and `binaryChange` is a binary-encoded form of + * the change submitted. + */ +function applyLocalChange(backend, change) { + const state = backendState(backend) + if (change.seq <= state.clock[change.actor] || 0) { + throw new RangeError('Change request has already been applied') + } - var Buffer; - try { - if (typeof window !== 'undefined' && typeof window.Buffer !== 'undefined') { - Buffer = window.Buffer; - } else { - Buffer = require('buffer').Buffer; + // Add the local actor's last change hash to deps. We do this because when frontend + // and backend are on separate threads, the frontend may fire off several local + // changes in sequence before getting a response from the backend; since the binary + // encoding and hashing is done by the backend, the frontend does not know the hash + // of its own last change in this case. Rather than handle this situation as a + // special case, we say that the frontend includes only specifies other actors' + // deps in changes it generates, and the dependency from the local actor's last + // change is always added here in the backend. + // + // Strictly speaking, we should check whether the local actor's last change is + // indirectly reachable through a different actor's change; in that case, it is not + // necessary to add this dependency. However, it doesn't do any harm either (only + // using a few extra bytes of storage). + if (change.seq > 1) { + const lastHash = hashByActor(state, change.actor, change.seq - 2) + if (!lastHash) { + throw new RangeError(`Cannot find hash of localChange before seq=${change.seq}`) } - } catch (e) { + let deps = {[lastHash]: true} + for (let hash of change.deps) deps[hash] = true + change.deps = Object.keys(deps).sort() } - BN.isBN = function isBN (num) { - if (num instanceof BN) { - return true; - } + const binaryChange = encodeChange(change) + const patch = state.applyChanges([binaryChange], true) + backend.frozen = true - return num !== null && typeof num === 'object' && - num.constructor.wordSize === BN.wordSize && Array.isArray(num.words); - }; + // On the patch we send out, omit the last local change hash + const lastHash = hashByActor(state, change.actor, change.seq - 1) + patch.deps = patch.deps.filter(head => head !== lastHash) + return [{state, heads: state.heads}, patch, binaryChange] +} - BN.max = function max (left, right) { - if (left.cmp(right) > 0) return left; - return right; - }; +/** + * Returns the state of the document serialised to an Uint8Array. + */ +function save(backend) { + return backendState(backend).save() +} - BN.min = function min (left, right) { - if (left.cmp(right) < 0) return left; - return right; - }; +/** + * Loads the document and/or changes contained in an Uint8Array, and returns a + * backend initialised with this state. + */ +function load(data) { + const state = new BackendDoc(data) + return {state, heads: state.heads} +} - BN.prototype._init = function init (number, base, endian) { - if (typeof number === 'number') { - return this._initNumber(number, base, endian); - } +/** + * Applies a list of `changes` to the node state `backend`, and returns the updated + * state with those changes incorporated. Unlike `applyChanges()`, this function + * does not produce a patch describing the incremental modifications, making it + * a little faster when loading a document from disk. When all the changes have + * been loaded, you can use `getPatch()` to construct the latest document state. + */ +function loadChanges(backend, changes) { + const state = backendState(backend) + state.applyChanges(changes) + backend.frozen = true + return {state, heads: state.heads} +} - if (typeof number === 'object') { - return this._initArray(number, base, endian); - } +/** + * Returns a patch that, when applied to an empty document, constructs the + * document tree in the state described by the node state `backend`. + */ +function getPatch(backend) { + return backendState(backend).getPatch() +} - if (base === 'hex') { - base = 16; - } - assert(base === (base | 0) && base >= 2 && base <= 36); +/** + * Returns an array of hashes of the current "head" changes (i.e. those changes + * that no other change depends on). + */ +function getHeads(backend) { + return backend.heads +} - number = number.toString().replace(/\s+/g, ''); - var start = 0; - if (number[0] === '-') { - start++; - this.negative = 1; - } +/** + * Returns the full history of changes that have been applied to a document. + */ +function getAllChanges(backend) { + return getChanges(backend, []) +} - if (start < number.length) { - if (base === 16) { - this._parseHex(number, start, endian); - } else { - this._parseBase(number, base, start); - if (endian === 'le') { - this._initArray(this.toArray(), base, endian); - } - } - } - }; +/** + * Returns all changes that are newer than or concurrent to the changes + * identified by the hashes in `haveDeps`. If `haveDeps` is an empty array, all + * changes are returned. Throws an exception if any of the given hashes is unknown. + */ +function getChanges(backend, haveDeps) { + if (!Array.isArray(haveDeps)) { + throw new TypeError('Pass an array of hashes to Backend.getChanges()') + } + return backendState(backend).getChanges(haveDeps) +} - BN.prototype._initNumber = function _initNumber (number, base, endian) { - if (number < 0) { - this.negative = 1; - number = -number; - } - if (number < 0x4000000) { - this.words = [ number & 0x3ffffff ]; - this.length = 1; - } else if (number < 0x10000000000000) { - this.words = [ - number & 0x3ffffff, - (number / 0x4000000) & 0x3ffffff - ]; - this.length = 2; - } else { - assert(number < 0x20000000000000); // 2 ^ 53 (unsafe) - this.words = [ - number & 0x3ffffff, - (number / 0x4000000) & 0x3ffffff, - 1 - ]; - this.length = 3; - } +/** + * Returns all changes that are present in `backend2` but not in `backend1`. + * Intended for use in situations where the two backends are for different actors. + * To get the changes added between an older and a newer document state of the same + * actor, use `getChanges()` instead. `getChangesAdded()` throws an exception if + * one of the backend states is frozen (i.e. if it is not the latest state of that + * backend instance; this distinction matters when the backend is mutable). + */ +function getChangesAdded(backend1, backend2) { + return backendState(backend2).getChangesAdded(backendState(backend1)) +} - if (endian !== 'le') return; +/** + * If the backend has applied a change with the given `hash` (given as a + * hexadecimal string), returns that change (as a byte array). Returns undefined + * if no change with that hash has been applied. A change with missing + * dependencies does not count as having been applied. + */ +function getChangeByHash(backend, hash) { + return backendState(backend).getChangeByHash(hash) +} - // Reverse the bytes - this._initArray(this.toArray(), base, endian); - }; +/** + * Returns the hashes of any missing dependencies, i.e. where we have applied a + * change that has a dependency on a change we have not seen. + * + * If the argument `heads` is given (an array of hexadecimal strings representing + * hashes as returned by `getHeads()`), this function also ensures that all of + * those hashes resolve to either a change that has been applied to the document, + * or that has been enqueued for later application once missing dependencies have + * arrived. Any missing heads hashes are included in the returned array. + */ +function getMissingDeps(backend, heads = []) { + return backendState(backend).getMissingDeps(heads) +} - BN.prototype._initArray = function _initArray (number, base, endian) { - // Perhaps a Uint8Array - assert(typeof number.length === 'number'); - if (number.length <= 0) { - this.words = [ 0 ]; - this.length = 1; - return this; - } +module.exports = { + init, clone, free, applyChanges, applyLocalChange, save, load, loadChanges, getPatch, + getHeads, getAllChanges, getChanges, getChangesAdded, getChangeByHash, getMissingDeps +} - this.length = Math.ceil(number.length / 3); - this.words = new Array(this.length); - for (var i = 0; i < this.length; i++) { - this.words[i] = 0; - } +},{"./columnar":49,"./new":52,"./util":54}],49:[function(require,module,exports){ +const pako = require('pako') +const { copyObject, parseOpId, equalBytes } = require('../src/common') +const { + utf8ToString, hexStringToBytes, bytesToHexString, + Encoder, Decoder, RLEEncoder, RLEDecoder, DeltaEncoder, DeltaDecoder, BooleanEncoder, BooleanDecoder +} = require('./encoding') - var j, w; - var off = 0; - if (endian === 'be') { - for (i = number.length - 1, j = 0; i >= 0; i -= 3) { - w = number[i] | (number[i - 1] << 8) | (number[i - 2] << 16); - this.words[j] |= (w << off) & 0x3ffffff; - this.words[j + 1] = (w >>> (26 - off)) & 0x3ffffff; - off += 24; - if (off >= 26) { - off -= 26; - j++; - } - } - } else if (endian === 'le') { - for (i = 0, j = 0; i < number.length; i += 3) { - w = number[i] | (number[i + 1] << 8) | (number[i + 2] << 16); - this.words[j] |= (w << off) & 0x3ffffff; - this.words[j + 1] = (w >>> (26 - off)) & 0x3ffffff; - off += 24; - if (off >= 26) { - off -= 26; - j++; - } - } - } - return this.strip(); - }; +// Maybe we should be using the platform's built-in hash implementation? +// Node has the crypto module: https://nodejs.org/api/crypto.html and browsers have +// https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/digest +// However, the WebCrypto API is asynchronous (returns promises), which would +// force all our APIs to become asynchronous as well, which would be annoying. +// +// I think on balance, it's safe enough to use a random library off npm: +// - We only need one hash function (not a full suite of crypto algorithms); +// - SHA256 is quite simple and has fairly few opportunities for subtle bugs +// (compared to asymmetric cryptography anyway); +// - It does not need a secure source of random bits and does not need to be +// constant-time; +// - I have reviewed the source code and it seems pretty reasonable. +const { Hash } = require('fast-sha256') - function parseHex4Bits (string, index) { - var c = string.charCodeAt(index); - // 'A' - 'F' - if (c >= 65 && c <= 70) { - return c - 55; - // 'a' - 'f' - } else if (c >= 97 && c <= 102) { - return c - 87; - // '0' - '9' - } else { - return (c - 48) & 0xf; - } - } +// These bytes don't mean anything, they were generated randomly +const MAGIC_BYTES = new Uint8Array([0x85, 0x6f, 0x4a, 0x83]) - function parseHexByte (string, lowerBound, index) { - var r = parseHex4Bits(string, index); - if (index - 1 >= lowerBound) { - r |= parseHex4Bits(string, index - 1) << 4; - } - return r; - } +const CHUNK_TYPE_DOCUMENT = 0 +const CHUNK_TYPE_CHANGE = 1 +const CHUNK_TYPE_DEFLATE = 2 // like CHUNK_TYPE_CHANGE but with DEFLATE compression - BN.prototype._parseHex = function _parseHex (number, start, endian) { - // Create possibly bigger array to ensure that it fits the number - this.length = Math.ceil((number.length - start) / 6); - this.words = new Array(this.length); - for (var i = 0; i < this.length; i++) { - this.words[i] = 0; - } +// Minimum number of bytes in a value before we enable DEFLATE compression (there is no point +// compressing very short values since compression may actually make them bigger) +const DEFLATE_MIN_SIZE = 256 - // 24-bits chunks - var off = 0; - var j = 0; +// The least-significant 3 bits of a columnId indicate its datatype +const COLUMN_TYPE = { + GROUP_CARD: 0, ACTOR_ID: 1, INT_RLE: 2, INT_DELTA: 3, BOOLEAN: 4, + STRING_RLE: 5, VALUE_LEN: 6, VALUE_RAW: 7 +} - var w; - if (endian === 'be') { - for (i = number.length - 1; i >= start; i -= 2) { - w = parseHexByte(number, start, i) << off; - this.words[j] |= w & 0x3ffffff; - if (off >= 18) { - off -= 18; - j += 1; - this.words[j] |= w >>> 26; - } else { - off += 8; - } - } - } else { - var parseLength = number.length - start; - for (i = parseLength % 2 === 0 ? start + 1 : start; i < number.length; i += 2) { - w = parseHexByte(number, start, i) << off; - this.words[j] |= w & 0x3ffffff; - if (off >= 18) { - off -= 18; - j += 1; - this.words[j] |= w >>> 26; - } else { - off += 8; - } - } - } +// The 4th-least-significant bit of a columnId is set if the column is DEFLATE-compressed +const COLUMN_TYPE_DEFLATE = 8 - this.strip(); - }; +// In the values in a column of type VALUE_LEN, the bottom four bits indicate the type of the value, +// one of the following types in VALUE_TYPE. The higher bits indicate the length of the value in the +// associated VALUE_RAW column (in bytes). +const VALUE_TYPE = { + NULL: 0, FALSE: 1, TRUE: 2, LEB128_UINT: 3, LEB128_INT: 4, IEEE754: 5, + UTF8: 6, BYTES: 7, COUNTER: 8, TIMESTAMP: 9, MIN_UNKNOWN: 10, MAX_UNKNOWN: 15 +} - function parseBase (str, start, end, mul) { - var r = 0; - var len = Math.min(str.length, end); - for (var i = start; i < len; i++) { - var c = str.charCodeAt(i) - 48; +// make* actions must be at even-numbered indexes in this list +const ACTIONS = ['makeMap', 'set', 'makeList', 'del', 'makeText', 'inc', 'makeTable', 'link'] - r *= mul; +const OBJECT_TYPE = {makeMap: 'map', makeList: 'list', makeText: 'text', makeTable: 'table'} - // 'a' - if (c >= 49) { - r += c - 49 + 0xa; +const COMMON_COLUMNS = [ + {columnName: 'objActor', columnId: 0 << 4 | COLUMN_TYPE.ACTOR_ID}, + {columnName: 'objCtr', columnId: 0 << 4 | COLUMN_TYPE.INT_RLE}, + {columnName: 'keyActor', columnId: 1 << 4 | COLUMN_TYPE.ACTOR_ID}, + {columnName: 'keyCtr', columnId: 1 << 4 | COLUMN_TYPE.INT_DELTA}, + {columnName: 'keyStr', columnId: 1 << 4 | COLUMN_TYPE.STRING_RLE}, + {columnName: 'idActor', columnId: 2 << 4 | COLUMN_TYPE.ACTOR_ID}, + {columnName: 'idCtr', columnId: 2 << 4 | COLUMN_TYPE.INT_DELTA}, + {columnName: 'insert', columnId: 3 << 4 | COLUMN_TYPE.BOOLEAN}, + {columnName: 'action', columnId: 4 << 4 | COLUMN_TYPE.INT_RLE}, + {columnName: 'valLen', columnId: 5 << 4 | COLUMN_TYPE.VALUE_LEN}, + {columnName: 'valRaw', columnId: 5 << 4 | COLUMN_TYPE.VALUE_RAW}, + {columnName: 'chldActor', columnId: 6 << 4 | COLUMN_TYPE.ACTOR_ID}, + {columnName: 'chldCtr', columnId: 6 << 4 | COLUMN_TYPE.INT_DELTA} +] - // 'A' - } else if (c >= 17) { - r += c - 17 + 0xa; +const CHANGE_COLUMNS = COMMON_COLUMNS.concat([ + {columnName: 'predNum', columnId: 7 << 4 | COLUMN_TYPE.GROUP_CARD}, + {columnName: 'predActor', columnId: 7 << 4 | COLUMN_TYPE.ACTOR_ID}, + {columnName: 'predCtr', columnId: 7 << 4 | COLUMN_TYPE.INT_DELTA} +]) - // '0' - '9' - } else { - r += c; - } - } - return r; - } +const DOC_OPS_COLUMNS = COMMON_COLUMNS.concat([ + {columnName: 'succNum', columnId: 8 << 4 | COLUMN_TYPE.GROUP_CARD}, + {columnName: 'succActor', columnId: 8 << 4 | COLUMN_TYPE.ACTOR_ID}, + {columnName: 'succCtr', columnId: 8 << 4 | COLUMN_TYPE.INT_DELTA} +]) - BN.prototype._parseBase = function _parseBase (number, base, start) { - // Initialize as zero - this.words = [ 0 ]; - this.length = 1; +const DOCUMENT_COLUMNS = [ + {columnName: 'actor', columnId: 0 << 4 | COLUMN_TYPE.ACTOR_ID}, + {columnName: 'seq', columnId: 0 << 4 | COLUMN_TYPE.INT_DELTA}, + {columnName: 'maxOp', columnId: 1 << 4 | COLUMN_TYPE.INT_DELTA}, + {columnName: 'time', columnId: 2 << 4 | COLUMN_TYPE.INT_DELTA}, + {columnName: 'message', columnId: 3 << 4 | COLUMN_TYPE.STRING_RLE}, + {columnName: 'depsNum', columnId: 4 << 4 | COLUMN_TYPE.GROUP_CARD}, + {columnName: 'depsIndex', columnId: 4 << 4 | COLUMN_TYPE.INT_DELTA}, + {columnName: 'extraLen', columnId: 5 << 4 | COLUMN_TYPE.VALUE_LEN}, + {columnName: 'extraRaw', columnId: 5 << 4 | COLUMN_TYPE.VALUE_RAW} +] - // Find length of limb in base - for (var limbLen = 0, limbPow = 1; limbPow <= 0x3ffffff; limbPow *= base) { - limbLen++; - } - limbLen--; - limbPow = (limbPow / base) | 0; +/** + * Maps an opId of the form {counter: 12345, actorId: 'someActorId'} to the form + * {counter: 12345, actorNum: 123, actorId: 'someActorId'}, where the actorNum + * is the index into the `actorIds` array. + */ +function actorIdToActorNum(opId, actorIds) { + if (!opId || !opId.actorId) return opId + const counter = opId.counter + const actorNum = actorIds.indexOf(opId.actorId) + if (actorNum < 0) throw new RangeError('missing actorId') // should not happen + return {counter, actorNum, actorId: opId.actorId} +} - var total = number.length - start; - var mod = total % limbLen; - var end = Math.min(total, total - mod) + start; +/** + * Comparison function to pass to Array.sort(), which compares two opIds in the + * form produced by `actorIdToActorNum` so that they are sorted in increasing + * Lamport timestamp order (sorted first by counter, then by actorId). + */ +function compareParsedOpIds(id1, id2) { + if (id1.counter < id2.counter) return -1 + if (id1.counter > id2.counter) return +1 + if (id1.actorId < id2.actorId) return -1 + if (id1.actorId > id2.actorId) return +1 + return 0 +} - var word = 0; - for (var i = start; i < end; i += limbLen) { - word = parseBase(number, i, i + limbLen, base); +/** + * Takes `changes`, an array of changes (represented as JS objects). Returns an + * object `{changes, actorIds}`, where `changes` is a copy of the argument in + * which all string opIds have been replaced with `{counter, actorNum}` objects, + * and where `actorIds` is a lexicographically sorted array of actor IDs occurring + * in any of the operations. `actorNum` is an index into that array of actorIds. + * If `single` is true, the actorId of the author of the change is moved to the + * beginning of the array of actorIds, so that `actorNum` is zero when referencing + * the author of the change itself. This special-casing is omitted if `single` is + * false. + */ +function parseAllOpIds(changes, single) { + const actors = {}, newChanges = [] + for (let change of changes) { + change = copyObject(change) + actors[change.actor] = true + change.ops = expandMultiOps(change.ops, change.startOp, change.actor) + change.ops = change.ops.map(op => { + op = copyObject(op) + if (op.obj !== '_root') op.obj = parseOpId(op.obj) + if (op.elemId && op.elemId !== '_head') op.elemId = parseOpId(op.elemId) + if (op.child) op.child = parseOpId(op.child) + if (op.pred) op.pred = op.pred.map(parseOpId) + if (op.obj.actorId) actors[op.obj.actorId] = true + if (op.elemId && op.elemId.actorId) actors[op.elemId.actorId] = true + if (op.child && op.child.actorId) actors[op.child.actorId] = true + for (let pred of op.pred) actors[pred.actorId] = true + return op + }) + newChanges.push(change) + } - this.imuln(limbPow); - if (this.words[0] + word < 0x4000000) { - this.words[0] += word; - } else { - this._iaddn(word); - } + let actorIds = Object.keys(actors).sort() + if (single) { + actorIds = [changes[0].actor].concat(actorIds.filter(actor => actor !== changes[0].actor)) + } + for (let change of newChanges) { + change.actorNum = actorIds.indexOf(change.actor) + for (let i = 0; i < change.ops.length; i++) { + let op = change.ops[i] + op.id = {counter: change.startOp + i, actorNum: change.actorNum, actorId: change.actor} + op.obj = actorIdToActorNum(op.obj, actorIds) + op.elemId = actorIdToActorNum(op.elemId, actorIds) + op.child = actorIdToActorNum(op.child, actorIds) + op.pred = op.pred.map(pred => actorIdToActorNum(pred, actorIds)) } + } + return {changes: newChanges, actorIds} +} - if (mod !== 0) { - var pow = 1; - word = parseBase(number, i, number.length, base); +/** + * Encodes the `obj` property of operation `op` into the two columns + * `objActor` and `objCtr`. + */ +function encodeObjectId(op, columns) { + if (op.obj === '_root') { + columns.objActor.appendValue(null) + columns.objCtr.appendValue(null) + } else if (op.obj.actorNum >= 0 && op.obj.counter > 0) { + columns.objActor.appendValue(op.obj.actorNum) + columns.objCtr.appendValue(op.obj.counter) + } else { + throw new RangeError(`Unexpected objectId reference: ${JSON.stringify(op.obj)}`) + } +} - for (i = 0; i < mod; i++) { - pow *= base; - } +/** + * Encodes the `key` and `elemId` properties of operation `op` into the three + * columns `keyActor`, `keyCtr`, and `keyStr`. + */ +function encodeOperationKey(op, columns) { + if (op.key) { + columns.keyActor.appendValue(null) + columns.keyCtr.appendValue(null) + columns.keyStr.appendValue(op.key) + } else if (op.elemId === '_head' && op.insert) { + columns.keyActor.appendValue(null) + columns.keyCtr.appendValue(0) + columns.keyStr.appendValue(null) + } else if (op.elemId && op.elemId.actorNum >= 0 && op.elemId.counter > 0) { + columns.keyActor.appendValue(op.elemId.actorNum) + columns.keyCtr.appendValue(op.elemId.counter) + columns.keyStr.appendValue(null) + } else { + throw new RangeError(`Unexpected operation key: ${JSON.stringify(op)}`) + } +} - this.imuln(pow); - if (this.words[0] + word < 0x4000000) { - this.words[0] += word; +/** + * Encodes the `action` property of operation `op` into the `action` column. + */ +function encodeOperationAction(op, columns) { + const actionCode = ACTIONS.indexOf(op.action) + if (actionCode >= 0) { + columns.action.appendValue(actionCode) + } else if (typeof op.action === 'number') { + columns.action.appendValue(op.action) + } else { + throw new RangeError(`Unexpected operation action: ${op.action}`) + } +} + +/** + * Given the datatype for a number, determine the typeTag and the value to encode + * otherwise guess + */ +function getNumberTypeAndValue(op) { + switch (op.datatype) { + case "counter": + return [ VALUE_TYPE.COUNTER, op.value ] + case "timestamp": + return [ VALUE_TYPE.TIMESTAMP, op.value ] + case "uint": + return [ VALUE_TYPE.LEB128_UINT, op.value ] + case "int": + return [ VALUE_TYPE.LEB128_INT, op.value ] + case "float64": { + const buf64 = new ArrayBuffer(8), view64 = new DataView(buf64) + view64.setFloat64(0, op.value, true) + return [ VALUE_TYPE.IEEE754, new Uint8Array(buf64) ] + } + default: + // increment operators get resolved here ... + if (Number.isInteger(op.value) && op.value <= Number.MAX_SAFE_INTEGER && op.value >= Number.MIN_SAFE_INTEGER) { + return [ VALUE_TYPE.LEB128_INT, op.value ] } else { - this._iaddn(word); + const buf64 = new ArrayBuffer(8), view64 = new DataView(buf64) + view64.setFloat64(0, op.value, true) + return [ VALUE_TYPE.IEEE754, new Uint8Array(buf64) ] } - } - - this.strip(); - }; + } +} - BN.prototype.copy = function copy (dest) { - dest.words = new Array(this.length); - for (var i = 0; i < this.length; i++) { - dest.words[i] = this.words[i]; +/** + * Encodes the `value` property of operation `op` into the two columns + * `valLen` and `valRaw`. + */ +function encodeValue(op, columns) { + if ((op.action !== 'set' && op.action !== 'inc') || op.value === null) { + columns.valLen.appendValue(VALUE_TYPE.NULL) + } else if (op.value === false) { + columns.valLen.appendValue(VALUE_TYPE.FALSE) + } else if (op.value === true) { + columns.valLen.appendValue(VALUE_TYPE.TRUE) + } else if (typeof op.value === 'string') { + const numBytes = columns.valRaw.appendRawString(op.value) + columns.valLen.appendValue(numBytes << 4 | VALUE_TYPE.UTF8) + } else if (ArrayBuffer.isView(op.value)) { + const numBytes = columns.valRaw.appendRawBytes(new Uint8Array(op.value.buffer)) + columns.valLen.appendValue(numBytes << 4 | VALUE_TYPE.BYTES) + } else if (typeof op.value === 'number') { + let [typeTag, value] = getNumberTypeAndValue(op) + let numBytes + if (typeTag === VALUE_TYPE.LEB128_UINT) { + numBytes = columns.valRaw.appendUint53(value) + } else if (typeTag === VALUE_TYPE.IEEE754) { + numBytes = columns.valRaw.appendRawBytes(value) + } else { + numBytes = columns.valRaw.appendInt53(value) } - dest.length = this.length; - dest.negative = this.negative; - dest.red = this.red; - }; - - BN.prototype.clone = function clone () { - var r = new BN(null); - this.copy(r); - return r; - }; + columns.valLen.appendValue(numBytes << 4 | typeTag) + } else if (typeof op.datatype === 'number' && op.datatype >= VALUE_TYPE.MIN_UNKNOWN && + op.datatype <= VALUE_TYPE.MAX_UNKNOWN && op.value instanceof Uint8Array) { + const numBytes = columns.valRaw.appendRawBytes(op.value) + columns.valLen.appendValue(numBytes << 4 | op.datatype) + } else if (op.datatype) { + throw new RangeError(`Unknown datatype ${op.datatype} for value ${op.value}`) + } else { + throw new RangeError(`Unsupported value in operation: ${op.value}`) + } +} - BN.prototype._expand = function _expand (size) { - while (this.length < size) { - this.words[this.length++] = 0; +/** + * Given `sizeTag` (an unsigned integer read from a VALUE_LEN column) and `bytes` (a Uint8Array + * read from a VALUE_RAW column, with length `sizeTag >> 4`), this function returns an object of the + * form `{value: value, datatype: datatypeTag}` where `value` is a JavaScript primitive datatype + * corresponding to the value, and `datatypeTag` is a datatype annotation such as 'counter'. + */ +function decodeValue(sizeTag, bytes) { + if (sizeTag === VALUE_TYPE.NULL) { + return {value: null} + } else if (sizeTag === VALUE_TYPE.FALSE) { + return {value: false} + } else if (sizeTag === VALUE_TYPE.TRUE) { + return {value: true} + } else if (sizeTag % 16 === VALUE_TYPE.UTF8) { + return {value: utf8ToString(bytes)} + } else { + if (sizeTag % 16 === VALUE_TYPE.LEB128_UINT) { + return {value: new Decoder(bytes).readUint53(), datatype: "uint"} + } else if (sizeTag % 16 === VALUE_TYPE.LEB128_INT) { + return {value: new Decoder(bytes).readInt53(), datatype: "int"} + } else if (sizeTag % 16 === VALUE_TYPE.IEEE754) { + const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength) + if (bytes.byteLength === 8) { + return {value: view.getFloat64(0, true), datatype: "float64"} + } else { + throw new RangeError(`Invalid length for floating point number: ${bytes.byteLength}`) + } + } else if (sizeTag % 16 === VALUE_TYPE.COUNTER) { + return {value: new Decoder(bytes).readInt53(), datatype: 'counter'} + } else if (sizeTag % 16 === VALUE_TYPE.TIMESTAMP) { + return {value: new Decoder(bytes).readInt53(), datatype: 'timestamp'} + } else { + return {value: bytes, datatype: sizeTag % 16} } - return this; - }; + } +} - // Remove leading `0` from `this` - BN.prototype.strip = function strip () { - while (this.length > 1 && this.words[this.length - 1] === 0) { - this.length--; +/** + * Reads one value from the column `columns[colIndex]` and interprets it based + * on the column type. `actorIds` is a list of actors that appear in the change; + * `actorIds[0]` is the actorId of the change's author. Mutates the `result` + * object with the value, and returns the number of columns processed (this is 2 + * in the case of a pair of VALUE_LEN and VALUE_RAW columns, which are processed + * in one go). + */ +function decodeValueColumns(columns, colIndex, actorIds, result) { + const { columnId, columnName, decoder } = columns[colIndex] + if (columnId % 8 === COLUMN_TYPE.VALUE_LEN && colIndex + 1 < columns.length && + columns[colIndex + 1].columnId === columnId + 1) { + const sizeTag = decoder.readValue() + const rawValue = columns[colIndex + 1].decoder.readRawBytes(sizeTag >> 4) + const { value, datatype } = decodeValue(sizeTag, rawValue) + result[columnName] = value + if (datatype) result[columnName + '_datatype'] = datatype + return 2 + } else if (columnId % 8 === COLUMN_TYPE.ACTOR_ID) { + const actorNum = decoder.readValue() + if (actorNum === null) { + result[columnName] = null + } else { + if (!actorIds[actorNum]) throw new RangeError(`No actor index ${actorNum}`) + result[columnName] = actorIds[actorNum] } - return this._normSign(); - }; + } else { + result[columnName] = decoder.readValue() + } + return 1 +} - BN.prototype._normSign = function _normSign () { - // -0 = 0 - if (this.length === 1 && this.words[0] === 0) { - this.negative = 0; - } - return this; - }; +/** + * Encodes an array of operations in a set of columns. The operations need to + * be parsed with `parseAllOpIds()` beforehand. If `forDocument` is true, we use + * the column structure of a whole document, otherwise we use the column + * structure for an individual change. Returns an array of + * `{columnId, columnName, encoder}` objects. + */ +function encodeOps(ops, forDocument) { + const columns = { + objActor : new RLEEncoder('uint'), + objCtr : new RLEEncoder('uint'), + keyActor : new RLEEncoder('uint'), + keyCtr : new DeltaEncoder(), + keyStr : new RLEEncoder('utf8'), + insert : new BooleanEncoder(), + action : new RLEEncoder('uint'), + valLen : new RLEEncoder('uint'), + valRaw : new Encoder(), + chldActor : new RLEEncoder('uint'), + chldCtr : new DeltaEncoder() + } - BN.prototype.inspect = function inspect () { - return (this.red ? ''; - }; + if (forDocument) { + columns.idActor = new RLEEncoder('uint') + columns.idCtr = new DeltaEncoder() + columns.succNum = new RLEEncoder('uint') + columns.succActor = new RLEEncoder('uint') + columns.succCtr = new DeltaEncoder() + } else { + columns.predNum = new RLEEncoder('uint') + columns.predCtr = new DeltaEncoder() + columns.predActor = new RLEEncoder('uint') + } - /* + for (let op of ops) { + encodeObjectId(op, columns) + encodeOperationKey(op, columns) + columns.insert.appendValue(!!op.insert) + encodeOperationAction(op, columns) + encodeValue(op, columns) - var zeros = []; - var groupSizes = []; - var groupBases = []; + if (op.child && op.child.counter) { + columns.chldActor.appendValue(op.child.actorNum) + columns.chldCtr.appendValue(op.child.counter) + } else { + columns.chldActor.appendValue(null) + columns.chldCtr.appendValue(null) + } - var s = ''; - var i = -1; - while (++i < BN.wordSize) { - zeros[i] = s; - s += '0'; - } - groupSizes[0] = 0; - groupSizes[1] = 0; - groupBases[0] = 0; - groupBases[1] = 0; - var base = 2 - 1; - while (++base < 36 + 1) { - var groupSize = 0; - var groupBase = 1; - while (groupBase < (1 << BN.wordSize) / base) { - groupBase *= base; - groupSize += 1; + if (forDocument) { + columns.idActor.appendValue(op.id.actorNum) + columns.idCtr.appendValue(op.id.counter) + columns.succNum.appendValue(op.succ.length) + op.succ.sort(compareParsedOpIds) + for (let i = 0; i < op.succ.length; i++) { + columns.succActor.appendValue(op.succ[i].actorNum) + columns.succCtr.appendValue(op.succ[i].counter) + } + } else { + columns.predNum.appendValue(op.pred.length) + op.pred.sort(compareParsedOpIds) + for (let i = 0; i < op.pred.length; i++) { + columns.predActor.appendValue(op.pred[i].actorNum) + columns.predCtr.appendValue(op.pred[i].counter) + } } - groupSizes[base] = groupSize; - groupBases[base] = groupBase; } - */ + let columnList = [] + for (let {columnName, columnId} of forDocument ? DOC_OPS_COLUMNS : CHANGE_COLUMNS) { + if (columns[columnName]) columnList.push({columnId, columnName, encoder: columns[columnName]}) + } + return columnList.sort((a, b) => a.columnId - b.columnId) +} - var zeros = [ - '', - '0', - '00', - '000', - '0000', - '00000', - '000000', - '0000000', - '00000000', - '000000000', - '0000000000', - '00000000000', - '000000000000', - '0000000000000', - '00000000000000', - '000000000000000', - '0000000000000000', - '00000000000000000', - '000000000000000000', - '0000000000000000000', - '00000000000000000000', - '000000000000000000000', - '0000000000000000000000', - '00000000000000000000000', - '000000000000000000000000', - '0000000000000000000000000' - ]; - - var groupSizes = [ - 0, 0, - 25, 16, 12, 11, 10, 9, 8, - 8, 7, 7, 7, 7, 6, 6, - 6, 6, 6, 6, 6, 5, 5, - 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5 - ]; - - var groupBases = [ - 0, 0, - 33554432, 43046721, 16777216, 48828125, 60466176, 40353607, 16777216, - 43046721, 10000000, 19487171, 35831808, 62748517, 7529536, 11390625, - 16777216, 24137569, 34012224, 47045881, 64000000, 4084101, 5153632, - 6436343, 7962624, 9765625, 11881376, 14348907, 17210368, 20511149, - 24300000, 28629151, 33554432, 39135393, 45435424, 52521875, 60466176 - ]; - - BN.prototype.toString = function toString (base, padding) { - base = base || 10; - padding = padding | 0 || 1; +function validDatatype(value, datatype) { + if (datatype === undefined) { + return (typeof value === 'string' || typeof value === 'boolean' || value === null) + } else { + return typeof value === 'number' + } +} - var out; - if (base === 16 || base === 'hex') { - out = ''; - var off = 0; - var carry = 0; - for (var i = 0; i < this.length; i++) { - var w = this.words[i]; - var word = (((w << off) | carry) & 0xffffff).toString(16); - carry = (w >>> (24 - off)) & 0xffffff; - if (carry !== 0 || i !== this.length - 1) { - out = zeros[6 - word.length] + word + out; - } else { - out = word + out; - } - off += 2; - if (off >= 26) { - off -= 26; - i--; - } - } - if (carry !== 0) { - out = carry.toString(16) + out; - } - while (out.length % padding !== 0) { - out = '0' + out; +function expandMultiOps(ops, startOp, actor) { + let opNum = startOp + let expandedOps = [] + for (const op of ops) { + if (op.action === 'set' && op.values && op.insert) { + if (op.pred.length !== 0) throw new RangeError('multi-insert pred must be empty') + let lastElemId = op.elemId + const datatype = op.datatype + for (const value of op.values) { + if (!validDatatype(value, datatype)) throw new RangeError(`Decode failed: bad value/datatype association (${value},${datatype})`) + expandedOps.push({action: 'set', obj: op.obj, elemId: lastElemId, datatype, value, pred: [], insert: true}) + lastElemId = `${opNum}@${actor}` + opNum += 1 } - if (this.negative !== 0) { - out = '-' + out; + } else if (op.action === 'del' && op.multiOp > 1) { + if (op.pred.length !== 1) throw new RangeError('multiOp deletion must have exactly one pred') + const startElemId = parseOpId(op.elemId), startPred = parseOpId(op.pred[0]) + for (let i = 0; i < op.multiOp; i++) { + const elemId = `${startElemId.counter + i}@${startElemId.actorId}` + const pred = [`${startPred.counter + i}@${startPred.actorId}`] + expandedOps.push({action: 'del', obj: op.obj, elemId, pred}) + opNum += 1 } - return out; + } else { + expandedOps.push(op) + opNum += 1 } + } + return expandedOps +} - if (base === (base | 0) && base >= 2 && base <= 36) { - // var groupSize = Math.floor(BN.wordSize * Math.LN2 / Math.log(base)); - var groupSize = groupSizes[base]; - // var groupBase = Math.pow(base, groupSize); - var groupBase = groupBases[base]; - out = ''; - var c = this.clone(); - c.negative = 0; - while (!c.isZero()) { - var r = c.modn(groupBase).toString(base); - c = c.idivn(groupBase); - - if (!c.isZero()) { - out = zeros[groupSize - r.length] + r + out; - } else { - out = r + out; - } - } - if (this.isZero()) { - out = '0' + out; - } - while (out.length % padding !== 0) { - out = '0' + out; - } - if (this.negative !== 0) { - out = '-' + out; - } - return out; +/** + * Takes a change as decoded by `decodeColumns`, and changes it into the form + * expected by the rest of the backend. If `forDocument` is true, we use the op + * structure of a whole document, otherwise we use the op structure for an + * individual change. + */ +function decodeOps(ops, forDocument) { + const newOps = [] + for (let op of ops) { + const obj = (op.objCtr === null) ? '_root' : `${op.objCtr}@${op.objActor}` + const elemId = op.keyStr ? undefined : (op.keyCtr === 0 ? '_head' : `${op.keyCtr}@${op.keyActor}`) + const action = ACTIONS[op.action] || op.action + const newOp = elemId ? {obj, elemId, action} : {obj, key: op.keyStr, action} + newOp.insert = !!op.insert + if (ACTIONS[op.action] === 'set' || ACTIONS[op.action] === 'inc') { + newOp.value = op.valLen + if (op.valLen_datatype) newOp.datatype = op.valLen_datatype } - - assert(false, 'Base should be between 2 and 36'); - }; - - BN.prototype.toNumber = function toNumber () { - var ret = this.words[0]; - if (this.length === 2) { - ret += this.words[1] * 0x4000000; - } else if (this.length === 3 && this.words[2] === 0x01) { - // NOTE: at this stage it is known that the top bit is set - ret += 0x10000000000000 + (this.words[1] * 0x4000000); - } else if (this.length > 2) { - assert(false, 'Number can only safely store up to 53 bits'); + if (!!op.chldCtr !== !!op.chldActor) { + throw new RangeError(`Mismatched child columns: ${op.chldCtr} and ${op.chldActor}`) } - return (this.negative !== 0) ? -ret : ret; - }; + if (op.chldCtr !== null) newOp.child = `${op.chldCtr}@${op.chldActor}` + if (forDocument) { + newOp.id = `${op.idCtr}@${op.idActor}` + newOp.succ = op.succNum.map(succ => `${succ.succCtr}@${succ.succActor}`) + checkSortedOpIds(op.succNum.map(succ => ({counter: succ.succCtr, actorId: succ.succActor}))) + } else { + newOp.pred = op.predNum.map(pred => `${pred.predCtr}@${pred.predActor}`) + checkSortedOpIds(op.predNum.map(pred => ({counter: pred.predCtr, actorId: pred.predActor}))) + } + newOps.push(newOp) + } + return newOps +} - BN.prototype.toJSON = function toJSON () { - return this.toString(16); - }; +/** + * Throws an exception if the opIds in the given array are not in sorted order. + */ +function checkSortedOpIds(opIds) { + let last = null + for (let opId of opIds) { + if (last && compareParsedOpIds(last, opId) !== -1) { + throw new RangeError('operation IDs are not in ascending order') + } + last = opId + } +} - BN.prototype.toBuffer = function toBuffer (endian, length) { - assert(typeof Buffer !== 'undefined'); - return this.toArrayLike(Buffer, endian, length); - }; +function encoderByColumnId(columnId) { + if ((columnId & 7) === COLUMN_TYPE.INT_DELTA) { + return new DeltaEncoder() + } else if ((columnId & 7) === COLUMN_TYPE.BOOLEAN) { + return new BooleanEncoder() + } else if ((columnId & 7) === COLUMN_TYPE.STRING_RLE) { + return new RLEEncoder('utf8') + } else if ((columnId & 7) === COLUMN_TYPE.VALUE_RAW) { + return new Encoder() + } else { + return new RLEEncoder('uint') + } +} - BN.prototype.toArray = function toArray (endian, length) { - return this.toArrayLike(Array, endian, length); - }; +function decoderByColumnId(columnId, buffer) { + if ((columnId & 7) === COLUMN_TYPE.INT_DELTA) { + return new DeltaDecoder(buffer) + } else if ((columnId & 7) === COLUMN_TYPE.BOOLEAN) { + return new BooleanDecoder(buffer) + } else if ((columnId & 7) === COLUMN_TYPE.STRING_RLE) { + return new RLEDecoder('utf8', buffer) + } else if ((columnId & 7) === COLUMN_TYPE.VALUE_RAW) { + return new Decoder(buffer) + } else { + return new RLEDecoder('uint', buffer) + } +} - BN.prototype.toArrayLike = function toArrayLike (ArrayType, endian, length) { - var byteLength = this.byteLength(); - var reqLength = length || Math.max(1, byteLength); - assert(byteLength <= reqLength, 'byte array longer than desired length'); - assert(reqLength > 0, 'Requested array length <= 0'); +function makeDecoders(columns, columnSpec) { + const emptyBuf = new Uint8Array(0) + let decoders = [], columnIndex = 0, specIndex = 0 - this.strip(); - var littleEndian = endian === 'le'; - var res = new ArrayType(reqLength); + while (columnIndex < columns.length || specIndex < columnSpec.length) { + if (columnIndex === columns.length || + (specIndex < columnSpec.length && columnSpec[specIndex].columnId < columns[columnIndex].columnId)) { + const {columnId, columnName} = columnSpec[specIndex] + decoders.push({columnId, columnName, decoder: decoderByColumnId(columnId, emptyBuf)}) + specIndex++ + } else if (specIndex === columnSpec.length || columns[columnIndex].columnId < columnSpec[specIndex].columnId) { + const {columnId, buffer} = columns[columnIndex] + decoders.push({columnId, decoder: decoderByColumnId(columnId, buffer)}) + columnIndex++ + } else { // columns[columnIndex].columnId === columnSpec[specIndex].columnId + const {columnId, buffer} = columns[columnIndex], {columnName} = columnSpec[specIndex] + decoders.push({columnId, columnName, decoder: decoderByColumnId(columnId, buffer)}) + columnIndex++ + specIndex++ + } + } + return decoders +} - var b, i; - var q = this.clone(); - if (!littleEndian) { - // Assume big-endian - for (i = 0; i < reqLength - byteLength; i++) { - res[i] = 0; +function decodeColumns(columns, actorIds, columnSpec) { + columns = makeDecoders(columns, columnSpec) + let parsedRows = [] + while (columns.some(col => !col.decoder.done)) { + let row = {}, col = 0 + while (col < columns.length) { + const columnId = columns[col].columnId + let groupId = columnId >> 4, groupCols = 1 + while (col + groupCols < columns.length && columns[col + groupCols].columnId >> 4 === groupId) { + groupCols++ } - for (i = 0; !q.isZero(); i++) { - b = q.andln(0xff); - q.iushrn(8); - - res[reqLength - i - 1] = b; + if (columnId % 8 === COLUMN_TYPE.GROUP_CARD) { + const values = [], count = columns[col].decoder.readValue() + for (let i = 0; i < count; i++) { + let value = {} + for (let colOffset = 1; colOffset < groupCols; colOffset++) { + decodeValueColumns(columns, col + colOffset, actorIds, value) + } + values.push(value) + } + row[columns[col].columnName] = values + col += groupCols + } else { + col += decodeValueColumns(columns, col, actorIds, row) } - } else { - for (i = 0; !q.isZero(); i++) { - b = q.andln(0xff); - q.iushrn(8); + } + parsedRows.push(row) + } + return parsedRows +} - res[i] = b; - } +function decodeColumnInfo(decoder) { + // A number that is all 1 bits except for the bit that indicates whether a column is + // deflate-compressed. We ignore this bit when checking whether columns are sorted by ID. + const COLUMN_ID_MASK = (-1 ^ COLUMN_TYPE_DEFLATE) >>> 0 - for (; i < reqLength; i++) { - res[i] = 0; - } + let lastColumnId = -1, columns = [], numColumns = decoder.readUint53() + for (let i = 0; i < numColumns; i++) { + const columnId = decoder.readUint53(), bufferLen = decoder.readUint53() + if ((columnId & COLUMN_ID_MASK) <= (lastColumnId & COLUMN_ID_MASK)) { + throw new RangeError('Columns must be in ascending order') } + lastColumnId = columnId + columns.push({columnId, bufferLen}) + } + return columns +} - return res; - }; +function encodeColumnInfo(encoder, columns) { + const nonEmptyColumns = columns.filter(column => column.encoder.buffer.byteLength > 0) + encoder.appendUint53(nonEmptyColumns.length) + for (let column of nonEmptyColumns) { + encoder.appendUint53(column.columnId) + encoder.appendUint53(column.encoder.buffer.byteLength) + } +} - if (Math.clz32) { - BN.prototype._countBits = function _countBits (w) { - return 32 - Math.clz32(w); - }; - } else { - BN.prototype._countBits = function _countBits (w) { - var t = w; - var r = 0; - if (t >= 0x1000) { - r += 13; - t >>>= 13; - } - if (t >= 0x40) { - r += 7; - t >>>= 7; - } - if (t >= 0x8) { - r += 4; - t >>>= 4; - } - if (t >= 0x02) { - r += 2; - t >>>= 2; - } - return r + t; - }; +function decodeChangeHeader(decoder) { + const numDeps = decoder.readUint53(), deps = [] + for (let i = 0; i < numDeps; i++) { + deps.push(bytesToHexString(decoder.readRawBytes(32))) + } + let change = { + actor: decoder.readHexString(), + seq: decoder.readUint53(), + startOp: decoder.readUint53(), + time: decoder.readInt53(), + message: decoder.readPrefixedString(), + deps } + const actorIds = [change.actor], numActorIds = decoder.readUint53() + for (let i = 0; i < numActorIds; i++) actorIds.push(decoder.readHexString()) + change.actorIds = actorIds + return change +} - BN.prototype._zeroBits = function _zeroBits (w) { - // Short-cut - if (w === 0) return 26; +/** + * Assembles a chunk of encoded data containing a checksum, headers, and a + * series of encoded columns. Calls `encodeHeaderCallback` with an encoder that + * should be used to add the headers. The columns should be given as `columns`. + */ +function encodeContainer(chunkType, encodeContentsCallback) { + const CHECKSUM_SIZE = 4 // checksum is first 4 bytes of SHA-256 hash of the rest of the data + const HEADER_SPACE = MAGIC_BYTES.byteLength + CHECKSUM_SIZE + 1 + 5 // 1 byte type + 5 bytes length + const body = new Encoder() + // Make space for the header at the beginning of the body buffer. We will + // copy the header in here later. This is cheaper than copying the body since + // the body is likely to be much larger than the header. + body.appendRawBytes(new Uint8Array(HEADER_SPACE)) + encodeContentsCallback(body) - var t = w; - var r = 0; - if ((t & 0x1fff) === 0) { - r += 13; - t >>>= 13; - } - if ((t & 0x7f) === 0) { - r += 7; - t >>>= 7; - } - if ((t & 0xf) === 0) { - r += 4; - t >>>= 4; - } - if ((t & 0x3) === 0) { - r += 2; - t >>>= 2; - } - if ((t & 0x1) === 0) { - r++; - } - return r; - }; + const bodyBuf = body.buffer + const header = new Encoder() + header.appendByte(chunkType) + header.appendUint53(bodyBuf.byteLength - HEADER_SPACE) - // Return number of used bits in a BN - BN.prototype.bitLength = function bitLength () { - var w = this.words[this.length - 1]; - var hi = this._countBits(w); - return (this.length - 1) * 26 + hi; - }; + // Compute the hash over chunkType, length, and body + const headerBuf = header.buffer + const sha256 = new Hash() + sha256.update(headerBuf) + sha256.update(bodyBuf.subarray(HEADER_SPACE)) + const hash = sha256.digest(), checksum = hash.subarray(0, CHECKSUM_SIZE) - function toBitArray (num) { - var w = new Array(num.bitLength()); + // Copy header into the body buffer so that they are contiguous + bodyBuf.set(MAGIC_BYTES, HEADER_SPACE - headerBuf.byteLength - CHECKSUM_SIZE - MAGIC_BYTES.byteLength) + bodyBuf.set(checksum, HEADER_SPACE - headerBuf.byteLength - CHECKSUM_SIZE) + bodyBuf.set(headerBuf, HEADER_SPACE - headerBuf.byteLength) + return {hash, bytes: bodyBuf.subarray(HEADER_SPACE - headerBuf.byteLength - CHECKSUM_SIZE - MAGIC_BYTES.byteLength)} +} - for (var bit = 0; bit < w.length; bit++) { - var off = (bit / 26) | 0; - var wbit = bit % 26; +function decodeContainerHeader(decoder, computeHash) { + if (!equalBytes(decoder.readRawBytes(MAGIC_BYTES.byteLength), MAGIC_BYTES)) { + throw new RangeError('Data does not begin with magic bytes 85 6f 4a 83') + } + const expectedHash = decoder.readRawBytes(4) + const hashStartOffset = decoder.offset + const chunkType = decoder.readByte() + const chunkLength = decoder.readUint53() + const header = {chunkType, chunkLength, chunkData: decoder.readRawBytes(chunkLength)} - w[bit] = (num.words[off] & (1 << wbit)) >>> wbit; + if (computeHash) { + const sha256 = new Hash() + sha256.update(decoder.buf.subarray(hashStartOffset, decoder.offset)) + const binaryHash = sha256.digest() + if (!equalBytes(binaryHash.subarray(0, 4), expectedHash)) { + throw new RangeError('checksum does not match data') } - - return w; + header.hash = bytesToHexString(binaryHash) } + return header +} - // Number of trailing zero bits - BN.prototype.zeroBits = function zeroBits () { - if (this.isZero()) return 0; +function encodeChange(changeObj) { + const { changes, actorIds } = parseAllOpIds([changeObj], true) + const change = changes[0] - var r = 0; - for (var i = 0; i < this.length; i++) { - var b = this._zeroBits(this.words[i]); - r += b; - if (b !== 26) break; + const { hash, bytes } = encodeContainer(CHUNK_TYPE_CHANGE, encoder => { + if (!Array.isArray(change.deps)) throw new TypeError('deps is not an array') + encoder.appendUint53(change.deps.length) + for (let hash of change.deps.slice().sort()) { + encoder.appendRawBytes(hexStringToBytes(hash)) } - return r; - }; + encoder.appendHexString(change.actor) + encoder.appendUint53(change.seq) + encoder.appendUint53(change.startOp) + encoder.appendInt53(change.time) + encoder.appendPrefixedString(change.message || '') + encoder.appendUint53(actorIds.length - 1) + for (let actor of actorIds.slice(1)) encoder.appendHexString(actor) - BN.prototype.byteLength = function byteLength () { - return Math.ceil(this.bitLength() / 8); - }; + const columns = encodeOps(change.ops, false) + encodeColumnInfo(encoder, columns) + for (let column of columns) encoder.appendRawBytes(column.encoder.buffer) + if (change.extraBytes) encoder.appendRawBytes(change.extraBytes) + }) - BN.prototype.toTwos = function toTwos (width) { - if (this.negative !== 0) { - return this.abs().inotn(width).iaddn(1); - } - return this.clone(); - }; + const hexHash = bytesToHexString(hash) + if (changeObj.hash && changeObj.hash !== hexHash) { + throw new RangeError(`Change hash does not match encoding: ${changeObj.hash} != ${hexHash}`) + } + return (bytes.byteLength >= DEFLATE_MIN_SIZE) ? deflateChange(bytes) : bytes +} - BN.prototype.fromTwos = function fromTwos (width) { - if (this.testn(width - 1)) { - return this.notn(width).iaddn(1).ineg(); - } - return this.clone(); - }; +function decodeChangeColumns(buffer) { + if (buffer[8] === CHUNK_TYPE_DEFLATE) buffer = inflateChange(buffer) + const decoder = new Decoder(buffer) + const header = decodeContainerHeader(decoder, true) + const chunkDecoder = new Decoder(header.chunkData) + if (!decoder.done) throw new RangeError('Encoded change has trailing data') + if (header.chunkType !== CHUNK_TYPE_CHANGE) throw new RangeError(`Unexpected chunk type: ${header.chunkType}`) - BN.prototype.isNeg = function isNeg () { - return this.negative !== 0; - }; - - // Return negative clone of `this` - BN.prototype.neg = function neg () { - return this.clone().ineg(); - }; - - BN.prototype.ineg = function ineg () { - if (!this.isZero()) { - this.negative ^= 1; - } - - return this; - }; - - // Or `num` with `this` in-place - BN.prototype.iuor = function iuor (num) { - while (this.length < num.length) { - this.words[this.length++] = 0; + const change = decodeChangeHeader(chunkDecoder) + const columns = decodeColumnInfo(chunkDecoder) + for (let i = 0; i < columns.length; i++) { + if ((columns[i].columnId & COLUMN_TYPE_DEFLATE) !== 0) { + throw new RangeError('change must not contain deflated columns') } + columns[i].buffer = chunkDecoder.readRawBytes(columns[i].bufferLen) + } + if (!chunkDecoder.done) { + const restLen = chunkDecoder.buf.byteLength - chunkDecoder.offset + change.extraBytes = chunkDecoder.readRawBytes(restLen) + } - for (var i = 0; i < num.length; i++) { - this.words[i] = this.words[i] | num.words[i]; - } + change.columns = columns + change.hash = header.hash + return change +} - return this.strip(); - }; +/** + * Decodes one change in binary format into its JS object representation. + */ +function decodeChange(buffer) { + const change = decodeChangeColumns(buffer) + change.ops = decodeOps(decodeColumns(change.columns, change.actorIds, CHANGE_COLUMNS), false) + delete change.actorIds + delete change.columns + return change +} - BN.prototype.ior = function ior (num) { - assert((this.negative | num.negative) === 0); - return this.iuor(num); - }; +/** + * Decodes the header fields of a change in binary format, but does not decode + * the operations. Saves work when we only need to inspect the headers. Only + * computes the hash of the change if `computeHash` is true. + */ +function decodeChangeMeta(buffer, computeHash) { + if (buffer[8] === CHUNK_TYPE_DEFLATE) buffer = inflateChange(buffer) + const header = decodeContainerHeader(new Decoder(buffer), computeHash) + if (header.chunkType !== CHUNK_TYPE_CHANGE) { + throw new RangeError('Buffer chunk type is not a change') + } + const meta = decodeChangeHeader(new Decoder(header.chunkData)) + meta.change = buffer + if (computeHash) meta.hash = header.hash + return meta +} - // Or `num` with `this` - BN.prototype.or = function or (num) { - if (this.length > num.length) return this.clone().ior(num); - return num.clone().ior(this); - }; +/** + * Compresses a binary change using DEFLATE. + */ +function deflateChange(buffer) { + const header = decodeContainerHeader(new Decoder(buffer), false) + if (header.chunkType !== CHUNK_TYPE_CHANGE) throw new RangeError(`Unexpected chunk type: ${header.chunkType}`) + const compressed = pako.deflateRaw(header.chunkData) + const encoder = new Encoder() + encoder.appendRawBytes(buffer.subarray(0, 8)) // copy MAGIC_BYTES and checksum + encoder.appendByte(CHUNK_TYPE_DEFLATE) + encoder.appendUint53(compressed.byteLength) + encoder.appendRawBytes(compressed) + return encoder.buffer +} - BN.prototype.uor = function uor (num) { - if (this.length > num.length) return this.clone().iuor(num); - return num.clone().iuor(this); - }; +/** + * Decompresses a binary change that has been compressed with DEFLATE. + */ +function inflateChange(buffer) { + const header = decodeContainerHeader(new Decoder(buffer), false) + if (header.chunkType !== CHUNK_TYPE_DEFLATE) throw new RangeError(`Unexpected chunk type: ${header.chunkType}`) + const decompressed = pako.inflateRaw(header.chunkData) + const encoder = new Encoder() + encoder.appendRawBytes(buffer.subarray(0, 8)) // copy MAGIC_BYTES and checksum + encoder.appendByte(CHUNK_TYPE_CHANGE) + encoder.appendUint53(decompressed.byteLength) + encoder.appendRawBytes(decompressed) + return encoder.buffer +} - // And `num` with `this` in-place - BN.prototype.iuand = function iuand (num) { - // b = min-length(num, this) - var b; - if (this.length > num.length) { - b = num; - } else { - b = this; - } +/** + * Takes an Uint8Array that may contain multiple concatenated changes, and + * returns an array of subarrays, each subarray containing one change. + */ +function splitContainers(buffer) { + let decoder = new Decoder(buffer), chunks = [], startOffset = 0 + while (!decoder.done) { + decodeContainerHeader(decoder, false) + chunks.push(buffer.subarray(startOffset, decoder.offset)) + startOffset = decoder.offset + } + return chunks +} - for (var i = 0; i < b.length; i++) { - this.words[i] = this.words[i] & num.words[i]; +/** + * Decodes a list of changes from the binary format into JS objects. + * `binaryChanges` is an array of `Uint8Array` objects. + */ +function decodeChanges(binaryChanges) { + let decoded = [] + for (let binaryChange of binaryChanges) { + for (let chunk of splitContainers(binaryChange)) { + if (chunk[8] === CHUNK_TYPE_DOCUMENT) { + decoded = decoded.concat(decodeDocument(chunk)) + } else if (chunk[8] === CHUNK_TYPE_CHANGE || chunk[8] === CHUNK_TYPE_DEFLATE) { + decoded.push(decodeChange(chunk)) + } else { + // ignoring chunk of unknown type + } } + } + return decoded +} - this.length = b.length; - - return this.strip(); - }; - - BN.prototype.iand = function iand (num) { - assert((this.negative | num.negative) === 0); - return this.iuand(num); - }; +function sortOpIds(a, b) { + if (a === b) return 0 + if (a === '_root') return -1 + if (b === '_root') return +1 + const a_ = parseOpId(a), b_ = parseOpId(b) + if (a_.counter < b_.counter) return -1 + if (a_.counter > b_.counter) return +1 + if (a_.actorId < b_.actorId) return -1 + if (a_.actorId > b_.actorId) return +1 + return 0 +} - // And `num` with `this` - BN.prototype.and = function and (num) { - if (this.length > num.length) return this.clone().iand(num); - return num.clone().iand(this); - }; +/** + * Takes a set of operations `ops` loaded from an encoded document, and + * reconstructs the changes that they originally came from. + * Does not return anything, only mutates `changes`. + */ +function groupChangeOps(changes, ops) { + let changesByActor = {} // map from actorId to array of changes by that actor + for (let change of changes) { + change.ops = [] + if (!changesByActor[change.actor]) changesByActor[change.actor] = [] + if (change.seq !== changesByActor[change.actor].length + 1) { + throw new RangeError(`Expected seq = ${changesByActor[change.actor].length + 1}, got ${change.seq}`) + } + if (change.seq > 1 && changesByActor[change.actor][change.seq - 2].maxOp > change.maxOp) { + throw new RangeError('maxOp must increase monotonically per actor') + } + changesByActor[change.actor].push(change) + } - BN.prototype.uand = function uand (num) { - if (this.length > num.length) return this.clone().iuand(num); - return num.clone().iuand(this); - }; + let opsById = {} + for (let op of ops) { + if (op.action === 'del') throw new RangeError('document should not contain del operations') + op.pred = opsById[op.id] ? opsById[op.id].pred : [] + opsById[op.id] = op + for (let succ of op.succ) { + if (!opsById[succ]) { + if (op.elemId) { + const elemId = op.insert ? op.id : op.elemId + opsById[succ] = {id: succ, action: 'del', obj: op.obj, elemId, pred: []} + } else { + opsById[succ] = {id: succ, action: 'del', obj: op.obj, key: op.key, pred: []} + } + } + opsById[succ].pred.push(op.id) + } + delete op.succ + } + for (let op of Object.values(opsById)) { + if (op.action === 'del') ops.push(op) + } - // Xor `num` with `this` in-place - BN.prototype.iuxor = function iuxor (num) { - // a.length > b.length - var a; - var b; - if (this.length > num.length) { - a = this; - b = num; - } else { - a = num; - b = this; + for (let op of ops) { + const { counter, actorId } = parseOpId(op.id) + const actorChanges = changesByActor[actorId] + // Binary search to find the change that should contain this operation + let left = 0, right = actorChanges.length + while (left < right) { + const index = Math.floor((left + right) / 2) + if (actorChanges[index].maxOp < counter) { + left = index + 1 + } else { + right = index + } + } + if (left >= actorChanges.length) { + throw new RangeError(`Operation ID ${op.id} outside of allowed range`) } + actorChanges[left].ops.push(op) + } - for (var i = 0; i < b.length; i++) { - this.words[i] = a.words[i] ^ b.words[i]; + for (let change of changes) { + change.ops.sort((op1, op2) => sortOpIds(op1.id, op2.id)) + change.startOp = change.maxOp - change.ops.length + 1 + delete change.maxOp + for (let i = 0; i < change.ops.length; i++) { + const op = change.ops[i], expectedId = `${change.startOp + i}@${change.actor}` + if (op.id !== expectedId) { + throw new RangeError(`Expected opId ${expectedId}, got ${op.id}`) + } + delete op.id } + } +} - if (this !== a) { - for (; i < a.length; i++) { - this.words[i] = a.words[i]; +function decodeDocumentChanges(changes, expectedHeads) { + let heads = {} // change hashes that are not a dependency of any other change + for (let i = 0; i < changes.length; i++) { + let change = changes[i] + change.deps = [] + for (let index of change.depsNum.map(d => d.depsIndex)) { + if (!changes[index] || !changes[index].hash) { + throw new RangeError(`No hash for index ${index} while processing index ${i}`) } + const hash = changes[index].hash + change.deps.push(hash) + if (heads[hash]) delete heads[hash] } + change.deps.sort() + delete change.depsNum - this.length = a.length; + if (change.extraLen_datatype !== VALUE_TYPE.BYTES) { + throw new RangeError(`Bad datatype for extra bytes: ${VALUE_TYPE.BYTES}`) + } + change.extraBytes = change.extraLen + delete change.extraLen_datatype - return this.strip(); - }; + // Encoding and decoding again to compute the hash of the change + changes[i] = decodeChange(encodeChange(change)) + heads[changes[i].hash] = true + } - BN.prototype.ixor = function ixor (num) { - assert((this.negative | num.negative) === 0); - return this.iuxor(num); - }; + const actualHeads = Object.keys(heads).sort() + let headsEqual = (actualHeads.length === expectedHeads.length), i = 0 + while (headsEqual && i < actualHeads.length) { + headsEqual = (actualHeads[i] === expectedHeads[i]) + i++ + } + if (!headsEqual) { + throw new RangeError(`Mismatched heads hashes: expected ${expectedHeads.join(', ')}, got ${actualHeads.join(', ')}`) + } +} - // Xor `num` with `this` - BN.prototype.xor = function xor (num) { - if (this.length > num.length) return this.clone().ixor(num); - return num.clone().ixor(this); - }; +function encodeDocumentHeader(doc) { + const { changesColumns, opsColumns, actorIds, heads, headsIndexes, extraBytes } = doc + for (let column of changesColumns) deflateColumn(column) + for (let column of opsColumns) deflateColumn(column) - BN.prototype.uxor = function uxor (num) { - if (this.length > num.length) return this.clone().iuxor(num); - return num.clone().iuxor(this); - }; + return encodeContainer(CHUNK_TYPE_DOCUMENT, encoder => { + encoder.appendUint53(actorIds.length) + for (let actor of actorIds) { + encoder.appendHexString(actor) + } + encoder.appendUint53(heads.length) + for (let head of heads.sort()) { + encoder.appendRawBytes(hexStringToBytes(head)) + } + encodeColumnInfo(encoder, changesColumns) + encodeColumnInfo(encoder, opsColumns) + for (let column of changesColumns) encoder.appendRawBytes(column.encoder.buffer) + for (let column of opsColumns) encoder.appendRawBytes(column.encoder.buffer) + for (let index of headsIndexes) encoder.appendUint53(index) + if (extraBytes) encoder.appendRawBytes(extraBytes) + }).bytes +} - // Not ``this`` with ``width`` bitwidth - BN.prototype.inotn = function inotn (width) { - assert(typeof width === 'number' && width >= 0); +function decodeDocumentHeader(buffer) { + const documentDecoder = new Decoder(buffer) + const header = decodeContainerHeader(documentDecoder, true) + const decoder = new Decoder(header.chunkData) + if (!documentDecoder.done) throw new RangeError('Encoded document has trailing data') + if (header.chunkType !== CHUNK_TYPE_DOCUMENT) throw new RangeError(`Unexpected chunk type: ${header.chunkType}`) - var bytesNeeded = Math.ceil(width / 26) | 0; - var bitsLeft = width % 26; + const actorIds = [], numActors = decoder.readUint53() + for (let i = 0; i < numActors; i++) { + actorIds.push(decoder.readHexString()) + } + const heads = [], headsIndexes = [], numHeads = decoder.readUint53() + for (let i = 0; i < numHeads; i++) { + heads.push(bytesToHexString(decoder.readRawBytes(32))) + } - // Extend the buffer with leading zeroes - this._expand(bytesNeeded); + const changesColumns = decodeColumnInfo(decoder) + const opsColumns = decodeColumnInfo(decoder) + for (let i = 0; i < changesColumns.length; i++) { + changesColumns[i].buffer = decoder.readRawBytes(changesColumns[i].bufferLen) + inflateColumn(changesColumns[i]) + } + for (let i = 0; i < opsColumns.length; i++) { + opsColumns[i].buffer = decoder.readRawBytes(opsColumns[i].bufferLen) + inflateColumn(opsColumns[i]) + } + if (!decoder.done) { + for (let i = 0; i < numHeads; i++) headsIndexes.push(decoder.readUint53()) + } - if (bitsLeft > 0) { - bytesNeeded--; - } + const extraBytes = decoder.readRawBytes(decoder.buf.byteLength - decoder.offset) + return { changesColumns, opsColumns, actorIds, heads, headsIndexes, extraBytes } +} - // Handle complete words - for (var i = 0; i < bytesNeeded; i++) { - this.words[i] = ~this.words[i] & 0x3ffffff; - } +function decodeDocument(buffer) { + const { changesColumns, opsColumns, actorIds, heads } = decodeDocumentHeader(buffer) + const changes = decodeColumns(changesColumns, actorIds, DOCUMENT_COLUMNS) + const ops = decodeOps(decodeColumns(opsColumns, actorIds, DOC_OPS_COLUMNS), true) + groupChangeOps(changes, ops) + decodeDocumentChanges(changes, heads) + return changes +} - // Handle the residue - if (bitsLeft > 0) { - this.words[i] = ~this.words[i] & (0x3ffffff >> (26 - bitsLeft)); - } +/** + * DEFLATE-compresses the given column if it is large enough to make the compression worthwhile. + */ +function deflateColumn(column) { + if (column.encoder.buffer.byteLength >= DEFLATE_MIN_SIZE) { + column.encoder = {buffer: pako.deflateRaw(column.encoder.buffer)} + column.columnId |= COLUMN_TYPE_DEFLATE + } +} - // And remove leading zeroes - return this.strip(); - }; +/** + * Decompresses the given column if it is DEFLATE-compressed. + */ +function inflateColumn(column) { + if ((column.columnId & COLUMN_TYPE_DEFLATE) !== 0) { + column.buffer = pako.inflateRaw(column.buffer) + column.columnId ^= COLUMN_TYPE_DEFLATE + } +} - BN.prototype.notn = function notn (width) { - return this.clone().inotn(width); - }; +module.exports = { + COLUMN_TYPE, VALUE_TYPE, ACTIONS, OBJECT_TYPE, DOC_OPS_COLUMNS, CHANGE_COLUMNS, DOCUMENT_COLUMNS, + encoderByColumnId, decoderByColumnId, makeDecoders, decodeValue, + splitContainers, encodeChange, decodeChangeColumns, decodeChange, decodeChangeMeta, decodeChanges, + encodeDocumentHeader, decodeDocumentHeader, decodeDocument +} - // Set `bit` of `this` - BN.prototype.setn = function setn (bit, val) { - assert(typeof bit === 'number' && bit >= 0); +},{"../src/common":82,"./encoding":50,"fast-sha256":174,"pako":65}],50:[function(require,module,exports){ +/** + * UTF-8 decoding and encoding using API that is supported in Node >= 12 and modern browsers: + * https://developer.mozilla.org/en-US/docs/Web/API/TextEncoder/encode + * https://developer.mozilla.org/en-US/docs/Web/API/TextDecoder/decode + * If you're running in an environment where it's not available, please use a polyfill, such as: + * https://github.com/anonyco/FastestSmallestTextEncoderDecoder + */ +const utf8encoder = new TextEncoder() +const utf8decoder = new TextDecoder('utf-8') - var off = (bit / 26) | 0; - var wbit = bit % 26; +function stringToUtf8(string) { + return utf8encoder.encode(string) +} - this._expand(off + 1); +function utf8ToString(buffer) { + return utf8decoder.decode(buffer) +} - if (val) { - this.words[off] = this.words[off] | (1 << wbit); - } else { - this.words[off] = this.words[off] & ~(1 << wbit); - } +/** + * Converts a string consisting of hexadecimal digits into an Uint8Array. + */ +function hexStringToBytes(value) { + if (typeof value !== 'string') { + throw new TypeError('value is not a string') + } + if (!/^([0-9a-f][0-9a-f])*$/.test(value)) { + throw new RangeError('value is not hexadecimal') + } + if (value === '') { + return new Uint8Array(0) + } else { + return new Uint8Array(value.match(/../g).map(b => parseInt(b, 16))) + } +} - return this.strip(); - }; +const NIBBLE_TO_HEX = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'] +const BYTE_TO_HEX = new Array(256) +for (let i = 0; i < 256; i++) { + BYTE_TO_HEX[i] = `${NIBBLE_TO_HEX[(i >>> 4) & 0xf]}${NIBBLE_TO_HEX[i & 0xf]}`; +} - // Add `num` to `this` in-place - BN.prototype.iadd = function iadd (num) { - var r; +/** + * Converts a Uint8Array into the equivalent hexadecimal string. + */ +function bytesToHexString(bytes) { + let hex = '', len = bytes.byteLength + for (let i = 0; i < len; i++) { + hex += BYTE_TO_HEX[bytes[i]] + } + return hex +} - // negative + positive - if (this.negative !== 0 && num.negative === 0) { - this.negative = 0; - r = this.isub(num); - this.negative ^= 1; - return this._normSign(); +/** + * Wrapper around an Uint8Array that allows values to be appended to the buffer, + * and that automatically grows the buffer when space runs out. + */ +class Encoder { + constructor() { + this.buf = new Uint8Array(16) + this.offset = 0 + } - // positive + negative - } else if (this.negative === 0 && num.negative !== 0) { - num.negative = 0; - r = this.isub(num); - num.negative = 1; - return r._normSign(); - } + /** + * Returns the byte array containing the encoded data. + */ + get buffer() { + this.finish() + return this.buf.subarray(0, this.offset) + } - // a.length > b.length - var a, b; - if (this.length > num.length) { - a = this; - b = num; - } else { - a = num; - b = this; - } + /** + * Reallocates the encoder's buffer to be bigger. + */ + grow(minSize = 0) { + let newSize = this.buf.byteLength * 4 + while (newSize < minSize) newSize *= 2 + const newBuf = new Uint8Array(newSize) + newBuf.set(this.buf, 0) + this.buf = newBuf + return this + } - var carry = 0; - for (var i = 0; i < b.length; i++) { - r = (a.words[i] | 0) + (b.words[i] | 0) + carry; - this.words[i] = r & 0x3ffffff; - carry = r >>> 26; - } - for (; carry !== 0 && i < a.length; i++) { - r = (a.words[i] | 0) + carry; - this.words[i] = r & 0x3ffffff; - carry = r >>> 26; - } + /** + * Appends one byte (0 to 255) to the buffer. + */ + appendByte(value) { + if (this.offset >= this.buf.byteLength) this.grow() + this.buf[this.offset] = value + this.offset += 1 + } - this.length = a.length; - if (carry !== 0) { - this.words[this.length] = carry; - this.length++; - // Copy the rest of the words - } else if (a !== this) { - for (; i < a.length; i++) { - this.words[i] = a.words[i]; - } - } + /** + * Encodes a 32-bit nonnegative integer in a variable number of bytes using + * the LEB128 encoding scheme (https://en.wikipedia.org/wiki/LEB128) and + * appends it to the buffer. Returns the number of bytes written. + */ + appendUint32(value) { + if (!Number.isInteger(value)) throw new RangeError('value is not an integer') + if (value < 0 || value > 0xffffffff) throw new RangeError('number out of range') - return this; - }; + const numBytes = Math.max(1, Math.ceil((32 - Math.clz32(value)) / 7)) + if (this.offset + numBytes > this.buf.byteLength) this.grow() - // Add `num` to `this` - BN.prototype.add = function add (num) { - var res; - if (num.negative !== 0 && this.negative === 0) { - num.negative = 0; - res = this.sub(num); - num.negative ^= 1; - return res; - } else if (num.negative === 0 && this.negative !== 0) { - this.negative = 0; - res = num.sub(this); - this.negative = 1; - return res; + for (let i = 0; i < numBytes; i++) { + this.buf[this.offset + i] = (value & 0x7f) | (i === numBytes - 1 ? 0x00 : 0x80) + value >>>= 7 // zero-filling right shift } + this.offset += numBytes + return numBytes + } - if (this.length > num.length) return this.clone().iadd(num); - - return num.clone().iadd(this); - }; + /** + * Encodes a 32-bit signed integer in a variable number of bytes using the + * LEB128 encoding scheme (https://en.wikipedia.org/wiki/LEB128) and appends + * it to the buffer. Returns the number of bytes written. + */ + appendInt32(value) { + if (!Number.isInteger(value)) throw new RangeError('value is not an integer') + if (value < -0x80000000 || value > 0x7fffffff) throw new RangeError('number out of range') - // Subtract `num` from `this` in-place - BN.prototype.isub = function isub (num) { - // this - (-num) = this + num - if (num.negative !== 0) { - num.negative = 0; - var r = this.iadd(num); - num.negative = 1; - return r._normSign(); + const numBytes = Math.ceil((33 - Math.clz32(value >= 0 ? value : -value - 1)) / 7) + if (this.offset + numBytes > this.buf.byteLength) this.grow() - // -this - num = -(this + num) - } else if (this.negative !== 0) { - this.negative = 0; - this.iadd(num); - this.negative = 1; - return this._normSign(); + for (let i = 0; i < numBytes; i++) { + this.buf[this.offset + i] = (value & 0x7f) | (i === numBytes - 1 ? 0x00 : 0x80) + value >>= 7 // sign-propagating right shift } + this.offset += numBytes + return numBytes + } - // At this point both numbers are positive - var cmp = this.cmp(num); + /** + * Encodes a nonnegative integer in a variable number of bytes using the LEB128 + * encoding scheme, up to the maximum size of integers supported by JavaScript + * (53 bits). + */ + appendUint53(value) { + if (!Number.isInteger(value)) throw new RangeError('value is not an integer') + if (value < 0 || value > Number.MAX_SAFE_INTEGER) { + throw new RangeError('number out of range') + } + const high32 = Math.floor(value / 0x100000000) + const low32 = (value & 0xffffffff) >>> 0 // right shift to interpret as unsigned + return this.appendUint64(high32, low32) + } - // Optimization - zeroify - if (cmp === 0) { - this.negative = 0; - this.length = 1; - this.words[0] = 0; - return this; + /** + * Encodes a signed integer in a variable number of bytes using the LEB128 + * encoding scheme, up to the maximum size of integers supported by JavaScript + * (53 bits). + */ + appendInt53(value) { + if (!Number.isInteger(value)) throw new RangeError('value is not an integer') + if (value < Number.MIN_SAFE_INTEGER || value > Number.MAX_SAFE_INTEGER) { + throw new RangeError('number out of range') } + const high32 = Math.floor(value / 0x100000000) + const low32 = (value & 0xffffffff) >>> 0 // right shift to interpret as unsigned + return this.appendInt64(high32, low32) + } - // a > b - var a, b; - if (cmp > 0) { - a = this; - b = num; - } else { - a = num; - b = this; + /** + * Encodes a 64-bit nonnegative integer in a variable number of bytes using + * the LEB128 encoding scheme, and appends it to the buffer. The number is + * given as two 32-bit halves since JavaScript cannot accurately represent + * integers with more than 53 bits in a single variable. + */ + appendUint64(high32, low32) { + if (!Number.isInteger(high32) || !Number.isInteger(low32)) { + throw new RangeError('value is not an integer') + } + if (high32 < 0 || high32 > 0xffffffff || low32 < 0 || low32 > 0xffffffff) { + throw new RangeError('number out of range') } + if (high32 === 0) return this.appendUint32(low32) - var carry = 0; - for (var i = 0; i < b.length; i++) { - r = (a.words[i] | 0) - (b.words[i] | 0) + carry; - carry = r >> 26; - this.words[i] = r & 0x3ffffff; + const numBytes = Math.ceil((64 - Math.clz32(high32)) / 7) + if (this.offset + numBytes > this.buf.byteLength) this.grow() + for (let i = 0; i < 4; i++) { + this.buf[this.offset + i] = (low32 & 0x7f) | 0x80 + low32 >>>= 7 // zero-filling right shift } - for (; carry !== 0 && i < a.length; i++) { - r = (a.words[i] | 0) + carry; - carry = r >> 26; - this.words[i] = r & 0x3ffffff; + this.buf[this.offset + 4] = (low32 & 0x0f) | ((high32 & 0x07) << 4) | (numBytes === 5 ? 0x00 : 0x80) + high32 >>>= 3 + for (let i = 5; i < numBytes; i++) { + this.buf[this.offset + i] = (high32 & 0x7f) | (i === numBytes - 1 ? 0x00 : 0x80) + high32 >>>= 7 } + this.offset += numBytes + return numBytes + } - // Copy rest of the words - if (carry === 0 && i < a.length && a !== this) { - for (; i < a.length; i++) { - this.words[i] = a.words[i]; - } + /** + * Encodes a 64-bit signed integer in a variable number of bytes using the + * LEB128 encoding scheme, and appends it to the buffer. The number is given + * as two 32-bit halves since JavaScript cannot accurately represent integers + * with more than 53 bits in a single variable. The sign of the 64-bit + * number is determined by the sign of the `high32` half; the sign of the + * `low32` half is ignored. + */ + appendInt64(high32, low32) { + if (!Number.isInteger(high32) || !Number.isInteger(low32)) { + throw new RangeError('value is not an integer') + } + if (high32 < -0x80000000 || high32 > 0x7fffffff || low32 < -0x80000000 || low32 > 0xffffffff) { + throw new RangeError('number out of range') } + low32 >>>= 0 // interpret as unsigned + if (high32 === 0 && low32 <= 0x7fffffff) return this.appendInt32(low32) + if (high32 === -1 && low32 >= 0x80000000) return this.appendInt32(low32 - 0x100000000) - this.length = Math.max(this.length, i); + const numBytes = Math.ceil((65 - Math.clz32(high32 >= 0 ? high32 : -high32 - 1)) / 7) + if (this.offset + numBytes > this.buf.byteLength) this.grow() + for (let i = 0; i < 4; i++) { + this.buf[this.offset + i] = (low32 & 0x7f) | 0x80 + low32 >>>= 7 // zero-filling right shift + } + this.buf[this.offset + 4] = (low32 & 0x0f) | ((high32 & 0x07) << 4) | (numBytes === 5 ? 0x00 : 0x80) + high32 >>= 3 // sign-propagating right shift + for (let i = 5; i < numBytes; i++) { + this.buf[this.offset + i] = (high32 & 0x7f) | (i === numBytes - 1 ? 0x00 : 0x80) + high32 >>= 7 + } + this.offset += numBytes + return numBytes + } - if (a !== this) { - this.negative = 1; + /** + * Appends the contents of byte buffer `data` to the buffer. Returns the + * number of bytes appended. + */ + appendRawBytes(data) { + if (this.offset + data.byteLength > this.buf.byteLength) { + this.grow(this.offset + data.byteLength) } + this.buf.set(data, this.offset) + this.offset += data.byteLength + return data.byteLength + } - return this.strip(); - }; + /** + * Appends a UTF-8 string to the buffer, without any metadata. Returns the + * number of bytes appended. + */ + appendRawString(value) { + if (typeof value !== 'string') throw new TypeError('value is not a string') + return this.appendRawBytes(stringToUtf8(value)) + } - // Subtract `num` from `this` - BN.prototype.sub = function sub (num) { - return this.clone().isub(num); - }; + /** + * Appends the contents of byte buffer `data` to the buffer, prefixed with the + * number of bytes in the buffer (as a LEB128-encoded unsigned integer). + */ + appendPrefixedBytes(data) { + this.appendUint53(data.byteLength) + this.appendRawBytes(data) + return this + } - function smallMulTo (self, num, out) { - out.negative = num.negative ^ self.negative; - var len = (self.length + num.length) | 0; - out.length = len; - len = (len - 1) | 0; + /** + * Appends a UTF-8 string to the buffer, prefixed with its length in bytes + * (where the length is encoded as an unsigned LEB128 integer). + */ + appendPrefixedString(value) { + if (typeof value !== 'string') throw new TypeError('value is not a string') + this.appendPrefixedBytes(stringToUtf8(value)) + return this + } - // Peel one iteration (compiler can't do it, because of code complexity) - var a = self.words[0] | 0; - var b = num.words[0] | 0; - var r = a * b; + /** + * Takes a value, which must be a string consisting only of hexadecimal + * digits, maps it to a byte array, and appends it to the buffer, prefixed + * with its length in bytes. + */ + appendHexString(value) { + this.appendPrefixedBytes(hexStringToBytes(value)) + return this + } - var lo = r & 0x3ffffff; - var carry = (r / 0x4000000) | 0; - out.words[0] = lo; + /** + * Flushes any unwritten data to the buffer. Call this before reading from + * the buffer constructed by this Encoder. + */ + finish() { + } +} - for (var k = 1; k < len; k++) { - // Sum all words with the same `i + j = k` and accumulate `ncarry`, - // note that ncarry could be >= 0x3ffffff - var ncarry = carry >>> 26; - var rword = carry & 0x3ffffff; - var maxJ = Math.min(k, num.length - 1); - for (var j = Math.max(0, k - self.length + 1); j <= maxJ; j++) { - var i = (k - j) | 0; - a = self.words[i] | 0; - b = num.words[j] | 0; - r = a * b + rword; - ncarry += (r / 0x4000000) | 0; - rword = r & 0x3ffffff; +/** + * Counterpart to Encoder. Wraps a Uint8Array buffer with a cursor indicating + * the current decoding position, and allows values to be incrementally read by + * decoding the bytes at the current position. + */ +class Decoder { + constructor(buffer) { + if (!(buffer instanceof Uint8Array)) { + throw new TypeError(`Not a byte array: ${buffer}`) + } + this.buf = buffer + this.offset = 0 + } + + /** + * Returns false if there is still data to be read at the current decoding + * position, and true if we are at the end of the buffer. + */ + get done() { + return this.offset === this.buf.byteLength + } + + /** + * Resets the cursor position, so that the next read goes back to the + * beginning of the buffer. + */ + reset() { + this.offset = 0 + } + + /** + * Moves the current decoding position forward by the specified number of + * bytes, without decoding anything. + */ + skip(bytes) { + if (this.offset + bytes > this.buf.byteLength) { + throw new RangeError('cannot skip beyond end of buffer') + } + this.offset += bytes + } + + /** + * Reads one byte (0 to 255) from the buffer. + */ + readByte() { + this.offset += 1 + return this.buf[this.offset - 1] + } + + /** + * Reads a LEB128-encoded unsigned integer from the current position in the buffer. + * Throws an exception if the value doesn't fit in a 32-bit unsigned int. + */ + readUint32() { + let result = 0, shift = 0 + while (this.offset < this.buf.byteLength) { + const nextByte = this.buf[this.offset] + if (shift === 28 && (nextByte & 0xf0) !== 0) { // more than 5 bytes, or value > 0xffffffff + throw new RangeError('number out of range') } - out.words[k] = rword | 0; - carry = ncarry | 0; + result = (result | (nextByte & 0x7f) << shift) >>> 0 // right shift to interpret value as unsigned + shift += 7 + this.offset++ + if ((nextByte & 0x80) === 0) return result } - if (carry !== 0) { - out.words[k] = carry | 0; - } else { - out.length--; + throw new RangeError('buffer ended with incomplete number') + } + + /** + * Reads a LEB128-encoded signed integer from the current position in the buffer. + * Throws an exception if the value doesn't fit in a 32-bit signed int. + */ + readInt32() { + let result = 0, shift = 0 + while (this.offset < this.buf.byteLength) { + const nextByte = this.buf[this.offset] + if ((shift === 28 && (nextByte & 0x80) !== 0) || // more than 5 bytes + (shift === 28 && (nextByte & 0x40) === 0 && (nextByte & 0x38) !== 0) || // positive int > 0x7fffffff + (shift === 28 && (nextByte & 0x40) !== 0 && (nextByte & 0x38) !== 0x38)) { // negative int < -0x80000000 + throw new RangeError('number out of range') + } + result |= (nextByte & 0x7f) << shift + shift += 7 + this.offset++ + + if ((nextByte & 0x80) === 0) { + if ((nextByte & 0x40) === 0 || shift > 28) { + return result // positive, or negative value that doesn't need sign-extending + } else { + return result | (-1 << shift) // sign-extend negative integer + } + } } + throw new RangeError('buffer ended with incomplete number') + } - return out.strip(); + /** + * Reads a LEB128-encoded unsigned integer from the current position in the + * buffer. Allows any integer that can be safely represented by JavaScript + * (up to 2^53 - 1), and throws an exception outside of that range. + */ + readUint53() { + const { low32, high32 } = this.readUint64() + if (high32 < 0 || high32 > 0x1fffff) { + throw new RangeError('number out of range') + } + return high32 * 0x100000000 + low32 } - // TODO(indutny): it may be reasonable to omit it for users who don't need - // to work with 256-bit numbers, otherwise it gives 20% improvement for 256-bit - // multiplication (like elliptic secp256k1). - var comb10MulTo = function comb10MulTo (self, num, out) { - var a = self.words; - var b = num.words; - var o = out.words; - var c = 0; - var lo; - var mid; - var hi; - var a0 = a[0] | 0; - var al0 = a0 & 0x1fff; - var ah0 = a0 >>> 13; - var a1 = a[1] | 0; - var al1 = a1 & 0x1fff; - var ah1 = a1 >>> 13; - var a2 = a[2] | 0; - var al2 = a2 & 0x1fff; - var ah2 = a2 >>> 13; - var a3 = a[3] | 0; - var al3 = a3 & 0x1fff; - var ah3 = a3 >>> 13; - var a4 = a[4] | 0; - var al4 = a4 & 0x1fff; - var ah4 = a4 >>> 13; - var a5 = a[5] | 0; - var al5 = a5 & 0x1fff; - var ah5 = a5 >>> 13; - var a6 = a[6] | 0; - var al6 = a6 & 0x1fff; - var ah6 = a6 >>> 13; - var a7 = a[7] | 0; - var al7 = a7 & 0x1fff; - var ah7 = a7 >>> 13; - var a8 = a[8] | 0; - var al8 = a8 & 0x1fff; - var ah8 = a8 >>> 13; - var a9 = a[9] | 0; - var al9 = a9 & 0x1fff; - var ah9 = a9 >>> 13; - var b0 = b[0] | 0; - var bl0 = b0 & 0x1fff; - var bh0 = b0 >>> 13; - var b1 = b[1] | 0; - var bl1 = b1 & 0x1fff; - var bh1 = b1 >>> 13; - var b2 = b[2] | 0; - var bl2 = b2 & 0x1fff; - var bh2 = b2 >>> 13; - var b3 = b[3] | 0; - var bl3 = b3 & 0x1fff; - var bh3 = b3 >>> 13; - var b4 = b[4] | 0; - var bl4 = b4 & 0x1fff; - var bh4 = b4 >>> 13; - var b5 = b[5] | 0; - var bl5 = b5 & 0x1fff; - var bh5 = b5 >>> 13; - var b6 = b[6] | 0; - var bl6 = b6 & 0x1fff; - var bh6 = b6 >>> 13; - var b7 = b[7] | 0; - var bl7 = b7 & 0x1fff; - var bh7 = b7 >>> 13; - var b8 = b[8] | 0; - var bl8 = b8 & 0x1fff; - var bh8 = b8 >>> 13; - var b9 = b[9] | 0; - var bl9 = b9 & 0x1fff; - var bh9 = b9 >>> 13; + /** + * Reads a LEB128-encoded signed integer from the current position in the + * buffer. Allows any integer that can be safely represented by JavaScript + * (between -(2^53 - 1) and 2^53 - 1), throws an exception outside of that range. + */ + readInt53() { + const { low32, high32 } = this.readInt64() + if (high32 < -0x200000 || (high32 === -0x200000 && low32 === 0) || high32 > 0x1fffff) { + throw new RangeError('number out of range') + } + return high32 * 0x100000000 + low32 + } - out.negative = self.negative ^ num.negative; - out.length = 19; - /* k = 0 */ - lo = Math.imul(al0, bl0); - mid = Math.imul(al0, bh0); - mid = (mid + Math.imul(ah0, bl0)) | 0; - hi = Math.imul(ah0, bh0); - var w0 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w0 >>> 26)) | 0; - w0 &= 0x3ffffff; - /* k = 1 */ - lo = Math.imul(al1, bl0); - mid = Math.imul(al1, bh0); - mid = (mid + Math.imul(ah1, bl0)) | 0; - hi = Math.imul(ah1, bh0); - lo = (lo + Math.imul(al0, bl1)) | 0; - mid = (mid + Math.imul(al0, bh1)) | 0; - mid = (mid + Math.imul(ah0, bl1)) | 0; - hi = (hi + Math.imul(ah0, bh1)) | 0; - var w1 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w1 >>> 26)) | 0; - w1 &= 0x3ffffff; - /* k = 2 */ - lo = Math.imul(al2, bl0); - mid = Math.imul(al2, bh0); - mid = (mid + Math.imul(ah2, bl0)) | 0; - hi = Math.imul(ah2, bh0); - lo = (lo + Math.imul(al1, bl1)) | 0; - mid = (mid + Math.imul(al1, bh1)) | 0; - mid = (mid + Math.imul(ah1, bl1)) | 0; - hi = (hi + Math.imul(ah1, bh1)) | 0; - lo = (lo + Math.imul(al0, bl2)) | 0; - mid = (mid + Math.imul(al0, bh2)) | 0; - mid = (mid + Math.imul(ah0, bl2)) | 0; - hi = (hi + Math.imul(ah0, bh2)) | 0; - var w2 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w2 >>> 26)) | 0; - w2 &= 0x3ffffff; - /* k = 3 */ - lo = Math.imul(al3, bl0); - mid = Math.imul(al3, bh0); - mid = (mid + Math.imul(ah3, bl0)) | 0; - hi = Math.imul(ah3, bh0); - lo = (lo + Math.imul(al2, bl1)) | 0; - mid = (mid + Math.imul(al2, bh1)) | 0; - mid = (mid + Math.imul(ah2, bl1)) | 0; - hi = (hi + Math.imul(ah2, bh1)) | 0; - lo = (lo + Math.imul(al1, bl2)) | 0; - mid = (mid + Math.imul(al1, bh2)) | 0; - mid = (mid + Math.imul(ah1, bl2)) | 0; - hi = (hi + Math.imul(ah1, bh2)) | 0; - lo = (lo + Math.imul(al0, bl3)) | 0; - mid = (mid + Math.imul(al0, bh3)) | 0; - mid = (mid + Math.imul(ah0, bl3)) | 0; - hi = (hi + Math.imul(ah0, bh3)) | 0; - var w3 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w3 >>> 26)) | 0; - w3 &= 0x3ffffff; - /* k = 4 */ - lo = Math.imul(al4, bl0); - mid = Math.imul(al4, bh0); - mid = (mid + Math.imul(ah4, bl0)) | 0; - hi = Math.imul(ah4, bh0); - lo = (lo + Math.imul(al3, bl1)) | 0; - mid = (mid + Math.imul(al3, bh1)) | 0; - mid = (mid + Math.imul(ah3, bl1)) | 0; - hi = (hi + Math.imul(ah3, bh1)) | 0; - lo = (lo + Math.imul(al2, bl2)) | 0; - mid = (mid + Math.imul(al2, bh2)) | 0; - mid = (mid + Math.imul(ah2, bl2)) | 0; - hi = (hi + Math.imul(ah2, bh2)) | 0; - lo = (lo + Math.imul(al1, bl3)) | 0; - mid = (mid + Math.imul(al1, bh3)) | 0; - mid = (mid + Math.imul(ah1, bl3)) | 0; - hi = (hi + Math.imul(ah1, bh3)) | 0; - lo = (lo + Math.imul(al0, bl4)) | 0; - mid = (mid + Math.imul(al0, bh4)) | 0; - mid = (mid + Math.imul(ah0, bl4)) | 0; - hi = (hi + Math.imul(ah0, bh4)) | 0; - var w4 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w4 >>> 26)) | 0; - w4 &= 0x3ffffff; - /* k = 5 */ - lo = Math.imul(al5, bl0); - mid = Math.imul(al5, bh0); - mid = (mid + Math.imul(ah5, bl0)) | 0; - hi = Math.imul(ah5, bh0); - lo = (lo + Math.imul(al4, bl1)) | 0; - mid = (mid + Math.imul(al4, bh1)) | 0; - mid = (mid + Math.imul(ah4, bl1)) | 0; - hi = (hi + Math.imul(ah4, bh1)) | 0; - lo = (lo + Math.imul(al3, bl2)) | 0; - mid = (mid + Math.imul(al3, bh2)) | 0; - mid = (mid + Math.imul(ah3, bl2)) | 0; - hi = (hi + Math.imul(ah3, bh2)) | 0; - lo = (lo + Math.imul(al2, bl3)) | 0; - mid = (mid + Math.imul(al2, bh3)) | 0; - mid = (mid + Math.imul(ah2, bl3)) | 0; - hi = (hi + Math.imul(ah2, bh3)) | 0; - lo = (lo + Math.imul(al1, bl4)) | 0; - mid = (mid + Math.imul(al1, bh4)) | 0; - mid = (mid + Math.imul(ah1, bl4)) | 0; - hi = (hi + Math.imul(ah1, bh4)) | 0; - lo = (lo + Math.imul(al0, bl5)) | 0; - mid = (mid + Math.imul(al0, bh5)) | 0; - mid = (mid + Math.imul(ah0, bl5)) | 0; - hi = (hi + Math.imul(ah0, bh5)) | 0; - var w5 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w5 >>> 26)) | 0; - w5 &= 0x3ffffff; - /* k = 6 */ - lo = Math.imul(al6, bl0); - mid = Math.imul(al6, bh0); - mid = (mid + Math.imul(ah6, bl0)) | 0; - hi = Math.imul(ah6, bh0); - lo = (lo + Math.imul(al5, bl1)) | 0; - mid = (mid + Math.imul(al5, bh1)) | 0; - mid = (mid + Math.imul(ah5, bl1)) | 0; - hi = (hi + Math.imul(ah5, bh1)) | 0; - lo = (lo + Math.imul(al4, bl2)) | 0; - mid = (mid + Math.imul(al4, bh2)) | 0; - mid = (mid + Math.imul(ah4, bl2)) | 0; - hi = (hi + Math.imul(ah4, bh2)) | 0; - lo = (lo + Math.imul(al3, bl3)) | 0; - mid = (mid + Math.imul(al3, bh3)) | 0; - mid = (mid + Math.imul(ah3, bl3)) | 0; - hi = (hi + Math.imul(ah3, bh3)) | 0; - lo = (lo + Math.imul(al2, bl4)) | 0; - mid = (mid + Math.imul(al2, bh4)) | 0; - mid = (mid + Math.imul(ah2, bl4)) | 0; - hi = (hi + Math.imul(ah2, bh4)) | 0; - lo = (lo + Math.imul(al1, bl5)) | 0; - mid = (mid + Math.imul(al1, bh5)) | 0; - mid = (mid + Math.imul(ah1, bl5)) | 0; - hi = (hi + Math.imul(ah1, bh5)) | 0; - lo = (lo + Math.imul(al0, bl6)) | 0; - mid = (mid + Math.imul(al0, bh6)) | 0; - mid = (mid + Math.imul(ah0, bl6)) | 0; - hi = (hi + Math.imul(ah0, bh6)) | 0; - var w6 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w6 >>> 26)) | 0; - w6 &= 0x3ffffff; - /* k = 7 */ - lo = Math.imul(al7, bl0); - mid = Math.imul(al7, bh0); - mid = (mid + Math.imul(ah7, bl0)) | 0; - hi = Math.imul(ah7, bh0); - lo = (lo + Math.imul(al6, bl1)) | 0; - mid = (mid + Math.imul(al6, bh1)) | 0; - mid = (mid + Math.imul(ah6, bl1)) | 0; - hi = (hi + Math.imul(ah6, bh1)) | 0; - lo = (lo + Math.imul(al5, bl2)) | 0; - mid = (mid + Math.imul(al5, bh2)) | 0; - mid = (mid + Math.imul(ah5, bl2)) | 0; - hi = (hi + Math.imul(ah5, bh2)) | 0; - lo = (lo + Math.imul(al4, bl3)) | 0; - mid = (mid + Math.imul(al4, bh3)) | 0; - mid = (mid + Math.imul(ah4, bl3)) | 0; - hi = (hi + Math.imul(ah4, bh3)) | 0; - lo = (lo + Math.imul(al3, bl4)) | 0; - mid = (mid + Math.imul(al3, bh4)) | 0; - mid = (mid + Math.imul(ah3, bl4)) | 0; - hi = (hi + Math.imul(ah3, bh4)) | 0; - lo = (lo + Math.imul(al2, bl5)) | 0; - mid = (mid + Math.imul(al2, bh5)) | 0; - mid = (mid + Math.imul(ah2, bl5)) | 0; - hi = (hi + Math.imul(ah2, bh5)) | 0; - lo = (lo + Math.imul(al1, bl6)) | 0; - mid = (mid + Math.imul(al1, bh6)) | 0; - mid = (mid + Math.imul(ah1, bl6)) | 0; - hi = (hi + Math.imul(ah1, bh6)) | 0; - lo = (lo + Math.imul(al0, bl7)) | 0; - mid = (mid + Math.imul(al0, bh7)) | 0; - mid = (mid + Math.imul(ah0, bl7)) | 0; - hi = (hi + Math.imul(ah0, bh7)) | 0; - var w7 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w7 >>> 26)) | 0; - w7 &= 0x3ffffff; - /* k = 8 */ - lo = Math.imul(al8, bl0); - mid = Math.imul(al8, bh0); - mid = (mid + Math.imul(ah8, bl0)) | 0; - hi = Math.imul(ah8, bh0); - lo = (lo + Math.imul(al7, bl1)) | 0; - mid = (mid + Math.imul(al7, bh1)) | 0; - mid = (mid + Math.imul(ah7, bl1)) | 0; - hi = (hi + Math.imul(ah7, bh1)) | 0; - lo = (lo + Math.imul(al6, bl2)) | 0; - mid = (mid + Math.imul(al6, bh2)) | 0; - mid = (mid + Math.imul(ah6, bl2)) | 0; - hi = (hi + Math.imul(ah6, bh2)) | 0; - lo = (lo + Math.imul(al5, bl3)) | 0; - mid = (mid + Math.imul(al5, bh3)) | 0; - mid = (mid + Math.imul(ah5, bl3)) | 0; - hi = (hi + Math.imul(ah5, bh3)) | 0; - lo = (lo + Math.imul(al4, bl4)) | 0; - mid = (mid + Math.imul(al4, bh4)) | 0; - mid = (mid + Math.imul(ah4, bl4)) | 0; - hi = (hi + Math.imul(ah4, bh4)) | 0; - lo = (lo + Math.imul(al3, bl5)) | 0; - mid = (mid + Math.imul(al3, bh5)) | 0; - mid = (mid + Math.imul(ah3, bl5)) | 0; - hi = (hi + Math.imul(ah3, bh5)) | 0; - lo = (lo + Math.imul(al2, bl6)) | 0; - mid = (mid + Math.imul(al2, bh6)) | 0; - mid = (mid + Math.imul(ah2, bl6)) | 0; - hi = (hi + Math.imul(ah2, bh6)) | 0; - lo = (lo + Math.imul(al1, bl7)) | 0; - mid = (mid + Math.imul(al1, bh7)) | 0; - mid = (mid + Math.imul(ah1, bl7)) | 0; - hi = (hi + Math.imul(ah1, bh7)) | 0; - lo = (lo + Math.imul(al0, bl8)) | 0; - mid = (mid + Math.imul(al0, bh8)) | 0; - mid = (mid + Math.imul(ah0, bl8)) | 0; - hi = (hi + Math.imul(ah0, bh8)) | 0; - var w8 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w8 >>> 26)) | 0; - w8 &= 0x3ffffff; - /* k = 9 */ - lo = Math.imul(al9, bl0); - mid = Math.imul(al9, bh0); - mid = (mid + Math.imul(ah9, bl0)) | 0; - hi = Math.imul(ah9, bh0); - lo = (lo + Math.imul(al8, bl1)) | 0; - mid = (mid + Math.imul(al8, bh1)) | 0; - mid = (mid + Math.imul(ah8, bl1)) | 0; - hi = (hi + Math.imul(ah8, bh1)) | 0; - lo = (lo + Math.imul(al7, bl2)) | 0; - mid = (mid + Math.imul(al7, bh2)) | 0; - mid = (mid + Math.imul(ah7, bl2)) | 0; - hi = (hi + Math.imul(ah7, bh2)) | 0; - lo = (lo + Math.imul(al6, bl3)) | 0; - mid = (mid + Math.imul(al6, bh3)) | 0; - mid = (mid + Math.imul(ah6, bl3)) | 0; - hi = (hi + Math.imul(ah6, bh3)) | 0; - lo = (lo + Math.imul(al5, bl4)) | 0; - mid = (mid + Math.imul(al5, bh4)) | 0; - mid = (mid + Math.imul(ah5, bl4)) | 0; - hi = (hi + Math.imul(ah5, bh4)) | 0; - lo = (lo + Math.imul(al4, bl5)) | 0; - mid = (mid + Math.imul(al4, bh5)) | 0; - mid = (mid + Math.imul(ah4, bl5)) | 0; - hi = (hi + Math.imul(ah4, bh5)) | 0; - lo = (lo + Math.imul(al3, bl6)) | 0; - mid = (mid + Math.imul(al3, bh6)) | 0; - mid = (mid + Math.imul(ah3, bl6)) | 0; - hi = (hi + Math.imul(ah3, bh6)) | 0; - lo = (lo + Math.imul(al2, bl7)) | 0; - mid = (mid + Math.imul(al2, bh7)) | 0; - mid = (mid + Math.imul(ah2, bl7)) | 0; - hi = (hi + Math.imul(ah2, bh7)) | 0; - lo = (lo + Math.imul(al1, bl8)) | 0; - mid = (mid + Math.imul(al1, bh8)) | 0; - mid = (mid + Math.imul(ah1, bl8)) | 0; - hi = (hi + Math.imul(ah1, bh8)) | 0; - lo = (lo + Math.imul(al0, bl9)) | 0; - mid = (mid + Math.imul(al0, bh9)) | 0; - mid = (mid + Math.imul(ah0, bl9)) | 0; - hi = (hi + Math.imul(ah0, bh9)) | 0; - var w9 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w9 >>> 26)) | 0; - w9 &= 0x3ffffff; - /* k = 10 */ - lo = Math.imul(al9, bl1); - mid = Math.imul(al9, bh1); - mid = (mid + Math.imul(ah9, bl1)) | 0; - hi = Math.imul(ah9, bh1); - lo = (lo + Math.imul(al8, bl2)) | 0; - mid = (mid + Math.imul(al8, bh2)) | 0; - mid = (mid + Math.imul(ah8, bl2)) | 0; - hi = (hi + Math.imul(ah8, bh2)) | 0; - lo = (lo + Math.imul(al7, bl3)) | 0; - mid = (mid + Math.imul(al7, bh3)) | 0; - mid = (mid + Math.imul(ah7, bl3)) | 0; - hi = (hi + Math.imul(ah7, bh3)) | 0; - lo = (lo + Math.imul(al6, bl4)) | 0; - mid = (mid + Math.imul(al6, bh4)) | 0; - mid = (mid + Math.imul(ah6, bl4)) | 0; - hi = (hi + Math.imul(ah6, bh4)) | 0; - lo = (lo + Math.imul(al5, bl5)) | 0; - mid = (mid + Math.imul(al5, bh5)) | 0; - mid = (mid + Math.imul(ah5, bl5)) | 0; - hi = (hi + Math.imul(ah5, bh5)) | 0; - lo = (lo + Math.imul(al4, bl6)) | 0; - mid = (mid + Math.imul(al4, bh6)) | 0; - mid = (mid + Math.imul(ah4, bl6)) | 0; - hi = (hi + Math.imul(ah4, bh6)) | 0; - lo = (lo + Math.imul(al3, bl7)) | 0; - mid = (mid + Math.imul(al3, bh7)) | 0; - mid = (mid + Math.imul(ah3, bl7)) | 0; - hi = (hi + Math.imul(ah3, bh7)) | 0; - lo = (lo + Math.imul(al2, bl8)) | 0; - mid = (mid + Math.imul(al2, bh8)) | 0; - mid = (mid + Math.imul(ah2, bl8)) | 0; - hi = (hi + Math.imul(ah2, bh8)) | 0; - lo = (lo + Math.imul(al1, bl9)) | 0; - mid = (mid + Math.imul(al1, bh9)) | 0; - mid = (mid + Math.imul(ah1, bl9)) | 0; - hi = (hi + Math.imul(ah1, bh9)) | 0; - var w10 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w10 >>> 26)) | 0; - w10 &= 0x3ffffff; - /* k = 11 */ - lo = Math.imul(al9, bl2); - mid = Math.imul(al9, bh2); - mid = (mid + Math.imul(ah9, bl2)) | 0; - hi = Math.imul(ah9, bh2); - lo = (lo + Math.imul(al8, bl3)) | 0; - mid = (mid + Math.imul(al8, bh3)) | 0; - mid = (mid + Math.imul(ah8, bl3)) | 0; - hi = (hi + Math.imul(ah8, bh3)) | 0; - lo = (lo + Math.imul(al7, bl4)) | 0; - mid = (mid + Math.imul(al7, bh4)) | 0; - mid = (mid + Math.imul(ah7, bl4)) | 0; - hi = (hi + Math.imul(ah7, bh4)) | 0; - lo = (lo + Math.imul(al6, bl5)) | 0; - mid = (mid + Math.imul(al6, bh5)) | 0; - mid = (mid + Math.imul(ah6, bl5)) | 0; - hi = (hi + Math.imul(ah6, bh5)) | 0; - lo = (lo + Math.imul(al5, bl6)) | 0; - mid = (mid + Math.imul(al5, bh6)) | 0; - mid = (mid + Math.imul(ah5, bl6)) | 0; - hi = (hi + Math.imul(ah5, bh6)) | 0; - lo = (lo + Math.imul(al4, bl7)) | 0; - mid = (mid + Math.imul(al4, bh7)) | 0; - mid = (mid + Math.imul(ah4, bl7)) | 0; - hi = (hi + Math.imul(ah4, bh7)) | 0; - lo = (lo + Math.imul(al3, bl8)) | 0; - mid = (mid + Math.imul(al3, bh8)) | 0; - mid = (mid + Math.imul(ah3, bl8)) | 0; - hi = (hi + Math.imul(ah3, bh8)) | 0; - lo = (lo + Math.imul(al2, bl9)) | 0; - mid = (mid + Math.imul(al2, bh9)) | 0; - mid = (mid + Math.imul(ah2, bl9)) | 0; - hi = (hi + Math.imul(ah2, bh9)) | 0; - var w11 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w11 >>> 26)) | 0; - w11 &= 0x3ffffff; - /* k = 12 */ - lo = Math.imul(al9, bl3); - mid = Math.imul(al9, bh3); - mid = (mid + Math.imul(ah9, bl3)) | 0; - hi = Math.imul(ah9, bh3); - lo = (lo + Math.imul(al8, bl4)) | 0; - mid = (mid + Math.imul(al8, bh4)) | 0; - mid = (mid + Math.imul(ah8, bl4)) | 0; - hi = (hi + Math.imul(ah8, bh4)) | 0; - lo = (lo + Math.imul(al7, bl5)) | 0; - mid = (mid + Math.imul(al7, bh5)) | 0; - mid = (mid + Math.imul(ah7, bl5)) | 0; - hi = (hi + Math.imul(ah7, bh5)) | 0; - lo = (lo + Math.imul(al6, bl6)) | 0; - mid = (mid + Math.imul(al6, bh6)) | 0; - mid = (mid + Math.imul(ah6, bl6)) | 0; - hi = (hi + Math.imul(ah6, bh6)) | 0; - lo = (lo + Math.imul(al5, bl7)) | 0; - mid = (mid + Math.imul(al5, bh7)) | 0; - mid = (mid + Math.imul(ah5, bl7)) | 0; - hi = (hi + Math.imul(ah5, bh7)) | 0; - lo = (lo + Math.imul(al4, bl8)) | 0; - mid = (mid + Math.imul(al4, bh8)) | 0; - mid = (mid + Math.imul(ah4, bl8)) | 0; - hi = (hi + Math.imul(ah4, bh8)) | 0; - lo = (lo + Math.imul(al3, bl9)) | 0; - mid = (mid + Math.imul(al3, bh9)) | 0; - mid = (mid + Math.imul(ah3, bl9)) | 0; - hi = (hi + Math.imul(ah3, bh9)) | 0; - var w12 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w12 >>> 26)) | 0; - w12 &= 0x3ffffff; - /* k = 13 */ - lo = Math.imul(al9, bl4); - mid = Math.imul(al9, bh4); - mid = (mid + Math.imul(ah9, bl4)) | 0; - hi = Math.imul(ah9, bh4); - lo = (lo + Math.imul(al8, bl5)) | 0; - mid = (mid + Math.imul(al8, bh5)) | 0; - mid = (mid + Math.imul(ah8, bl5)) | 0; - hi = (hi + Math.imul(ah8, bh5)) | 0; - lo = (lo + Math.imul(al7, bl6)) | 0; - mid = (mid + Math.imul(al7, bh6)) | 0; - mid = (mid + Math.imul(ah7, bl6)) | 0; - hi = (hi + Math.imul(ah7, bh6)) | 0; - lo = (lo + Math.imul(al6, bl7)) | 0; - mid = (mid + Math.imul(al6, bh7)) | 0; - mid = (mid + Math.imul(ah6, bl7)) | 0; - hi = (hi + Math.imul(ah6, bh7)) | 0; - lo = (lo + Math.imul(al5, bl8)) | 0; - mid = (mid + Math.imul(al5, bh8)) | 0; - mid = (mid + Math.imul(ah5, bl8)) | 0; - hi = (hi + Math.imul(ah5, bh8)) | 0; - lo = (lo + Math.imul(al4, bl9)) | 0; - mid = (mid + Math.imul(al4, bh9)) | 0; - mid = (mid + Math.imul(ah4, bl9)) | 0; - hi = (hi + Math.imul(ah4, bh9)) | 0; - var w13 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w13 >>> 26)) | 0; - w13 &= 0x3ffffff; - /* k = 14 */ - lo = Math.imul(al9, bl5); - mid = Math.imul(al9, bh5); - mid = (mid + Math.imul(ah9, bl5)) | 0; - hi = Math.imul(ah9, bh5); - lo = (lo + Math.imul(al8, bl6)) | 0; - mid = (mid + Math.imul(al8, bh6)) | 0; - mid = (mid + Math.imul(ah8, bl6)) | 0; - hi = (hi + Math.imul(ah8, bh6)) | 0; - lo = (lo + Math.imul(al7, bl7)) | 0; - mid = (mid + Math.imul(al7, bh7)) | 0; - mid = (mid + Math.imul(ah7, bl7)) | 0; - hi = (hi + Math.imul(ah7, bh7)) | 0; - lo = (lo + Math.imul(al6, bl8)) | 0; - mid = (mid + Math.imul(al6, bh8)) | 0; - mid = (mid + Math.imul(ah6, bl8)) | 0; - hi = (hi + Math.imul(ah6, bh8)) | 0; - lo = (lo + Math.imul(al5, bl9)) | 0; - mid = (mid + Math.imul(al5, bh9)) | 0; - mid = (mid + Math.imul(ah5, bl9)) | 0; - hi = (hi + Math.imul(ah5, bh9)) | 0; - var w14 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w14 >>> 26)) | 0; - w14 &= 0x3ffffff; - /* k = 15 */ - lo = Math.imul(al9, bl6); - mid = Math.imul(al9, bh6); - mid = (mid + Math.imul(ah9, bl6)) | 0; - hi = Math.imul(ah9, bh6); - lo = (lo + Math.imul(al8, bl7)) | 0; - mid = (mid + Math.imul(al8, bh7)) | 0; - mid = (mid + Math.imul(ah8, bl7)) | 0; - hi = (hi + Math.imul(ah8, bh7)) | 0; - lo = (lo + Math.imul(al7, bl8)) | 0; - mid = (mid + Math.imul(al7, bh8)) | 0; - mid = (mid + Math.imul(ah7, bl8)) | 0; - hi = (hi + Math.imul(ah7, bh8)) | 0; - lo = (lo + Math.imul(al6, bl9)) | 0; - mid = (mid + Math.imul(al6, bh9)) | 0; - mid = (mid + Math.imul(ah6, bl9)) | 0; - hi = (hi + Math.imul(ah6, bh9)) | 0; - var w15 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w15 >>> 26)) | 0; - w15 &= 0x3ffffff; - /* k = 16 */ - lo = Math.imul(al9, bl7); - mid = Math.imul(al9, bh7); - mid = (mid + Math.imul(ah9, bl7)) | 0; - hi = Math.imul(ah9, bh7); - lo = (lo + Math.imul(al8, bl8)) | 0; - mid = (mid + Math.imul(al8, bh8)) | 0; - mid = (mid + Math.imul(ah8, bl8)) | 0; - hi = (hi + Math.imul(ah8, bh8)) | 0; - lo = (lo + Math.imul(al7, bl9)) | 0; - mid = (mid + Math.imul(al7, bh9)) | 0; - mid = (mid + Math.imul(ah7, bl9)) | 0; - hi = (hi + Math.imul(ah7, bh9)) | 0; - var w16 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w16 >>> 26)) | 0; - w16 &= 0x3ffffff; - /* k = 17 */ - lo = Math.imul(al9, bl8); - mid = Math.imul(al9, bh8); - mid = (mid + Math.imul(ah9, bl8)) | 0; - hi = Math.imul(ah9, bh8); - lo = (lo + Math.imul(al8, bl9)) | 0; - mid = (mid + Math.imul(al8, bh9)) | 0; - mid = (mid + Math.imul(ah8, bl9)) | 0; - hi = (hi + Math.imul(ah8, bh9)) | 0; - var w17 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w17 >>> 26)) | 0; - w17 &= 0x3ffffff; - /* k = 18 */ - lo = Math.imul(al9, bl9); - mid = Math.imul(al9, bh9); - mid = (mid + Math.imul(ah9, bl9)) | 0; - hi = Math.imul(ah9, bh9); - var w18 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w18 >>> 26)) | 0; - w18 &= 0x3ffffff; - o[0] = w0; - o[1] = w1; - o[2] = w2; - o[3] = w3; - o[4] = w4; - o[5] = w5; - o[6] = w6; - o[7] = w7; - o[8] = w8; - o[9] = w9; - o[10] = w10; - o[11] = w11; - o[12] = w12; - o[13] = w13; - o[14] = w14; - o[15] = w15; - o[16] = w16; - o[17] = w17; - o[18] = w18; - if (c !== 0) { - o[19] = c; - out.length++; + /** + * Reads a LEB128-encoded unsigned integer from the current position in the + * buffer. Throws an exception if the value doesn't fit in a 64-bit unsigned + * int. Returns the number in two 32-bit halves, as an object of the form + * `{high32, low32}`. + */ + readUint64() { + let low32 = 0, high32 = 0, shift = 0 + while (this.offset < this.buf.byteLength && shift <= 28) { + const nextByte = this.buf[this.offset] + low32 = (low32 | (nextByte & 0x7f) << shift) >>> 0 // right shift to interpret value as unsigned + if (shift === 28) { + high32 = (nextByte & 0x70) >>> 4 + } + shift += 7 + this.offset++ + if ((nextByte & 0x80) === 0) return { high32, low32 } } - return out; - }; - // Polyfill comb - if (!Math.imul) { - comb10MulTo = smallMulTo; + shift = 3 + while (this.offset < this.buf.byteLength) { + const nextByte = this.buf[this.offset] + if (shift === 31 && (nextByte & 0xfe) !== 0) { // more than 10 bytes, or value > 2^64 - 1 + throw new RangeError('number out of range') + } + high32 = (high32 | (nextByte & 0x7f) << shift) >>> 0 + shift += 7 + this.offset++ + if ((nextByte & 0x80) === 0) return { high32, low32 } + } + throw new RangeError('buffer ended with incomplete number') } - function bigMulTo (self, num, out) { - out.negative = num.negative ^ self.negative; - out.length = self.length + num.length; - - var carry = 0; - var hncarry = 0; - for (var k = 0; k < out.length - 1; k++) { - // Sum all words with the same `i + j = k` and accumulate `ncarry`, - // note that ncarry could be >= 0x3ffffff - var ncarry = hncarry; - hncarry = 0; - var rword = carry & 0x3ffffff; - var maxJ = Math.min(k, num.length - 1); - for (var j = Math.max(0, k - self.length + 1); j <= maxJ; j++) { - var i = k - j; - var a = self.words[i] | 0; - var b = num.words[j] | 0; - var r = a * b; - - var lo = r & 0x3ffffff; - ncarry = (ncarry + ((r / 0x4000000) | 0)) | 0; - lo = (lo + rword) | 0; - rword = lo & 0x3ffffff; - ncarry = (ncarry + (lo >>> 26)) | 0; + /** + * Reads a LEB128-encoded signed integer from the current position in the + * buffer. Throws an exception if the value doesn't fit in a 64-bit signed + * int. Returns the number in two 32-bit halves, as an object of the form + * `{high32, low32}`. The `low32` half is always non-negative, and the + * sign of the `high32` half indicates the sign of the 64-bit number. + */ + readInt64() { + let low32 = 0, high32 = 0, shift = 0 + while (this.offset < this.buf.byteLength && shift <= 28) { + const nextByte = this.buf[this.offset] + low32 = (low32 | (nextByte & 0x7f) << shift) >>> 0 // right shift to interpret value as unsigned + if (shift === 28) { + high32 = (nextByte & 0x70) >>> 4 + } + shift += 7 + this.offset++ + if ((nextByte & 0x80) === 0) { + if ((nextByte & 0x40) !== 0) { // sign-extend negative integer + if (shift < 32) low32 = (low32 | (-1 << shift)) >>> 0 + high32 |= -1 << Math.max(shift - 32, 0) + } + return { high32, low32 } + } + } - hncarry += ncarry >>> 26; - ncarry &= 0x3ffffff; + shift = 3 + while (this.offset < this.buf.byteLength) { + const nextByte = this.buf[this.offset] + // On the 10th byte there are only two valid values: all 7 value bits zero + // (if the value is positive) or all 7 bits one (if the value is negative) + if (shift === 31 && nextByte !== 0 && nextByte !== 0x7f) { + throw new RangeError('number out of range') + } + high32 |= (nextByte & 0x7f) << shift + shift += 7 + this.offset++ + if ((nextByte & 0x80) === 0) { + if ((nextByte & 0x40) !== 0 && shift < 32) { // sign-extend negative integer + high32 |= -1 << shift + } + return { high32, low32 } } - out.words[k] = rword; - carry = ncarry; - ncarry = hncarry; } - if (carry !== 0) { - out.words[k] = carry; - } else { - out.length--; + throw new RangeError('buffer ended with incomplete number') + } + + /** + * Extracts a subarray `length` bytes in size, starting from the current + * position in the buffer, and moves the position forward. + */ + readRawBytes(length) { + const start = this.offset + if (start + length > this.buf.byteLength) { + throw new RangeError('subarray exceeds buffer size') } + this.offset += length + return this.buf.subarray(start, this.offset) + } - return out.strip(); + /** + * Extracts `length` bytes from the buffer, starting from the current position, + * and returns the UTF-8 string decoding of those bytes. + */ + readRawString(length) { + return utf8ToString(this.readRawBytes(length)) } - function jumboMulTo (self, num, out) { - var fftm = new FFTM(); - return fftm.mulp(self, num, out); + /** + * Extracts a subarray from the current position in the buffer, prefixed with + * its length in bytes (encoded as an unsigned LEB128 integer). + */ + readPrefixedBytes() { + return this.readRawBytes(this.readUint53()) } - BN.prototype.mulTo = function mulTo (num, out) { - var res; - var len = this.length + num.length; - if (this.length === 10 && num.length === 10) { - res = comb10MulTo(this, num, out); - } else if (len < 63) { - res = smallMulTo(this, num, out); - } else if (len < 1024) { - res = bigMulTo(this, num, out); - } else { - res = jumboMulTo(this, num, out); - } + /** + * Reads a UTF-8 string from the current position in the buffer, prefixed with its + * length in bytes (where the length is encoded as an unsigned LEB128 integer). + */ + readPrefixedString() { + return utf8ToString(this.readPrefixedBytes()) + } - return res; - }; + /** + * Reads a byte array from the current position in the buffer, prefixed with its + * length in bytes. Returns that byte array converted to a hexadecimal string. + */ + readHexString() { + return bytesToHexString(this.readPrefixedBytes()) + } +} - // Cooley-Tukey algorithm for FFT - // slightly revisited to rely on looping instead of recursion +/** + * An encoder that uses run-length encoding to compress sequences of repeated + * values. The constructor argument specifies the type of values, which may be + * either 'int', 'uint', or 'utf8'. Besides valid values of the selected + * datatype, values may also be null. + * + * The encoded buffer starts with a LEB128-encoded signed integer, the + * repetition count. The interpretation of the following values depends on this + * repetition count: + * - If this number is a positive value n, the next value in the buffer + * (encoded as the specified datatype) is repeated n times in the sequence. + * - If the repetition count is a negative value -n, then the next n values + * (encoded as the specified datatype) in the buffer are treated as a + * literal, i.e. they appear in the sequence without any further + * interpretation or repetition. + * - If the repetition count is zero, then the next value in the buffer is a + * LEB128-encoded unsigned integer indicating the number of null values + * that appear at the current position in the sequence. + * + * After one of these three has completed, the process repeats, starting again + * with a repetition count, until we reach the end of the buffer. + */ +class RLEEncoder extends Encoder { + constructor(type) { + super() + this.type = type + this.state = 'empty' + this.lastValue = undefined + this.count = 0 + this.literal = [] + } - function FFTM (x, y) { - this.x = x; - this.y = y; + /** + * Appends a new value to the sequence. If `repetitions` is given, the value is repeated + * `repetitions` times. + */ + appendValue(value, repetitions = 1) { + this._appendValue(value, repetitions) } - FFTM.prototype.makeRBT = function makeRBT (N) { - var t = new Array(N); - var l = BN.prototype._countBits(N) - 1; - for (var i = 0; i < N; i++) { - t[i] = this.revBin(i, l, N); + /** + * Like `appendValue()`, but this method is not overridden by `DeltaEncoder`. + */ + _appendValue(value, repetitions = 1) { + if (repetitions <= 0) return + if (this.state === 'empty') { + this.state = (value === null ? 'nulls' : (repetitions === 1 ? 'loneValue' : 'repetition')) + this.lastValue = value + this.count = repetitions + } else if (this.state === 'loneValue') { + if (value === null) { + this.flush() + this.state = 'nulls' + this.count = repetitions + } else if (value === this.lastValue) { + this.state = 'repetition' + this.count = 1 + repetitions + } else if (repetitions > 1) { + this.flush() + this.state = 'repetition' + this.count = repetitions + this.lastValue = value + } else { + this.state = 'literal' + this.literal = [this.lastValue] + this.lastValue = value + } + } else if (this.state === 'repetition') { + if (value === null) { + this.flush() + this.state = 'nulls' + this.count = repetitions + } else if (value === this.lastValue) { + this.count += repetitions + } else if (repetitions > 1) { + this.flush() + this.state = 'repetition' + this.count = repetitions + this.lastValue = value + } else { + this.flush() + this.state = 'loneValue' + this.lastValue = value + } + } else if (this.state === 'literal') { + if (value === null) { + this.literal.push(this.lastValue) + this.flush() + this.state = 'nulls' + this.count = repetitions + } else if (value === this.lastValue) { + this.flush() + this.state = 'repetition' + this.count = 1 + repetitions + } else if (repetitions > 1) { + this.literal.push(this.lastValue) + this.flush() + this.state = 'repetition' + this.count = repetitions + this.lastValue = value + } else { + this.literal.push(this.lastValue) + this.lastValue = value + } + } else if (this.state === 'nulls') { + if (value === null) { + this.count += repetitions + } else if (repetitions > 1) { + this.flush() + this.state = 'repetition' + this.count = repetitions + this.lastValue = value + } else { + this.flush() + this.state = 'loneValue' + this.lastValue = value + } } + } - return t; - }; - - // Returns binary-reversed representation of `x` - FFTM.prototype.revBin = function revBin (x, l, N) { - if (x === 0 || x === N - 1) return x; - - var rb = 0; - for (var i = 0; i < l; i++) { - rb |= (x & 1) << (l - i - 1); - x >>= 1; + /** + * Copies values from the RLEDecoder `decoder` into this encoder. The `options` object may + * contain the following keys: + * - `count`: The number of values to copy. If not specified, copies all remaining values. + * - `sumValues`: If true, the function computes the sum of all numeric values as they are + * copied (null values are counted as zero), and returns that number. + * - `sumShift`: If set, values are shifted right by `sumShift` bits before adding to the sum. + * + * Returns an object of the form `{nonNullValues, sum}` where `nonNullValues` is the number of + * non-null values copied, and `sum` is the sum (only if the `sumValues` option is set). + */ + copyFrom(decoder, options = {}) { + const { count, sumValues, sumShift } = options + if (!(decoder instanceof RLEDecoder) || (decoder.type !== this.type)) { + throw new TypeError('incompatible type of decoder') } + let remaining = (typeof count === 'number' ? count : Number.MAX_SAFE_INTEGER) + let nonNullValues = 0, sum = 0 + if (count && remaining > 0 && decoder.done) throw new RangeError(`cannot copy ${count} values`) + if (remaining === 0 || decoder.done) return sumValues ? {nonNullValues, sum} : {nonNullValues} - return rb; - }; - - // Performs "tweedling" phase, therefore 'emulating' - // behaviour of the recursive algorithm - FFTM.prototype.permute = function permute (rbt, rws, iws, rtws, itws, N) { - for (var i = 0; i < N; i++) { - rtws[i] = rws[rbt[i]]; - itws[i] = iws[rbt[i]]; + // Copy a value so that we have a well-defined starting state. NB: when super.copyFrom() is + // called by the DeltaEncoder subclass, the following calls to readValue() and appendValue() + // refer to the overridden methods, while later readRecord(), readRawValue() and _appendValue() + // calls refer to the non-overridden RLEDecoder/RLEEncoder methods. + let firstValue = decoder.readValue() + if (firstValue === null) { + const numNulls = Math.min(decoder.count + 1, remaining) + remaining -= numNulls + decoder.count -= numNulls - 1 + this.appendValue(null, numNulls) + if (count && remaining > 0 && decoder.done) throw new RangeError(`cannot copy ${count} values`) + if (remaining === 0 || decoder.done) return sumValues ? {nonNullValues, sum} : {nonNullValues} + firstValue = decoder.readValue() + if (firstValue === null) throw new RangeError('null run must be followed by non-null value') } - }; - - FFTM.prototype.transform = function transform (rws, iws, rtws, itws, N, rbt) { - this.permute(rbt, rws, iws, rtws, itws, N); - - for (var s = 1; s < N; s <<= 1) { - var l = s << 1; - - var rtwdf = Math.cos(2 * Math.PI / l); - var itwdf = Math.sin(2 * Math.PI / l); - - for (var p = 0; p < N; p += l) { - var rtwdf_ = rtwdf; - var itwdf_ = itwdf; - - for (var j = 0; j < s; j++) { - var re = rtws[p + j]; - var ie = itws[p + j]; - - var ro = rtws[p + j + s]; - var io = itws[p + j + s]; - - var rx = rtwdf_ * ro - itwdf_ * io; - - io = rtwdf_ * io + itwdf_ * ro; - ro = rx; - - rtws[p + j] = re + ro; - itws[p + j] = ie + io; - - rtws[p + j + s] = re - ro; - itws[p + j + s] = ie - io; + this.appendValue(firstValue) + remaining-- + nonNullValues++ + if (sumValues) sum += (sumShift ? (firstValue >>> sumShift) : firstValue) + if (count && remaining > 0 && decoder.done) throw new RangeError(`cannot copy ${count} values`) + if (remaining === 0 || decoder.done) return sumValues ? {nonNullValues, sum} : {nonNullValues} - /* jshint maxdepth : false */ - if (j !== l) { - rx = rtwdf * rtwdf_ - itwdf * itwdf_; + // Copy data at the record level without expanding repetitions + let firstRun = (decoder.count > 0) + while (remaining > 0 && !decoder.done) { + if (!firstRun) decoder.readRecord() + const numValues = Math.min(decoder.count, remaining) + decoder.count -= numValues - itwdf_ = rtwdf * itwdf_ + itwdf * rtwdf_; - rtwdf_ = rx; - } + if (decoder.state === 'literal') { + nonNullValues += numValues + for (let i = 0; i < numValues; i++) { + if (decoder.done) throw new RangeError('incomplete literal') + const value = decoder.readRawValue() + if (value === decoder.lastValue) throw new RangeError('Repetition of values is not allowed in literal') + decoder.lastValue = value + this._appendValue(value) + if (sumValues) sum += (sumShift ? (value >>> sumShift) : value) } + } else if (decoder.state === 'repetition') { + nonNullValues += numValues + if (sumValues) sum += numValues * (sumShift ? (decoder.lastValue >>> sumShift) : decoder.lastValue) + const value = decoder.lastValue + this._appendValue(value) + if (numValues > 1) { + this._appendValue(value) + if (this.state !== 'repetition') throw new RangeError(`Unexpected state ${this.state}`) + this.count += numValues - 2 + } + } else if (decoder.state === 'nulls') { + this._appendValue(null) + if (this.state !== 'nulls') throw new RangeError(`Unexpected state ${this.state}`) + this.count += numValues - 1 } + + firstRun = false + remaining -= numValues } - }; + if (count && remaining > 0 && decoder.done) throw new RangeError(`cannot copy ${count} values`) + return sumValues ? {nonNullValues, sum} : {nonNullValues} + } - FFTM.prototype.guessLen13b = function guessLen13b (n, m) { - var N = Math.max(m, n) | 1; - var odd = N & 1; - var i = 0; - for (N = N / 2 | 0; N; N = N >>> 1) { - i++; + /** + * Private method, do not call from outside the class. + */ + flush() { + if (this.state === 'loneValue') { + this.appendInt32(-1) + this.appendRawValue(this.lastValue) + } else if (this.state === 'repetition') { + this.appendInt53(this.count) + this.appendRawValue(this.lastValue) + } else if (this.state === 'literal') { + this.appendInt53(-this.literal.length) + for (let v of this.literal) this.appendRawValue(v) + } else if (this.state === 'nulls') { + this.appendInt32(0) + this.appendUint53(this.count) } + this.state = 'empty' + } - return 1 << i + 1 + odd; - }; + /** + * Private method, do not call from outside the class. + */ + appendRawValue(value) { + if (this.type === 'int') { + this.appendInt53(value) + } else if (this.type === 'uint') { + this.appendUint53(value) + } else if (this.type === 'utf8') { + this.appendPrefixedString(value) + } else { + throw new RangeError(`Unknown RLEEncoder datatype: ${this.type}`) + } + } - FFTM.prototype.conjugate = function conjugate (rws, iws, N) { - if (N <= 1) return; + /** + * Flushes any unwritten data to the buffer. Call this before reading from + * the buffer constructed by this Encoder. + */ + finish() { + if (this.state === 'literal') this.literal.push(this.lastValue) + // Don't write anything if the only values we have seen are nulls + if (this.state !== 'nulls' || this.offset > 0) this.flush() + } +} - for (var i = 0; i < N / 2; i++) { - var t = rws[i]; +/** + * Counterpart to RLEEncoder: reads values from an RLE-compressed sequence, + * returning nulls and repeated values as required. + */ +class RLEDecoder extends Decoder { + constructor(type, buffer) { + super(buffer) + this.type = type + this.lastValue = undefined + this.count = 0 + this.state = undefined + } - rws[i] = rws[N - i - 1]; - rws[N - i - 1] = t; + /** + * Returns false if there is still data to be read at the current decoding + * position, and true if we are at the end of the buffer. + */ + get done() { + return (this.count === 0) && (this.offset === this.buf.byteLength) + } - t = iws[i]; + /** + * Resets the cursor position, so that the next read goes back to the + * beginning of the buffer. + */ + reset() { + this.offset = 0 + this.lastValue = undefined + this.count = 0 + this.state = undefined + } - iws[i] = -iws[N - i - 1]; - iws[N - i - 1] = -t; + /** + * Returns the next value (or null) in the sequence. + */ + readValue() { + if (this.done) return null + if (this.count === 0) this.readRecord() + this.count -= 1 + if (this.state === 'literal') { + const value = this.readRawValue() + if (value === this.lastValue) throw new RangeError('Repetition of values is not allowed in literal') + this.lastValue = value + return value + } else { + return this.lastValue } - }; + } - FFTM.prototype.normalize13b = function normalize13b (ws, N) { - var carry = 0; - for (var i = 0; i < N / 2; i++) { - var w = Math.round(ws[2 * i + 1] / N) * 0x2000 + - Math.round(ws[2 * i] / N) + - carry; + /** + * Discards the next `numSkip` values in the sequence. + */ + skipValues(numSkip) { + while (numSkip > 0 && !this.done) { + if (this.count === 0) { + this.count = this.readInt53() + if (this.count > 0) { + this.lastValue = (this.count <= numSkip) ? this.skipRawValues(1) : this.readRawValue() + this.state = 'repetition' + } else if (this.count < 0) { + this.count = -this.count + this.state = 'literal' + } else { // this.count == 0 + this.count = this.readUint53() + this.lastValue = null + this.state = 'nulls' + } + } - ws[i] = w & 0x3ffffff; + const consume = Math.min(numSkip, this.count) + if (this.state === 'literal') this.skipRawValues(consume) + numSkip -= consume + this.count -= consume + } + } - if (w < 0x4000000) { - carry = 0; - } else { - carry = w / 0x4000000 | 0; + /** + * Private method, do not call from outside the class. + * Reads a repetition count from the buffer and sets up the state appropriately. + */ + readRecord() { + this.count = this.readInt53() + if (this.count > 1) { + const value = this.readRawValue() + if ((this.state === 'repetition' || this.state === 'literal') && this.lastValue === value) { + throw new RangeError('Successive repetitions with the same value are not allowed') } + this.state = 'repetition' + this.lastValue = value + } else if (this.count === 1) { + throw new RangeError('Repetition count of 1 is not allowed, use a literal instead') + } else if (this.count < 0) { + this.count = -this.count + if (this.state === 'literal') throw new RangeError('Successive literals are not allowed') + this.state = 'literal' + } else { // this.count == 0 + if (this.state === 'nulls') throw new RangeError('Successive null runs are not allowed') + this.count = this.readUint53() + if (this.count === 0) throw new RangeError('Zero-length null runs are not allowed') + this.lastValue = null + this.state = 'nulls' } + } - return ws; - }; - - FFTM.prototype.convert13b = function convert13b (ws, len, rws, N) { - var carry = 0; - for (var i = 0; i < len; i++) { - carry = carry + (ws[i] | 0); - - rws[2 * i] = carry & 0x1fff; carry = carry >>> 13; - rws[2 * i + 1] = carry & 0x1fff; carry = carry >>> 13; + /** + * Private method, do not call from outside the class. + * Reads one value of the datatype configured on construction. + */ + readRawValue() { + if (this.type === 'int') { + return this.readInt53() + } else if (this.type === 'uint') { + return this.readUint53() + } else if (this.type === 'utf8') { + return this.readPrefixedString() + } else { + throw new RangeError(`Unknown RLEDecoder datatype: ${this.type}`) } + } - // Pad with zeroes - for (i = 2 * len; i < N; ++i) { - rws[i] = 0; + /** + * Private method, do not call from outside the class. + * Skips over `num` values of the datatype configured on construction. + */ + skipRawValues(num) { + if (this.type === 'utf8') { + for (let i = 0; i < num; i++) this.skip(this.readUint53()) + } else { + while (num > 0 && this.offset < this.buf.byteLength) { + if ((this.buf[this.offset] & 0x80) === 0) num-- + this.offset++ + } + if (num > 0) throw new RangeError('cannot skip beyond end of buffer') } + } +} - assert(carry === 0); - assert((carry & ~0x1fff) === 0); - }; +/** + * A variant of RLEEncoder: rather than storing the actual values passed to + * appendValue(), this version stores only the first value, and for all + * subsequent values it stores the difference to the previous value. This + * encoding is good when values tend to come in sequentially incrementing runs, + * because the delta between successive values is 1, and repeated values of 1 + * are easily compressed with run-length encoding. + * + * Null values are also allowed, as with RLEEncoder. + */ +class DeltaEncoder extends RLEEncoder { + constructor() { + super('int') + this.absoluteValue = 0 + } - FFTM.prototype.stub = function stub (N) { - var ph = new Array(N); - for (var i = 0; i < N; i++) { - ph[i] = 0; + /** + * Appends a new integer value to the sequence. If `repetitions` is given, the value is repeated + * `repetitions` times. + */ + appendValue(value, repetitions = 1) { + if (repetitions <= 0) return + if (typeof value === 'number') { + super.appendValue(value - this.absoluteValue, 1) + this.absoluteValue = value + if (repetitions > 1) super.appendValue(0, repetitions - 1) + } else { + super.appendValue(value, repetitions) } + } - return ph; - }; - - FFTM.prototype.mulp = function mulp (x, y, out) { - var N = 2 * this.guessLen13b(x.length, y.length); - - var rbt = this.makeRBT(N); - - var _ = this.stub(N); - - var rws = new Array(N); - var rwst = new Array(N); - var iwst = new Array(N); - - var nrws = new Array(N); - var nrwst = new Array(N); - var niwst = new Array(N); - - var rmws = out.words; - rmws.length = N; + /** + * Copies values from the DeltaDecoder `decoder` into this encoder. The `options` object may + * contain the key `count`, indicating the number of values to copy. If not specified, copies + * all remaining values in the decoder. + */ + copyFrom(decoder, options = {}) { + if (options.sumValues) { + throw new RangeError('unsupported options for DeltaEncoder.copyFrom()') + } + if (!(decoder instanceof DeltaDecoder)) { + throw new TypeError('incompatible type of decoder') + } - this.convert13b(x.words, x.length, rws, N); - this.convert13b(y.words, y.length, nrws, N); + let remaining = options.count + if (remaining > 0 && decoder.done) throw new RangeError(`cannot copy ${remaining} values`) + if (remaining === 0 || decoder.done) return - this.transform(rws, _, rwst, iwst, N, rbt); - this.transform(nrws, _, nrwst, niwst, N, rbt); + // Copy any null values, and the first non-null value, so that appendValue() computes the + // difference between the encoder's last value and the decoder's first (absolute) value. + let value = decoder.readValue(), nulls = 0 + this.appendValue(value) + if (value === null) { + nulls = decoder.count + 1 + if (remaining !== undefined && remaining < nulls) nulls = remaining + decoder.count -= nulls - 1 + this.count += nulls - 1 + if (remaining > nulls && decoder.done) throw new RangeError(`cannot copy ${remaining} values`) + if (remaining === nulls || decoder.done) return - for (var i = 0; i < N; i++) { - var rx = rwst[i] * nrwst[i] - iwst[i] * niwst[i]; - iwst[i] = rwst[i] * niwst[i] + iwst[i] * nrwst[i]; - rwst[i] = rx; + // The next value read is certain to be non-null because we're not at the end of the decoder, + // and a run of nulls must be followed by a run of non-nulls. + if (decoder.count === 0) this.appendValue(decoder.readValue()) } - this.conjugate(rwst, iwst, N); - this.transform(rwst, iwst, rmws, _, N, rbt); - this.conjugate(rmws, _, N); - this.normalize13b(rmws, N); + // Once we have the first value, the subsequent relative values can be copied verbatim without + // any further processing. Note that the first value copied by super.copyFrom() is an absolute + // value, while subsequent values are relative. Thus, the sum of all of the (non-null) copied + // values must equal the absolute value of the final element copied. + if (remaining !== undefined) remaining -= nulls + 1 + const { nonNullValues, sum } = super.copyFrom(decoder, {count: remaining, sumValues: true}) + if (nonNullValues > 0) { + this.absoluteValue = sum + decoder.absoluteValue = sum + } + } +} - out.negative = x.negative ^ y.negative; - out.length = x.length + y.length; - return out.strip(); - }; +/** + * Counterpart to DeltaEncoder: reads values from a delta-compressed sequence of + * numbers (may include null values). + */ +class DeltaDecoder extends RLEDecoder { + constructor(buffer) { + super('int', buffer) + this.absoluteValue = 0 + } - // Multiply `this` by `num` - BN.prototype.mul = function mul (num) { - var out = new BN(null); - out.words = new Array(this.length + num.length); - return this.mulTo(num, out); - }; + /** + * Resets the cursor position, so that the next read goes back to the + * beginning of the buffer. + */ + reset() { + this.offset = 0 + this.lastValue = undefined + this.count = 0 + this.state = undefined + this.absoluteValue = 0 + } - // Multiply employing FFT - BN.prototype.mulf = function mulf (num) { - var out = new BN(null); - out.words = new Array(this.length + num.length); - return jumboMulTo(this, num, out); - }; + /** + * Returns the next integer (or null) value in the sequence. + */ + readValue() { + const value = super.readValue() + if (value === null) return null + this.absoluteValue += value + return this.absoluteValue + } - // In-place Multiplication - BN.prototype.imul = function imul (num) { - return this.clone().mulTo(num, this); - }; + /** + * Discards the next `numSkip` values in the sequence. + */ + skipValues(numSkip) { + while (numSkip > 0 && !this.done) { + if (this.count === 0) this.readRecord() + const consume = Math.min(numSkip, this.count) + if (this.state === 'literal') { + for (let i = 0; i < consume; i++) { + this.lastValue = this.readRawValue() + this.absoluteValue += this.lastValue + } + } else if (this.state === 'repetition') { + this.absoluteValue += consume * this.lastValue + } + numSkip -= consume + this.count -= consume + } + } +} - BN.prototype.imuln = function imuln (num) { - assert(typeof num === 'number'); - assert(num < 0x4000000); +/** + * Encodes a sequence of boolean values by mapping it to a sequence of integers: + * the number of false values, followed by the number of true values, followed + * by the number of false values, and so on. Each number is encoded as a LEB128 + * unsigned integer. This encoding is a bit like RLEEncoder, except that we + * only encode the repetition count but not the actual value, since the values + * just alternate between false and true (starting with false). + */ +class BooleanEncoder extends Encoder { + constructor() { + super() + this.lastValue = false + this.count = 0 + } - // Carry - var carry = 0; - for (var i = 0; i < this.length; i++) { - var w = (this.words[i] | 0) * num; - var lo = (w & 0x3ffffff) + (carry & 0x3ffffff); - carry >>= 26; - carry += (w / 0x4000000) | 0; - // NOTE: lo is 27bit maximum - carry += lo >>> 26; - this.words[i] = lo & 0x3ffffff; + /** + * Appends a new value to the sequence. If `repetitions` is given, the value is repeated + * `repetitions` times. + */ + appendValue(value, repetitions = 1) { + if (value !== false && value !== true) { + throw new RangeError(`Unsupported value for BooleanEncoder: ${value}`) } - - if (carry !== 0) { - this.words[i] = carry; - this.length++; + if (repetitions <= 0) return + if (this.lastValue === value) { + this.count += repetitions + } else { + this.appendUint53(this.count) + this.lastValue = value + this.count = repetitions } + } - return this; - }; - - BN.prototype.muln = function muln (num) { - return this.clone().imuln(num); - }; + /** + * Copies values from the BooleanDecoder `decoder` into this encoder. The `options` object may + * contain the key `count`, indicating the number of values to copy. If not specified, copies + * all remaining values in the decoder. + */ + copyFrom(decoder, options = {}) { + if (!(decoder instanceof BooleanDecoder)) { + throw new TypeError('incompatible type of decoder') + } - // `this` * `this` - BN.prototype.sqr = function sqr () { - return this.mul(this); - }; + const { count } = options + let remaining = (typeof count === 'number' ? count : Number.MAX_SAFE_INTEGER) + if (count && remaining > 0 && decoder.done) throw new RangeError(`cannot copy ${count} values`) + if (remaining === 0 || decoder.done) return - // `this` * `this` in-place - BN.prototype.isqr = function isqr () { - return this.imul(this.clone()); - }; + // Copy one value to bring decoder and encoder state into sync, then finish that value's repetitions + this.appendValue(decoder.readValue()) + remaining-- + const firstCopy = Math.min(decoder.count, remaining) + this.count += firstCopy + decoder.count -= firstCopy + remaining -= firstCopy - // Math.pow(`this`, `num`) - BN.prototype.pow = function pow (num) { - var w = toBitArray(num); - if (w.length === 0) return new BN(1); + while (remaining > 0 && !decoder.done) { + decoder.count = decoder.readUint53() + if (decoder.count === 0) throw new RangeError('Zero-length runs are not allowed') + decoder.lastValue = !decoder.lastValue + this.appendUint53(this.count) - // Skip leading zeroes - var res = this; - for (var i = 0; i < w.length; i++, res = res.sqr()) { - if (w[i] !== 0) break; + const numCopied = Math.min(decoder.count, remaining) + this.count = numCopied + this.lastValue = decoder.lastValue + decoder.count -= numCopied + remaining -= numCopied } - if (++i < w.length) { - for (var q = res.sqr(); i < w.length; i++, q = q.sqr()) { - if (w[i] === 0) continue; + if (count && remaining > 0 && decoder.done) throw new RangeError(`cannot copy ${count} values`) + } - res = res.mul(q); - } + /** + * Flushes any unwritten data to the buffer. Call this before reading from + * the buffer constructed by this Encoder. + */ + finish() { + if (this.count > 0) { + this.appendUint53(this.count) + this.count = 0 } + } +} - return res; - }; - - // Shift-left in-place - BN.prototype.iushln = function iushln (bits) { - assert(typeof bits === 'number' && bits >= 0); - var r = bits % 26; - var s = (bits - r) / 26; - var carryMask = (0x3ffffff >>> (26 - r)) << (26 - r); - var i; +/** + * Counterpart to BooleanEncoder: reads boolean values from a runlength-encoded + * sequence. + */ +class BooleanDecoder extends Decoder { + constructor(buffer) { + super(buffer) + this.lastValue = true // is negated the first time we read a count + this.firstRun = true + this.count = 0 + } - if (r !== 0) { - var carry = 0; + /** + * Returns false if there is still data to be read at the current decoding + * position, and true if we are at the end of the buffer. + */ + get done() { + return (this.count === 0) && (this.offset === this.buf.byteLength) + } - for (i = 0; i < this.length; i++) { - var newCarry = this.words[i] & carryMask; - var c = ((this.words[i] | 0) - newCarry) << r; - this.words[i] = c | carry; - carry = newCarry >>> (26 - r); - } + /** + * Resets the cursor position, so that the next read goes back to the + * beginning of the buffer. + */ + reset() { + this.offset = 0 + this.lastValue = true + this.firstRun = true + this.count = 0 + } - if (carry) { - this.words[i] = carry; - this.length++; + /** + * Returns the next value in the sequence. + */ + readValue() { + if (this.done) return false + while (this.count === 0) { + this.count = this.readUint53() + this.lastValue = !this.lastValue + if (this.count === 0 && !this.firstRun) { + throw new RangeError('Zero-length runs are not allowed') } + this.firstRun = false } + this.count -= 1 + return this.lastValue + } - if (s !== 0) { - for (i = this.length - 1; i >= 0; i--) { - this.words[i + s] = this.words[i]; + /** + * Discards the next `numSkip` values in the sequence. + */ + skipValues(numSkip) { + while (numSkip > 0 && !this.done) { + if (this.count === 0) { + this.count = this.readUint53() + this.lastValue = !this.lastValue + if (this.count === 0 && !this.firstRun) { + throw new RangeError('Zero-length runs are not allowed') + } + this.firstRun = false } - - for (i = 0; i < s; i++) { - this.words[i] = 0; + if (this.count < numSkip) { + numSkip -= this.count + this.count = 0 + } else { + this.count -= numSkip + numSkip = 0 } - - this.length += s; } + } +} - return this.strip(); - }; +module.exports = { + stringToUtf8, utf8ToString, hexStringToBytes, bytesToHexString, + Encoder, Decoder, RLEEncoder, RLEDecoder, DeltaEncoder, DeltaDecoder, BooleanEncoder, BooleanDecoder +} - BN.prototype.ishln = function ishln (bits) { - // TODO(indutny): implement me - assert(this.negative === 0); - return this.iushln(bits); - }; +},{}],51:[function(require,module,exports){ +const { init, clone, free, applyChanges, applyLocalChange, save, load, loadChanges, getPatch, getHeads, getAllChanges, getChanges, getChangesAdded, getChangeByHash, getMissingDeps } = require("./backend") +const { receiveSyncMessage, generateSyncMessage, encodeSyncMessage, decodeSyncMessage, encodeSyncState, decodeSyncState, initSyncState } = require('./sync') - // Shift-right in-place - // NOTE: `hint` is a lowest bit before trailing zeroes - // NOTE: if `extended` is present - it will be filled with destroyed bits - BN.prototype.iushrn = function iushrn (bits, hint, extended) { - assert(typeof bits === 'number' && bits >= 0); - var h; - if (hint) { - h = (hint - (hint % 26)) / 26; - } else { - h = 0; - } +module.exports = { + init, clone, free, applyChanges, applyLocalChange, save, load, loadChanges, getPatch, + getHeads, getAllChanges, getChanges, getChangesAdded, getChangeByHash, getMissingDeps, + receiveSyncMessage, generateSyncMessage, encodeSyncMessage, decodeSyncMessage, encodeSyncState, decodeSyncState, initSyncState +} - var r = bits % 26; - var s = Math.min((bits - r) / 26, this.length); - var mask = 0x3ffffff ^ ((0x3ffffff >>> r) << r); - var maskedWords = extended; +},{"./backend":48,"./sync":53}],52:[function(require,module,exports){ +const { parseOpId, copyObject } = require('../src/common') +const { COLUMN_TYPE, VALUE_TYPE, ACTIONS, OBJECT_TYPE, DOC_OPS_COLUMNS, CHANGE_COLUMNS, DOCUMENT_COLUMNS, + encoderByColumnId, decoderByColumnId, makeDecoders, decodeValue, + encodeChange, decodeChangeColumns, decodeChangeMeta, decodeChanges, decodeDocumentHeader, encodeDocumentHeader } = require('./columnar') - h -= s; - h = Math.max(0, h); +const MAX_BLOCK_SIZE = 600 // operations +const BLOOM_BITS_PER_ENTRY = 10, BLOOM_NUM_PROBES = 7 // 1% false positive rate +const BLOOM_FILTER_SIZE = Math.floor(BLOOM_BITS_PER_ENTRY * MAX_BLOCK_SIZE / 8) // bytes - // Extended mode, copy masked part - if (maskedWords) { - for (var i = 0; i < s; i++) { - maskedWords.words[i] = this.words[i]; +const objActorIdx = 0, objCtrIdx = 1, keyActorIdx = 2, keyCtrIdx = 3, keyStrIdx = 4, + idActorIdx = 5, idCtrIdx = 6, insertIdx = 7, actionIdx = 8, valLenIdx = 9, valRawIdx = 10, + predNumIdx = 13, predActorIdx = 14, predCtrIdx = 15, succNumIdx = 13, succActorIdx = 14, succCtrIdx = 15 + +const PRED_COLUMN_IDS = CHANGE_COLUMNS + .filter(column => ['predNum', 'predActor', 'predCtr'].includes(column.columnName)) + .map(column => column.columnId) + +/** + * Updates `objectTree`, which is a tree of nested objects, so that afterwards + * `objectTree[path[0]][path[1]][...] === value`. Only the root object is mutated, whereas any + * nested objects are copied before updating. This means that once the root object has been + * shallow-copied, this function can be used to update it without mutating the previous version. + */ +function deepCopyUpdate(objectTree, path, value) { + if (path.length === 1) { + objectTree[path[0]] = value + } else { + let child = Object.assign({}, objectTree[path[0]]) + deepCopyUpdate(child, path.slice(1), value) + objectTree[path[0]] = child + } +} + +/** + * Scans a block of document operations, encoded as columns `docCols`, to find the position at which + * an operation (or sequence of operations) `ops` should be applied. `actorIds` is the array that + * maps actor numbers to hexadecimal actor IDs. `resumeInsertion` is true if we're performing a list + * insertion and we already found the reference element in a previous block, but we reached the end + * of that previous block while scanning for the actual insertion position, and so we're continuing + * the scan in a subsequent block. + * + * Returns an object with keys: + * - `found`: false if we were scanning for a reference element in a list but couldn't find it; + * true otherwise. + * - `skipCount`: the number of operations, counted from the start of the block, after which the + * new operations should be inserted or applied. + * - `visibleCount`: if modifying a list object, the number of visible (i.e. non-deleted) list + * elements that precede the position where the new operations should be applied. + */ +function seekWithinBlock(ops, docCols, actorIds, resumeInsertion) { + for (let col of docCols) col.decoder.reset() + const { objActor, objCtr, keyActor, keyCtr, keyStr, idActor, idCtr, insert } = ops + const [objActorD, objCtrD, /* keyActorD */, /* keyCtrD */, keyStrD, idActorD, idCtrD, insertD, actionD, + /* valLenD */, /* valRawD */, /* chldActorD */, /* chldCtrD */, succNumD] = docCols.map(col => col.decoder) + let skipCount = 0, visibleCount = 0, elemVisible = false, nextObjActor = null, nextObjCtr = null + let nextIdActor = null, nextIdCtr = null, nextKeyStr = null, nextInsert = null, nextSuccNum = 0 + + // Seek to the beginning of the object being updated + if (objCtr !== null && !resumeInsertion) { + while (!objCtrD.done || !objActorD.done || !actionD.done) { + nextObjCtr = objCtrD.readValue() + nextObjActor = actorIds[objActorD.readValue()] + actionD.skipValues(1) + if (nextObjCtr === null || !nextObjActor || nextObjCtr < objCtr || + (nextObjCtr === objCtr && nextObjActor < objActor)) { + skipCount += 1 + } else { + break } - maskedWords.length = s; } + } + if ((nextObjCtr !== objCtr || nextObjActor !== objActor) && !resumeInsertion) { + return {found: true, skipCount, visibleCount} + } - if (s === 0) { - // No-op, we should not move anything at all - } else if (this.length > s) { - this.length -= s; - for (i = 0; i < this.length; i++) { - this.words[i] = this.words[i + s]; + // Seek to the appropriate key (if string key is used) + if (keyStr !== null) { + keyStrD.skipValues(skipCount) + while (!keyStrD.done) { + const objActorIndex = objActorD.readValue() + nextObjActor = objActorIndex === null ? null : actorIds[objActorIndex] + nextObjCtr = objCtrD.readValue() + nextKeyStr = keyStrD.readValue() + if (nextKeyStr !== null && nextKeyStr < keyStr && + nextObjCtr === objCtr && nextObjActor === objActor) { + skipCount += 1 + } else { + break } - } else { - this.words[0] = 0; - this.length = 1; } + return {found: true, skipCount, visibleCount} + } - var carry = 0; - for (i = this.length - 1; i >= 0 && (carry !== 0 || i >= h); i--) { - var word = this.words[i] | 0; - this.words[i] = (carry << (26 - r)) | (word >>> r); - carry = word & mask; - } + idCtrD.skipValues(skipCount) + idActorD.skipValues(skipCount) + insertD.skipValues(skipCount) + succNumD.skipValues(skipCount) + nextIdCtr = idCtrD.readValue() + nextIdActor = actorIds[idActorD.readValue()] + nextInsert = insertD.readValue() + nextSuccNum = succNumD.readValue() - // Push carried bits as a mask - if (maskedWords && carry !== 0) { - maskedWords.words[maskedWords.length++] = carry; + // If we are inserting into a list, an opId key is used, and we need to seek to a position *after* + // the referenced operation. Moreover, we need to skip over any existing operations with a greater + // opId than the new insertion, for CRDT convergence on concurrent insertions in the same place. + if (insert) { + // If insertion is not at the head, search for the reference element + if (!resumeInsertion && keyCtr !== null && keyCtr > 0 && keyActor !== null) { + skipCount += 1 + while (!idCtrD.done && !idActorD.done && (nextIdCtr !== keyCtr || nextIdActor !== keyActor)) { + if (nextInsert) elemVisible = false + if (nextSuccNum === 0 && !elemVisible) { + visibleCount += 1 + elemVisible = true + } + nextIdCtr = idCtrD.readValue() + nextIdActor = actorIds[idActorD.readValue()] + nextObjCtr = objCtrD.readValue() + nextObjActor = actorIds[objActorD.readValue()] + nextInsert = insertD.readValue() + nextSuccNum = succNumD.readValue() + if (nextObjCtr === objCtr && nextObjActor === objActor) skipCount += 1; else break + } + if (nextObjCtr !== objCtr || nextObjActor !== objActor || nextIdCtr !== keyCtr || + nextIdActor !== keyActor || !nextInsert) { + return {found: false, skipCount, visibleCount} + } + if (nextInsert) elemVisible = false + if (nextSuccNum === 0 && !elemVisible) { + visibleCount += 1 + elemVisible = true + } + + // Set up the next* variables to the operation following the reference element + if (idCtrD.done || idActorD.done) return {found: true, skipCount, visibleCount} + nextIdCtr = idCtrD.readValue() + nextIdActor = actorIds[idActorD.readValue()] + nextObjCtr = objCtrD.readValue() + nextObjActor = actorIds[objActorD.readValue()] + nextInsert = insertD.readValue() + nextSuccNum = succNumD.readValue() } - if (this.length === 0) { - this.words[0] = 0; - this.length = 1; + // Skip over any list elements with greater ID than the new one, and any non-insertions + while ((!nextInsert || nextIdCtr > idCtr || (nextIdCtr === idCtr && nextIdActor > idActor)) && + nextObjCtr === objCtr && nextObjActor === objActor) { + skipCount += 1 + if (nextInsert) elemVisible = false + if (nextSuccNum === 0 && !elemVisible) { + visibleCount += 1 + elemVisible = true + } + if (!idCtrD.done && !idActorD.done) { + nextIdCtr = idCtrD.readValue() + nextIdActor = actorIds[idActorD.readValue()] + nextObjCtr = objCtrD.readValue() + nextObjActor = actorIds[objActorD.readValue()] + nextInsert = insertD.readValue() + nextSuccNum = succNumD.readValue() + } else { + break + } } - return this.strip(); - }; + } else if (keyCtr !== null && keyCtr > 0 && keyActor !== null) { + // If we are updating an existing list element, seek to just before the referenced ID + while ((!nextInsert || nextIdCtr !== keyCtr || nextIdActor !== keyActor) && + nextObjCtr === objCtr && nextObjActor === objActor) { + skipCount += 1 + if (nextInsert) elemVisible = false + if (nextSuccNum === 0 && !elemVisible) { + visibleCount += 1 + elemVisible = true + } + if (!idCtrD.done && !idActorD.done) { + nextIdCtr = idCtrD.readValue() + nextIdActor = actorIds[idActorD.readValue()] + nextObjCtr = objCtrD.readValue() + nextObjActor = actorIds[objActorD.readValue()] + nextInsert = insertD.readValue() + nextSuccNum = succNumD.readValue() + } else { + break + } + } + if (nextObjCtr !== objCtr || nextObjActor !== objActor || nextIdCtr !== keyCtr || + nextIdActor !== keyActor || !nextInsert) { + return {found: false, skipCount, visibleCount} + } + } + return {found: true, skipCount, visibleCount} +} - BN.prototype.ishrn = function ishrn (bits, hint, extended) { - // TODO(indutny): implement me - assert(this.negative === 0); - return this.iushrn(bits, hint, extended); - }; +/** + * Returns the number of list elements that should be added to a list index when skipping over the + * block with index `blockIndex` in the list object with object ID consisting of actor number + * `objActorNum` and counter `objCtr`. + */ +function visibleListElements(docState, blockIndex, objActorNum, objCtr) { + const thisBlock = docState.blocks[blockIndex] + const nextBlock = docState.blocks[blockIndex + 1] - // Shift-left - BN.prototype.shln = function shln (bits) { - return this.clone().ishln(bits); - }; + if (thisBlock.lastObjectActor !== objActorNum || thisBlock.lastObjectCtr !== objCtr || + thisBlock.numVisible === undefined) { + return 0 - BN.prototype.ushln = function ushln (bits) { - return this.clone().iushln(bits); - }; + // If a list element is split across the block boundary, don't double-count it + } else if (thisBlock.lastVisibleActor === nextBlock.firstVisibleActor && + thisBlock.lastVisibleActor !== undefined && + thisBlock.lastVisibleCtr === nextBlock.firstVisibleCtr && + thisBlock.lastVisibleCtr !== undefined) { + return thisBlock.numVisible - 1 + } else { + return thisBlock.numVisible + } +} - // Shift-right - BN.prototype.shrn = function shrn (bits) { - return this.clone().ishrn(bits); - }; +/** + * Scans the blocks of document operations to find the position where a new operation should be + * inserted. Returns an object with keys: + * - `blockIndex`: the index of the block into which we should insert the new operation + * - `skipCount`: the number of operations, counted from the start of the block, after which the + * new operations should be inserted or merged. + * - `visibleCount`: if modifying a list object, the number of visible (i.e. non-deleted) list + * elements that precede the position where the new operations should be applied. + */ +function seekToOp(docState, ops) { + const { objActor, objActorNum, objCtr, keyActor, keyCtr, keyStr } = ops + let blockIndex = 0, totalVisible = 0 - BN.prototype.ushrn = function ushrn (bits) { - return this.clone().iushrn(bits); - }; + // Skip any blocks that contain only objects with lower objectIds + if (objCtr !== null) { + while (blockIndex < docState.blocks.length - 1) { + const blockActor = docState.blocks[blockIndex].lastObjectActor === undefined ? undefined + : docState.actorIds[docState.blocks[blockIndex].lastObjectActor] + const blockCtr = docState.blocks[blockIndex].lastObjectCtr + if (blockCtr === null || blockCtr < objCtr || (blockCtr === objCtr && blockActor < objActor)) { + blockIndex++ + } else { + break + } + } + } - // Test if n bit is set - BN.prototype.testn = function testn (bit) { - assert(typeof bit === 'number' && bit >= 0); - var r = bit % 26; - var s = (bit - r) / 26; - var q = 1 << r; + if (keyStr !== null) { + // String key is used. First skip any blocks that contain only lower keys + while (blockIndex < docState.blocks.length - 1) { + const { lastObjectActor, lastObjectCtr, lastKey } = docState.blocks[blockIndex] + if (objCtr === lastObjectCtr && objActorNum === lastObjectActor && + lastKey !== undefined && lastKey < keyStr) blockIndex++; else break + } - // Fast case: bit is much higher than all existing words - if (this.length <= s) return false; + // When we have a candidate block, decode it to find the exact insertion position + const {skipCount} = seekWithinBlock(ops, docState.blocks[blockIndex].columns, docState.actorIds, false) + return {blockIndex, skipCount, visibleCount: 0} - // Check bit and return - var w = this.words[s]; + } else { + // List operation + const insertAtHead = keyCtr === null || keyCtr === 0 || keyActor === null + const keyActorNum = keyActor === null ? null : docState.actorIds.indexOf(keyActor) + let resumeInsertion = false - return !!(w & q); - }; + while (true) { + // Search for the reference element, skipping any blocks whose Bloom filter does not contain + // the reference element. We only do this if not inserting at the head (in which case there is + // no reference element), or if we already found the reference element in an earlier block (in + // which case we have resumeInsertion === true). The latter case arises with concurrent + // insertions at the same position, and so we have to scan beyond the reference element to + // find the actual insertion position, and that further scan crosses a block boundary. + if (!insertAtHead && !resumeInsertion) { + while (blockIndex < docState.blocks.length - 1 && + docState.blocks[blockIndex].lastObjectActor === objActorNum && + docState.blocks[blockIndex].lastObjectCtr === objCtr && + !bloomFilterContains(docState.blocks[blockIndex].bloom, keyActorNum, keyCtr)) { + // If we reach the end of the list object without a Bloom filter hit, the reference element + // doesn't exist + if (docState.blocks[blockIndex].lastObjectCtr > objCtr) { + throw new RangeError(`Reference element not found: ${keyCtr}@${keyActor}`) + } - // Return only lowers bits of number (in-place) - BN.prototype.imaskn = function imaskn (bits) { - assert(typeof bits === 'number' && bits >= 0); - var r = bits % 26; - var s = (bits - r) / 26; + // Add up number of visible list elements in any blocks we skip, for list index computation + totalVisible += visibleListElements(docState, blockIndex, objActorNum, objCtr) + blockIndex++ + } + } - assert(this.negative === 0, 'imaskn works only with positive numbers'); + // We have a candidate block. Decode it to see whether it really contains the reference element + const {found, skipCount, visibleCount} = seekWithinBlock(ops, + docState.blocks[blockIndex].columns, + docState.actorIds, + resumeInsertion) - if (this.length <= s) { - return this; - } + if (blockIndex === docState.blocks.length - 1 || + docState.blocks[blockIndex].lastObjectActor !== objActorNum || + docState.blocks[blockIndex].lastObjectCtr !== objCtr) { + // Last block: if we haven't found the reference element by now, it's an error + if (found) { + return {blockIndex, skipCount, visibleCount: totalVisible + visibleCount} + } else { + throw new RangeError(`Reference element not found: ${keyCtr}@${keyActor}`) + } - if (r !== 0) { - s++; - } - this.length = Math.min(s, this.length); + } else if (found && skipCount < docState.blocks[blockIndex].numOps) { + // The insertion position lies within the current block + return {blockIndex, skipCount, visibleCount: totalVisible + visibleCount} + } - if (r !== 0) { - var mask = 0x3ffffff ^ ((0x3ffffff >>> r) << r); - this.words[this.length - 1] &= mask; + // Reference element not found and there are still blocks left ==> it was probably a false positive. + // Reference element found, but we skipped all the way to the end of the block ==> we need to + // continue scanning the next block to find the actual insertion position. + // Either way, go back round the loop again to skip blocks until the next Bloom filter hit. + resumeInsertion = found && ops.insert + totalVisible += visibleListElements(docState, blockIndex, objActorNum, objCtr) + blockIndex++ } + } +} - return this.strip(); - }; +/** + * Updates Bloom filter `bloom`, given as a Uint8Array, to contain the list element ID consisting of + * counter `elemIdCtr` and actor number `elemIdActor`. We don't actually bother computing a hash + * function, since those two integers serve perfectly fine as input. We turn the two integers into a + * sequence of probe indexes using the triple hashing algorithm from the following paper: + * + * Peter C. Dillinger and Panagiotis Manolios. Bloom Filters in Probabilistic Verification. + * 5th International Conference on Formal Methods in Computer-Aided Design (FMCAD), November 2004. + * http://www.ccis.northeastern.edu/home/pete/pub/bloom-filters-verification.pdf + */ +function bloomFilterAdd(bloom, elemIdActor, elemIdCtr) { + let modulo = 8 * bloom.byteLength, x = elemIdCtr % modulo, y = elemIdActor % modulo - // Return only lowers bits of number - BN.prototype.maskn = function maskn (bits) { - return this.clone().imaskn(bits); - }; + // Use one step of FNV-1a to compute a third value from the two inputs. + // Taken from http://www.isthe.com/chongo/tech/comp/fnv/index.html + // The prime is just over 2^24, so elemIdCtr can be up to about 2^29 = 500 million before the + // result of the multiplication exceeds 2^53. And even if it does exceed 2^53 and loses precision, + // that shouldn't be a problem as it should still be deterministic, and the Bloom filter + // computation only needs to be internally consistent within this library. + let z = ((elemIdCtr ^ elemIdActor) * 16777619 >>> 0) % modulo - // Add plain number `num` to `this` - BN.prototype.iaddn = function iaddn (num) { - assert(typeof num === 'number'); - assert(num < 0x4000000); - if (num < 0) return this.isubn(-num); + for (let i = 0; i < BLOOM_NUM_PROBES; i++) { + bloom[x >>> 3] |= 1 << (x & 7) + x = (x + y) % modulo + y = (y + z) % modulo + } +} - // Possible sign change - if (this.negative !== 0) { - if (this.length === 1 && (this.words[0] | 0) < num) { - this.words[0] = num - (this.words[0] | 0); - this.negative = 0; - return this; - } +/** + * Returns true if the list element ID consisting of counter `elemIdCtr` and actor number + * `elemIdActor` is likely to be contained in the Bloom filter `bloom`. + */ +function bloomFilterContains(bloom, elemIdActor, elemIdCtr) { + let modulo = 8 * bloom.byteLength, x = elemIdCtr % modulo, y = elemIdActor % modulo + let z = ((elemIdCtr ^ elemIdActor) * 16777619 >>> 0) % modulo - this.negative = 0; - this.isubn(num); - this.negative = 1; - return this; + // See comments in the bloomFilterAdd function for an explanation + for (let i = 0; i < BLOOM_NUM_PROBES; i++) { + if ((bloom[x >>> 3] & (1 << (x & 7))) === 0) { + return false } + x = (x + y) % modulo + y = (y + z) % modulo + } + return true +} - // Add without checks - return this._iaddn(num); - }; - - BN.prototype._iaddn = function _iaddn (num) { - this.words[0] += num; - - // Carry - for (var i = 0; i < this.length && this.words[i] >= 0x4000000; i++) { - this.words[i] -= 0x4000000; - if (i === this.length - 1) { - this.words[i + 1] = 1; - } else { - this.words[i + 1]++; - } - } - this.length = Math.max(this.length, i + 1); +/** + * Reads the relevant columns of a block of operations and updates that block to contain the + * metadata we need to efficiently figure out where to insert new operations. + */ +function updateBlockMetadata(block) { + block.bloom = new Uint8Array(BLOOM_FILTER_SIZE) + block.numOps = 0 + block.lastKey = undefined + block.numVisible = undefined + block.lastObjectActor = undefined + block.lastObjectCtr = undefined + block.firstVisibleActor = undefined + block.firstVisibleCtr = undefined + block.lastVisibleActor = undefined + block.lastVisibleCtr = undefined - return this; - }; + for (let col of block.columns) col.decoder.reset() + const [objActorD, objCtrD, keyActorD, keyCtrD, keyStrD, idActorD, idCtrD, insertD, /* actionD */, + /* valLenD */, /* valRawD */, /* chldActorD */, /* chldCtrD */, succNumD] = block.columns.map(col => col.decoder) - // Subtract plain number `num` from `this` - BN.prototype.isubn = function isubn (num) { - assert(typeof num === 'number'); - assert(num < 0x4000000); - if (num < 0) return this.iaddn(-num); + while (!idCtrD.done) { + block.numOps += 1 + const objActor = objActorD.readValue(), objCtr = objCtrD.readValue() + const keyActor = keyActorD.readValue(), keyCtr = keyCtrD.readValue(), keyStr = keyStrD.readValue() + const idActor = idActorD.readValue(), idCtr = idCtrD.readValue() + const insert = insertD.readValue(), succNum = succNumD.readValue() - if (this.negative !== 0) { - this.negative = 0; - this.iaddn(num); - this.negative = 1; - return this; + if (block.lastObjectActor !== objActor || block.lastObjectCtr !== objCtr) { + block.numVisible = 0 + block.lastObjectActor = objActor + block.lastObjectCtr = objCtr } - this.words[0] -= num; + if (keyStr !== null) { + // Map key: for each object, record the highest key contained in the block + block.lastKey = keyStr + } else if (insert || keyCtr !== null) { + // List element + block.lastKey = undefined + const elemIdActor = insert ? idActor : keyActor + const elemIdCtr = insert ? idCtr : keyCtr + bloomFilterAdd(block.bloom, elemIdActor, elemIdCtr) - if (this.length === 1 && this.words[0] < 0) { - this.words[0] = -this.words[0]; - this.negative = 1; - } else { - // Carry - for (var i = 0; i < this.length && this.words[i] < 0; i++) { - this.words[i] += 0x4000000; - this.words[i + 1] -= 1; + // If the list element is visible, update the block metadata accordingly + if (succNum === 0) { + if (block.firstVisibleActor === undefined) block.firstVisibleActor = elemIdActor + if (block.firstVisibleCtr === undefined) block.firstVisibleCtr = elemIdCtr + if (block.lastVisibleActor !== elemIdActor || block.lastVisibleCtr !== elemIdCtr) { + block.numVisible += 1 + block.lastVisibleActor = elemIdActor + block.lastVisibleCtr = elemIdCtr + } } } + } +} - return this.strip(); - }; - - BN.prototype.addn = function addn (num) { - return this.clone().iaddn(num); - }; +/** + * Updates a block's metadata based on an operation being added to a block. + */ +function addBlockOperation(block, op, actorIds, isChangeOp) { + if (op[keyStrIdx] !== null) { + // TODO this comparison should use UTF-8 encoding, not JavaScript's UTF-16 + if (block.lastObjectCtr === op[objCtrIdx] && block.lastObjectActor === op[objActorIdx] && + (block.lastKey === undefined || block.lastKey < op[keyStrIdx])) { + block.lastKey = op[keyStrIdx] + } + } else { + // List element + const elemIdActor = op[insertIdx] ? op[idActorIdx] : op[keyActorIdx] + const elemIdCtr = op[insertIdx] ? op[idCtrIdx] : op[keyCtrIdx] + bloomFilterAdd(block.bloom, elemIdActor, elemIdCtr) - BN.prototype.subn = function subn (num) { - return this.clone().isubn(num); - }; + // Set lastVisible on the assumption that this is the last op in the block; if there are further + // ops after this one in the block, lastVisible will be overwritten again later. + if (op[succNumIdx] === 0 || isChangeOp) { + if (block.firstVisibleActor === undefined) block.firstVisibleActor = elemIdActor + if (block.firstVisibleCtr === undefined) block.firstVisibleCtr = elemIdCtr + block.lastVisibleActor = elemIdActor + block.lastVisibleCtr = elemIdCtr + } + } - BN.prototype.iabs = function iabs () { - this.negative = 0; - - return this; - }; - - BN.prototype.abs = function abs () { - return this.clone().iabs(); - }; - - BN.prototype._ishlnsubmul = function _ishlnsubmul (num, mul, shift) { - var len = num.length + shift; - var i; - - this._expand(len); - - var w; - var carry = 0; - for (i = 0; i < num.length; i++) { - w = (this.words[i + shift] | 0) + carry; - var right = (num.words[i] | 0) * mul; - w -= right & 0x3ffffff; - carry = (w >> 26) - ((right / 0x4000000) | 0); - this.words[i + shift] = w & 0x3ffffff; - } - for (; i < this.length - shift; i++) { - w = (this.words[i + shift] | 0) + carry; - carry = w >> 26; - this.words[i + shift] = w & 0x3ffffff; - } + // Keep track of the largest objectId contained within a block + if (block.lastObjectCtr === undefined || + op[objActorIdx] !== null && op[objCtrIdx] !== null && + (block.lastObjectCtr === null || block.lastObjectCtr < op[objCtrIdx] || + (block.lastObjectCtr === op[objCtrIdx] && actorIds[block.lastObjectActor] < actorIds[op[objActorIdx]]))) { + block.lastObjectActor = op[objActorIdx] + block.lastObjectCtr = op[objCtrIdx] + block.lastKey = (op[keyStrIdx] !== null ? op[keyStrIdx] : undefined) + block.numVisible = 0 + } +} - if (carry === 0) return this.strip(); +/** + * Takes a block containing too many operations, and splits it into a sequence of adjacent blocks of + * roughly equal size. + */ +function splitBlock(block) { + for (let col of block.columns) col.decoder.reset() - // Subtraction overflow - assert(carry === -1); - carry = 0; - for (i = 0; i < this.length; i++) { - w = -(this.words[i] | 0) + carry; - carry = w >> 26; - this.words[i] = w & 0x3ffffff; - } - this.negative = 1; + // Make each of the resulting blocks between 50% and 80% full (leaving a bit of space in each + // block so that it doesn't get split again right away the next time an operation is added). + // The upper bound cannot be lower than 75% since otherwise we would end up with a block less than + // 50% full when going from two to three blocks. + const numBlocks = Math.ceil(block.numOps / (0.8 * MAX_BLOCK_SIZE)) + let blocks = [], opsSoFar = 0 - return this.strip(); - }; + for (let i = 1; i <= numBlocks; i++) { + const opsToCopy = Math.ceil(i * block.numOps / numBlocks) - opsSoFar + const encoders = block.columns.map(col => ({columnId: col.columnId, encoder: encoderByColumnId(col.columnId)})) + copyColumns(encoders, block.columns, opsToCopy) + const decoders = encoders.map(col => { + const decoder = decoderByColumnId(col.columnId, col.encoder.buffer) + return {columnId: col.columnId, decoder} + }) - BN.prototype._wordDiv = function _wordDiv (num, mode) { - var shift = this.length - num.length; + const newBlock = {columns: decoders} + updateBlockMetadata(newBlock) + blocks.push(newBlock) + opsSoFar += opsToCopy + } - var a = this.clone(); - var b = num; + return blocks +} - // Normalize - var bhi = b.words[b.length - 1] | 0; - var bhiBits = this._countBits(bhi); - shift = 26 - bhiBits; - if (shift !== 0) { - b = b.ushln(shift); - a.iushln(shift); - bhi = b.words[b.length - 1] | 0; - } +/** + * Takes an array of blocks and concatenates the corresponding columns across all of the blocks. + */ +function concatBlocks(blocks) { + const encoders = blocks[0].columns.map(col => ({columnId: col.columnId, encoder: encoderByColumnId(col.columnId)})) - // Initialize quotient - var m = a.length - b.length; - var q; + for (let block of blocks) { + for (let col of block.columns) col.decoder.reset() + copyColumns(encoders, block.columns, block.numOps) + } + return encoders +} - if (mode !== 'mod') { - q = new BN(null); - q.length = m + 1; - q.words = new Array(q.length); - for (var i = 0; i < q.length; i++) { - q.words[i] = 0; - } +/** + * Copies `count` rows from the set of input columns `inCols` to the set of output columns + * `outCols`. The input columns are given as an array of `{columnId, decoder}` objects, and the + * output columns are given as an array of `{columnId, encoder}` objects. Both are sorted in + * increasing order of columnId. If there is no matching input column for a given output column, it + * is filled in with `count` blank values (according to the column type). + */ +function copyColumns(outCols, inCols, count) { + if (count === 0) return + let inIndex = 0, lastGroup = -1, lastCardinality = 0, valueColumn = -1, valueBytes = 0 + for (let outCol of outCols) { + while (inIndex < inCols.length && inCols[inIndex].columnId < outCol.columnId) inIndex++ + let inCol = null + if (inIndex < inCols.length && inCols[inIndex].columnId === outCol.columnId && + inCols[inIndex].decoder.buf.byteLength > 0) { + inCol = inCols[inIndex].decoder } + const colCount = (outCol.columnId >> 4 === lastGroup) ? lastCardinality : count - var diff = a.clone()._ishlnsubmul(b, 1, m); - if (diff.negative === 0) { - a = diff; - if (q) { - q.words[m] = 1; + if (outCol.columnId % 8 === COLUMN_TYPE.GROUP_CARD) { + lastGroup = outCol.columnId >> 4 + if (inCol) { + lastCardinality = outCol.encoder.copyFrom(inCol, {count, sumValues: true}).sum + } else { + outCol.encoder.appendValue(0, count) + lastCardinality = 0 } - } - - for (var j = m - 1; j >= 0; j--) { - var qj = (a.words[b.length + j] | 0) * 0x4000000 + - (a.words[b.length + j - 1] | 0); - - // NOTE: (qj / bhi) is (0x3ffffff * 0x4000000 + 0x3ffffff) / 0x2000000 max - // (0x7ffffff) - qj = Math.min((qj / bhi) | 0, 0x3ffffff); - - a._ishlnsubmul(b, qj, j); - while (a.negative !== 0) { - qj--; - a.negative = 0; - a._ishlnsubmul(b, 1, j); - if (!a.isZero()) { - a.negative ^= 1; + } else if (outCol.columnId % 8 === COLUMN_TYPE.VALUE_LEN) { + if (inCol) { + if (inIndex + 1 === inCols.length || inCols[inIndex + 1].columnId !== outCol.columnId + 1) { + throw new RangeError('VALUE_LEN column without accompanying VALUE_RAW column') } + valueColumn = outCol.columnId + 1 + valueBytes = outCol.encoder.copyFrom(inCol, {count: colCount, sumValues: true, sumShift: 4}).sum + } else { + outCol.encoder.appendValue(null, colCount) + valueColumn = outCol.columnId + 1 + valueBytes = 0 } - if (q) { - q.words[j] = qj; + } else if (outCol.columnId % 8 === COLUMN_TYPE.VALUE_RAW) { + if (outCol.columnId !== valueColumn) { + throw new RangeError('VALUE_RAW column without accompanying VALUE_LEN column') } - } - if (q) { - q.strip(); - } - a.strip(); - - // Denormalize - if (mode !== 'div' && shift !== 0) { - a.iushrn(shift); - } - - return { - div: q || null, - mod: a - }; - }; - - // NOTE: 1) `mode` can be set to `mod` to request mod only, - // to `div` to request div only, or be absent to - // request both div & mod - // 2) `positive` is true if unsigned mod is requested - BN.prototype.divmod = function divmod (num, mode, positive) { - assert(!num.isZero()); - - if (this.isZero()) { - return { - div: new BN(0), - mod: new BN(0) - }; - } - - var div, mod, res; - if (this.negative !== 0 && num.negative === 0) { - res = this.neg().divmod(num, mode); - - if (mode !== 'mod') { - div = res.div.neg(); + if (valueBytes > 0) { + outCol.encoder.appendRawBytes(inCol.readRawBytes(valueBytes)) } - - if (mode !== 'div') { - mod = res.mod.neg(); - if (positive && mod.negative !== 0) { - mod.iadd(num); - } + } else { // ACTOR_ID, INT_RLE, INT_DELTA, BOOLEAN, or STRING_RLE + if (inCol) { + outCol.encoder.copyFrom(inCol, {count: colCount}) + } else { + const blankValue = (outCol.columnId % 8 === COLUMN_TYPE.BOOLEAN) ? false : null + outCol.encoder.appendValue(blankValue, colCount) } - - return { - div: div, - mod: mod - }; } + } +} - if (this.negative === 0 && num.negative !== 0) { - res = this.divmod(num.neg(), mode); - - if (mode !== 'mod') { - div = res.div.neg(); +/** + * Parses one operation from a set of columns. The argument `columns` contains a list of objects + * with `columnId` and `decoder` properties. Returns an array in which the i'th element is the + * value read from the i'th column in `columns`. Does not interpret datatypes; the only + * interpretation of values is that if `actorTable` is given, a value `v` in a column of type + * ACTOR_ID is replaced with `actorTable[v]`. + */ +function readOperation(columns, actorTable) { + let operation = [], colValue, lastGroup = -1, lastCardinality = 0, valueColumn = -1, valueBytes = 0 + for (let col of columns) { + if (col.columnId % 8 === COLUMN_TYPE.VALUE_RAW) { + if (col.columnId !== valueColumn) throw new RangeError('unexpected VALUE_RAW column') + colValue = col.decoder.readRawBytes(valueBytes) + } else if (col.columnId % 8 === COLUMN_TYPE.GROUP_CARD) { + lastGroup = col.columnId >> 4 + lastCardinality = col.decoder.readValue() || 0 + colValue = lastCardinality + } else if (col.columnId >> 4 === lastGroup) { + colValue = [] + if (col.columnId % 8 === COLUMN_TYPE.VALUE_LEN) { + valueColumn = col.columnId + 1 + valueBytes = 0 } - - return { - div: div, - mod: res.mod - }; - } - - if ((this.negative & num.negative) !== 0) { - res = this.neg().divmod(num.neg(), mode); - - if (mode !== 'div') { - mod = res.mod.neg(); - if (positive && mod.negative !== 0) { - mod.isub(num); + for (let i = 0; i < lastCardinality; i++) { + let value = col.decoder.readValue() + if (col.columnId % 8 === COLUMN_TYPE.ACTOR_ID && actorTable && typeof value === 'number') { + value = actorTable[value] + } + if (col.columnId % 8 === COLUMN_TYPE.VALUE_LEN) { + valueBytes += colValue >>> 4 } + colValue.push(value) + } + } else { + colValue = col.decoder.readValue() + if (col.columnId % 8 === COLUMN_TYPE.ACTOR_ID && actorTable && typeof colValue === 'number') { + colValue = actorTable[colValue] + } + if (col.columnId % 8 === COLUMN_TYPE.VALUE_LEN) { + valueColumn = col.columnId + 1 + valueBytes = colValue >>> 4 } - - return { - div: res.div, - mod: mod - }; } - // Both numbers are positive at this point - - // Strip both numbers to approximate shift value - if (num.length > this.length || this.cmp(num) < 0) { - return { - div: new BN(0), - mod: this - }; - } + operation.push(colValue) + } + return operation +} - // Very short reduction - if (num.length === 1) { - if (mode === 'div') { - return { - div: this.divn(num.words[0]), - mod: null - }; - } +/** + * Appends `operation`, in the form returned by `readOperation()`, to the columns in `outCols`. The + * argument `inCols` provides metadata about the types of columns in `operation`; the value + * `operation[i]` comes from the column `inCols[i]`. + */ +function appendOperation(outCols, inCols, operation) { + let inIndex = 0, lastGroup = -1, lastCardinality = 0 + for (let outCol of outCols) { + while (inIndex < inCols.length && inCols[inIndex].columnId < outCol.columnId) inIndex++ - if (mode === 'mod') { - return { - div: null, - mod: new BN(this.modn(num.words[0])) - }; + if (inIndex < inCols.length && inCols[inIndex].columnId === outCol.columnId) { + const colValue = operation[inIndex] + if (outCol.columnId % 8 === COLUMN_TYPE.GROUP_CARD) { + lastGroup = outCol.columnId >> 4 + lastCardinality = colValue + outCol.encoder.appendValue(colValue) + } else if (outCol.columnId >> 4 === lastGroup) { + if (!Array.isArray(colValue) || colValue.length !== lastCardinality) { + throw new RangeError('bad group value') + } + for (let v of colValue) outCol.encoder.appendValue(v) + } else if (outCol.columnId % 8 === COLUMN_TYPE.VALUE_RAW) { + if (colValue) outCol.encoder.appendRawBytes(colValue) + } else { + outCol.encoder.appendValue(colValue) } - - return { - div: this.divn(num.words[0]), - mod: new BN(this.modn(num.words[0])) - }; + } else if (outCol.columnId % 8 === COLUMN_TYPE.GROUP_CARD) { + lastGroup = outCol.columnId >> 4 + lastCardinality = 0 + outCol.encoder.appendValue(0) + } else if (outCol.columnId % 8 !== COLUMN_TYPE.VALUE_RAW) { + const count = (outCol.columnId >> 4 === lastGroup) ? lastCardinality : 1 + let blankValue = null + if (outCol.columnId % 8 === COLUMN_TYPE.BOOLEAN) blankValue = false + if (outCol.columnId % 8 === COLUMN_TYPE.VALUE_LEN) blankValue = 0 + outCol.encoder.appendValue(blankValue, count) } + } +} - return this._wordDiv(num, mode); - }; +/** + * Parses the next operation from block `blockIndex` of the document. Returns an object of the form + * `{docOp, blockIndex}` where `docOp` is an operation in the form returned by `readOperation()`, + * and `blockIndex` is the block number to use on the next call (it moves on to the next block when + * we reach the end of the current block). `docOp` is null if there are no more operations. + */ +function readNextDocOp(docState, blockIndex) { + let block = docState.blocks[blockIndex] + if (!block.columns[actionIdx].decoder.done) { + return {docOp: readOperation(block.columns), blockIndex} + } else if (blockIndex === docState.blocks.length - 1) { + return {docOp: null, blockIndex} + } else { + blockIndex += 1 + block = docState.blocks[blockIndex] + for (let col of block.columns) col.decoder.reset() + return {docOp: readOperation(block.columns), blockIndex} + } +} - // Find `this` / `num` - BN.prototype.div = function div (num) { - return this.divmod(num, 'div', false).div; - }; +/** + * Parses the next operation from a sequence of changes. `changeState` serves as the state of this + * pseudo-iterator, and it is mutated to reflect the new operation. In particular, + * `changeState.nextOp` is set to the operation that was read, and `changeState.done` is set to true + * when we have finished reading the last operation in the last change. + */ +function readNextChangeOp(docState, changeState) { + // If we've finished reading one change, move to the next change that contains at least one op + while (changeState.changeIndex < changeState.changes.length - 1 && + (!changeState.columns || changeState.columns[actionIdx].decoder.done)) { + changeState.changeIndex += 1 + const change = changeState.changes[changeState.changeIndex] + changeState.columns = makeDecoders(change.columns, CHANGE_COLUMNS) + changeState.opCtr = change.startOp - // Find `this` % `num` - BN.prototype.mod = function mod (num) { - return this.divmod(num, 'mod', false).mod; - }; + // If it's an empty change (no ops), set its maxOp here since it won't be set below + if (changeState.columns[actionIdx].decoder.done) { + change.maxOp = change.startOp - 1 + } - BN.prototype.umod = function umod (num) { - return this.divmod(num, 'mod', true).mod; - }; + // Update docState based on the information in the change + updateBlockColumns(docState, changeState.columns) + const {actorIds, actorTable} = getActorTable(docState.actorIds, change) + docState.actorIds = actorIds + changeState.actorTable = actorTable + changeState.actorIndex = docState.actorIds.indexOf(change.actorIds[0]) + } - // Find Round(`this` / `num`) - BN.prototype.divRound = function divRound (num) { - var dm = this.divmod(num); + // Reached the end of the last change? + if (changeState.columns[actionIdx].decoder.done) { + changeState.done = true + changeState.nextOp = null + return + } - // Fast case - exact division - if (dm.mod.isZero()) return dm.div; + changeState.nextOp = readOperation(changeState.columns, changeState.actorTable) + changeState.nextOp[idActorIdx] = changeState.actorIndex + changeState.nextOp[idCtrIdx] = changeState.opCtr + changeState.changes[changeState.changeIndex].maxOp = changeState.opCtr + if (changeState.opCtr > docState.maxOp) docState.maxOp = changeState.opCtr + changeState.opCtr += 1 - var mod = dm.div.negative !== 0 ? dm.mod.isub(num) : dm.mod; + const op = changeState.nextOp + if ((op[objCtrIdx] === null && op[objActorIdx] !== null) || + (op[objCtrIdx] !== null && op[objActorIdx] === null)) { + throw new RangeError(`Mismatched object reference: (${op[objCtrIdx]}, ${op[objActorIdx]})`) + } + if ((op[keyCtrIdx] === null && op[keyActorIdx] !== null) || + (op[keyCtrIdx] === 0 && op[keyActorIdx] !== null) || + (op[keyCtrIdx] > 0 && op[keyActorIdx] === null)) { + throw new RangeError(`Mismatched operation key: (${op[keyCtrIdx]}, ${op[keyActorIdx]})`) + } +} - var half = num.ushrn(1); - var r2 = num.andln(1); - var cmp = mod.cmp(half); +function emptyObjectPatch(objectId, type) { + if (type === 'list' || type === 'text') { + return {objectId, type, edits: []} + } else { + return {objectId, type, props: {}} + } +} - // Round down - if (cmp < 0 || r2 === 1 && cmp === 0) return dm.div; +/** + * Returns true if the two given operation IDs have the same actor ID, and the counter of `id2` is + * exactly `delta` greater than the counter of `id1`. + */ +function opIdDelta(id1, id2, delta = 1) { + const parsed1 = parseOpId(id1), parsed2 = parseOpId(id2) + return parsed1.actorId === parsed2.actorId && parsed1.counter + delta === parsed2.counter +} - // Round up - return dm.div.negative !== 0 ? dm.div.isubn(1) : dm.div.iaddn(1); - }; +/** + * Appends a list edit operation (insert, update, remove) to an array of existing operations. If the + * last existing operation can be extended (as a multi-op), we do that. + */ +function appendEdit(existingEdits, nextEdit) { + if (existingEdits.length === 0) { + existingEdits.push(nextEdit) + return + } - BN.prototype.modn = function modn (num) { - assert(num <= 0x3ffffff); - var p = (1 << 26) % num; + let lastEdit = existingEdits[existingEdits.length - 1] + if (lastEdit.action === 'insert' && nextEdit.action === 'insert' && + lastEdit.index === nextEdit.index - 1 && + lastEdit.value.type === 'value' && nextEdit.value.type === 'value' && + lastEdit.elemId === lastEdit.opId && nextEdit.elemId === nextEdit.opId && + opIdDelta(lastEdit.elemId, nextEdit.elemId, 1) && + lastEdit.value.datatype === nextEdit.value.datatype && + typeof lastEdit.value.value === typeof nextEdit.value.value) { + lastEdit.action = 'multi-insert' + if (nextEdit.value.datatype) lastEdit.datatype = nextEdit.value.datatype + lastEdit.values = [lastEdit.value.value, nextEdit.value.value] + delete lastEdit.value + delete lastEdit.opId - var acc = 0; - for (var i = this.length - 1; i >= 0; i--) { - acc = (p * acc + (this.words[i] | 0)) % num; - } + } else if (lastEdit.action === 'multi-insert' && nextEdit.action === 'insert' && + lastEdit.index + lastEdit.values.length === nextEdit.index && + nextEdit.value.type === 'value' && nextEdit.elemId === nextEdit.opId && + opIdDelta(lastEdit.elemId, nextEdit.elemId, lastEdit.values.length) && + lastEdit.datatype === nextEdit.value.datatype && + typeof lastEdit.values[0] === typeof nextEdit.value.value) { + lastEdit.values.push(nextEdit.value.value) - return acc; - }; + } else if (lastEdit.action === 'remove' && nextEdit.action === 'remove' && + lastEdit.index === nextEdit.index) { + lastEdit.count += nextEdit.count - // In-place division by number - BN.prototype.idivn = function idivn (num) { - assert(num <= 0x3ffffff); + } else { + existingEdits.push(nextEdit) + } +} - var carry = 0; - for (var i = this.length - 1; i >= 0; i--) { - var w = (this.words[i] | 0) + carry * 0x4000000; - this.words[i] = (w / num) | 0; - carry = w % num; +/** + * `edits` is an array of (SingleInsertEdit | MultiInsertEdit | UpdateEdit | RemoveEdit) list edits + * for a patch. This function appends an UpdateEdit to this array. A conflict is represented by + * having several consecutive edits with the same index, and this can be realised by calling + * `appendUpdate` several times for the same list element. On the first such call, `firstUpdate` + * must be true. + * + * It is possible that coincidentally the previous edit (potentially arising from a different + * change) is for the same index. If this is the case, to avoid accidentally treating consecutive + * updates for the same index as a conflict, we remove the previous edit for the same index. This is + * safe because the previous edit is overwritten by the new edit being appended, and we know that + * it's for the same list elements because there are no intervening insertions/deletions that could + * have changed the indexes. + */ +function appendUpdate(edits, index, elemId, opId, value, firstUpdate) { + let insert = false + if (firstUpdate) { + // Pop all edits for the same index off the end of the edits array. This sequence may begin with + // either an insert or an update. If it's an insert, we remember that fact, and use it below. + while (!insert && edits.length > 0) { + const lastEdit = edits[edits.length - 1] + if ((lastEdit.action === 'insert' || lastEdit.action === 'update') && lastEdit.index === index) { + edits.pop() + insert = (lastEdit.action === 'insert') + } else if (lastEdit.action === 'multi-insert' && lastEdit.index + lastEdit.values.length - 1 === index) { + lastEdit.values.pop() + insert = true + } else { + break + } } + } - return this.strip(); - }; - - BN.prototype.divn = function divn (num) { - return this.clone().idivn(num); - }; - - BN.prototype.egcd = function egcd (p) { - assert(p.negative === 0); - assert(!p.isZero()); - - var x = this; - var y = p.clone(); + // If we popped an insert edit off the edits array, we need to turn the new update into an insert + // in order to ensure the list element still gets inserted (just with a new value). + if (insert) { + appendEdit(edits, {action: 'insert', index, elemId, opId, value}) + } else { + appendEdit(edits, {action: 'update', index, opId, value}) + } +} - if (x.negative !== 0) { - x = x.umod(p); +/** + * `edits` is an array of (SingleInsertEdit | MultiInsertEdit | UpdateEdit | RemoveEdit) list edits + * for a patch. We assume that there is a suffix of this array that consists of an insertion at + * position `index`, followed by zero or more UpdateEdits at the same index. This function rewrites + * that suffix to be all updates instead. This is needed because sometimes when generating a patch + * we think we are performing a list insertion, but then it later turns out that there was already + * an existing value at that list element, and so we actually need to do an update, not an insert. + * + * If the suffix is preceded by one or more updates at the same index, those earlier updates are + * removed by `appendUpdate()` to ensure we don't inadvertently treat them as part of the same + * conflict. + */ +function convertInsertToUpdate(edits, index, elemId) { + let updates = [] + while (edits.length > 0) { + let lastEdit = edits[edits.length - 1] + if (lastEdit.action === 'insert') { + if (lastEdit.index !== index) throw new RangeError('last edit has unexpected index') + updates.unshift(edits.pop()) + break + } else if (lastEdit.action === 'update') { + if (lastEdit.index !== index) throw new RangeError('last edit has unexpected index') + updates.unshift(edits.pop()) } else { - x = x.clone(); + // It's impossible to encounter a remove edit here because the state machine in + // updatePatchProperty() ensures that a property can have either an insert or a remove edit, + // but not both. It's impossible to encounter a multi-insert here because multi-inserts always + // have equal elemId and opId (i.e. they can only be used for the operation that first inserts + // an element, but not for any subsequent assignments to that list element); moreover, + // convertInsertToUpdate is only called if an insert action is followed by a non-overwritten + // document op. The fact that there is a non-overwritten document op after another op on the + // same list element implies that the original insertion op for that list element must be + // overwritten, and thus the original insertion op cannot have given rise to a multi-insert. + throw new RangeError('last edit has unexpected action') } + } - // A * x + B * y = x - var A = new BN(1); - var B = new BN(0); - - // C * x + D * y = y - var C = new BN(0); - var D = new BN(1); - - var g = 0; - - while (x.isEven() && y.isEven()) { - x.iushrn(1); - y.iushrn(1); - ++g; - } + // Now take the edits we popped off and push them back onto the list again + let firstUpdate = true + for (let update of updates) { + appendUpdate(edits, index, elemId, update.opId, update.value, firstUpdate) + firstUpdate = false + } +} - var yp = y.clone(); - var xp = x.clone(); +/** + * Updates `patches` to reflect the operation `op` within the document with state `docState`. + * Can be called multiple times if there are multiple operations for the same property (e.g. due + * to a conflict). `propState` is an object that carries over state between such successive + * invocations for the same property. If the current object is a list, `listIndex` is the index + * into that list (counting only visible elements). If the operation `op` was already previously + * in the document, `oldSuccNum` is the value of `op[succNumIdx]` before the current change was + * applied (allowing us to determine whether this operation was overwritten or deleted in the + * current change). `oldSuccNum` must be undefined if the operation came from the current change. + * If we are creating an incremental patch as a result of applying one or more changes, `newBlock` + * is the block to which the operations are getting written; we will update the metadata on this + * block. `newBlock` should be null if we are creating a patch for the whole document. + */ +function updatePatchProperty(patches, newBlock, objectId, op, docState, propState, listIndex, oldSuccNum) { + const isWholeDoc = !newBlock + const type = op[actionIdx] < ACTIONS.length ? OBJECT_TYPE[ACTIONS[op[actionIdx]]] : null + const opId = `${op[idCtrIdx]}@${docState.actorIds[op[idActorIdx]]}` + const elemIdActor = op[insertIdx] ? op[idActorIdx] : op[keyActorIdx] + const elemIdCtr = op[insertIdx] ? op[idCtrIdx] : op[keyCtrIdx] + const elemId = op[keyStrIdx] ? op[keyStrIdx] : `${elemIdCtr}@${docState.actorIds[elemIdActor]}` - while (!x.isZero()) { - for (var i = 0, im = 1; (x.words[0] & im) === 0 && i < 26; ++i, im <<= 1); - if (i > 0) { - x.iushrn(i); - while (i-- > 0) { - if (A.isOdd() || B.isOdd()) { - A.iadd(yp); - B.isub(xp); - } + // When the change contains a new make* operation (i.e. with an even-numbered action), record the + // new parent-child relationship in objectMeta. TODO: also handle link/move operations. + if (op[actionIdx] % 2 === 0 && !docState.objectMeta[opId]) { + docState.objectMeta[opId] = {parentObj: objectId, parentKey: elemId, opId, type, children: {}} + deepCopyUpdate(docState.objectMeta, [objectId, 'children', elemId, opId], {objectId: opId, type, props: {}}) + } - A.iushrn(1); - B.iushrn(1); - } - } + // firstOp is true if the current operation is the first of a sequence of ops for the same key + const firstOp = !propState[elemId] + if (!propState[elemId]) propState[elemId] = {visibleOps: [], hasChild: false} - for (var j = 0, jm = 1; (y.words[0] & jm) === 0 && j < 26; ++j, jm <<= 1); - if (j > 0) { - y.iushrn(j); - while (j-- > 0) { - if (C.isOdd() || D.isOdd()) { - C.iadd(yp); - D.isub(xp); - } + // An operation is overwritten if it is a document operation that has at least one successor + const isOverwritten = (oldSuccNum !== undefined && op[succNumIdx] > 0) - C.iushrn(1); - D.iushrn(1); - } - } + // Record all visible values for the property, and whether it has any child object + if (!isOverwritten) { + propState[elemId].visibleOps.push(op) + propState[elemId].hasChild = propState[elemId].hasChild || (op[actionIdx] % 2) === 0 // even-numbered action == make* operation + } - if (x.cmp(y) >= 0) { - x.isub(y); - A.isub(C); - B.isub(D); - } else { - y.isub(x); - C.isub(A); - D.isub(B); + // If one or more of the values of the property is a child object, we update objectMeta to store + // all of the visible values of the property (even the non-child-object values). Then, when we + // subsequently process an update within that child object, we can construct the patch to + // contain the conflicting values. + const prevChildren = docState.objectMeta[objectId].children[elemId] + if (propState[elemId].hasChild || (prevChildren && Object.keys(prevChildren).length > 0)) { + let values = {} + for (let visible of propState[elemId].visibleOps) { + const opId = `${visible[idCtrIdx]}@${docState.actorIds[visible[idActorIdx]]}` + if (ACTIONS[visible[actionIdx]] === 'set') { + values[opId] = Object.assign({type: 'value'}, decodeValue(visible[valLenIdx], visible[valRawIdx])) + } else if (visible[actionIdx] % 2 === 0) { + const objType = visible[actionIdx] < ACTIONS.length ? OBJECT_TYPE[ACTIONS[visible[actionIdx]]] : null + values[opId] = emptyObjectPatch(opId, objType) } } - return { - a: C, - b: D, - gcd: y.iushln(g) - }; - }; + // Copy so that objectMeta is not modified if an exception is thrown while applying change + deepCopyUpdate(docState.objectMeta, [objectId, 'children', elemId], values) + } - // This is reduced incarnation of the binary EEA - // above, designated to invert members of the - // _prime_ fields F(p) at a maximal speed - BN.prototype._invmp = function _invmp (p) { - assert(p.negative === 0); - assert(!p.isZero()); + let patchKey, patchValue - var a = this; - var b = p.clone(); + // For counters, increment operations are succs to the set operation that created the counter, + // but in this case we want to add the values rather than overwriting them. + if (isOverwritten && ACTIONS[op[actionIdx]] === 'set' && (op[valLenIdx] & 0x0f) === VALUE_TYPE.COUNTER) { + // This is the initial set operation that creates a counter. Initialise the counter state + // to contain all successors of the set operation. Only if we later find that each of these + // successor operations is an increment, we make the counter visible in the patch. + if (!propState[elemId]) propState[elemId] = {visibleOps: [], hasChild: false} + if (!propState[elemId].counterStates) propState[elemId].counterStates = {} + let counterStates = propState[elemId].counterStates + let counterState = {opId, value: decodeValue(op[valLenIdx], op[valRawIdx]).value, succs: {}} - if (a.negative !== 0) { - a = a.umod(p); - } else { - a = a.clone(); + for (let i = 0; i < op[succNumIdx]; i++) { + const succOp = `${op[succCtrIdx][i]}@${docState.actorIds[op[succActorIdx][i]]}` + counterStates[succOp] = counterState + counterState.succs[succOp] = true } - var x1 = new BN(1); - var x2 = new BN(0); + } else if (ACTIONS[op[actionIdx]] === 'inc') { + // Incrementing a previously created counter. + if (!propState[elemId] || !propState[elemId].counterStates || !propState[elemId].counterStates[opId]) { + throw new RangeError(`increment operation ${opId} for unknown counter`) + } + let counterState = propState[elemId].counterStates[opId] + counterState.value += decodeValue(op[valLenIdx], op[valRawIdx]).value + delete counterState.succs[opId] - var delta = b.clone(); + if (Object.keys(counterState.succs).length === 0) { + patchKey = counterState.opId + patchValue = {type: 'value', datatype: 'counter', value: counterState.value} + // TODO if the counter is in a list element, we need to add a 'remove' action when deleted + } - while (a.cmpn(1) > 0 && b.cmpn(1) > 0) { - for (var i = 0, im = 1; (a.words[0] & im) === 0 && i < 26; ++i, im <<= 1); - if (i > 0) { - a.iushrn(i); - while (i-- > 0) { - if (x1.isOdd()) { - x1.iadd(delta); - } + } else if (!isOverwritten) { + // Add the value to the patch if it is not overwritten (i.e. if it has no succs). + if (ACTIONS[op[actionIdx]] === 'set') { + patchKey = opId + patchValue = Object.assign({type: 'value'}, decodeValue(op[valLenIdx], op[valRawIdx])) + } else if (op[actionIdx] % 2 === 0) { // even-numbered action == make* operation + if (!patches[opId]) patches[opId] = emptyObjectPatch(opId, type) + patchKey = opId + patchValue = patches[opId] + } + } - x1.iushrn(1); - } + if (!patches[objectId]) patches[objectId] = emptyObjectPatch(objectId, docState.objectMeta[objectId].type) + const patch = patches[objectId] + + // Updating a list or text object (with elemId key) + if (op[keyStrIdx] === null) { + // If we come across any document op that was previously non-overwritten/non-deleted, that + // means the current list element already had a value before this change was applied, and + // therefore the current element cannot be an insert. If we already registered an insert, we + // have to convert it into an update. + if (oldSuccNum === 0 && !isWholeDoc && propState[elemId].action === 'insert') { + propState[elemId].action = 'update' + convertInsertToUpdate(patch.edits, listIndex, elemId) + if (newBlock && newBlock.lastObjectActor === op[objActorIdx] && newBlock.lastObjectCtr === op[objCtrIdx]) { + newBlock.numVisible -= 1 } + } - for (var j = 0, jm = 1; (b.words[0] & jm) === 0 && j < 26; ++j, jm <<= 1); - if (j > 0) { - b.iushrn(j); - while (j-- > 0) { - if (x2.isOdd()) { - x2.iadd(delta); - } + if (patchValue) { + // If the op has a non-overwritten value and it came from the change, it's an insert. + // (It's not necessarily the case that op[insertIdx] is true: if a list element is concurrently + // deleted and updated, the node that first processes the deletion and then the update will + // observe the update as a re-insertion of the deleted list element.) + if (!propState[elemId].action && (oldSuccNum === undefined || isWholeDoc)) { + propState[elemId].action = 'insert' + appendEdit(patch.edits, {action: 'insert', index: listIndex, elemId, opId: patchKey, value: patchValue}) + if (newBlock && newBlock.lastObjectActor === op[objActorIdx] && newBlock.lastObjectCtr === op[objCtrIdx]) { + newBlock.numVisible += 1 + } - x2.iushrn(1); + // If the property has a value and it's not an insert, then it must be an update. + // We might have previously registered it as a remove, in which case we convert it to update. + } else if (propState[elemId].action === 'remove') { + let lastEdit = patch.edits[patch.edits.length - 1] + if (lastEdit.action !== 'remove') throw new RangeError('last edit has unexpected type') + if (lastEdit.count > 1) lastEdit.count -= 1; else patch.edits.pop() + propState[elemId].action = 'update' + appendUpdate(patch.edits, listIndex, elemId, patchKey, patchValue, true) + if (newBlock && newBlock.lastObjectActor === op[objActorIdx] && newBlock.lastObjectCtr === op[objCtrIdx]) { + newBlock.numVisible += 1 } - } - if (a.cmp(b) >= 0) { - a.isub(b); - x1.isub(x2); } else { - b.isub(a); - x2.isub(x1); + // A 'normal' update + appendUpdate(patch.edits, listIndex, elemId, patchKey, patchValue, !propState[elemId].action) + if (!propState[elemId].action) propState[elemId].action = 'update' } - } - var res; - if (a.cmpn(1) === 0) { - res = x1; - } else { - res = x2; + } else if (oldSuccNum === 0 && !propState[elemId].action) { + // If the property used to have a non-overwritten/non-deleted value, but no longer, it's a remove + propState[elemId].action = 'remove' + appendEdit(patch.edits, {action: 'remove', index: listIndex, count: 1}) + if (newBlock && newBlock.lastObjectActor === op[objActorIdx] && newBlock.lastObjectCtr === op[objCtrIdx]) { + newBlock.numVisible -= 1 + } } - if (res.cmpn(0) < 0) { - res.iadd(p); - } + } else if (patchValue || !isWholeDoc) { + // Updating a map or table (with string key) + if (firstOp || !patch.props[op[keyStrIdx]]) patch.props[op[keyStrIdx]] = {} + if (patchValue) patch.props[op[keyStrIdx]][patchKey] = patchValue + } +} - return res; - }; +/** + * Applies operations (from one or more changes) to the document by merging the sequence of change + * ops into the sequence of document ops. The two inputs are `changeState` and `docState` + * respectively. Assumes that the decoders of both sets of columns are at the position where we want + * to start merging. `patches` is mutated to reflect the effect of the change operations. `ops` is + * the operation sequence to apply (as decoded by `groupRelatedOps()`). `docState` is as + * documented in `applyOps()`. If the operations are updating a list or text object, `listIndex` + * is the number of visible elements that precede the position at which we start merging. + * `blockIndex` is the document block number from which we are currently reading. + */ +function mergeDocChangeOps(patches, newBlock, outCols, changeState, docState, listIndex, blockIndex) { + const firstOp = changeState.nextOp, insert = firstOp[insertIdx] + const objActor = firstOp[objActorIdx], objCtr = firstOp[objCtrIdx] + const objectId = objActor === null ? '_root' : `${objCtr}@${docState.actorIds[objActor]}` + const idActorIndex = changeState.actorIndex, idActor = docState.actorIds[idActorIndex] + let foundListElem = false, elemVisible = false, propState = {}, docOp + ;({ docOp, blockIndex } = readNextDocOp(docState, blockIndex)) + let docOpsConsumed = (docOp === null ? 0 : 1) + let docOpOldSuccNum = (docOp === null ? 0 : docOp[succNumIdx]) + let changeOp = null, changeOps = [], changeCols = [], predSeen = [], lastChangeKey = null + changeState.objectIds.add(objectId) - BN.prototype.gcd = function gcd (num) { - if (this.isZero()) return num.abs(); - if (num.isZero()) return this.abs(); + // Merge the two inputs: the sequence of ops in the doc, and the sequence of ops in the change. + // At each iteration, we either output the doc's op (possibly updated based on the change's ops) + // or output an op from the change. + while (true) { + // The array `changeOps` contains operations from the change(s) we're applying. When the array + // is empty, we load changes from the change. Typically we load only a single operation at a + // time, with two exceptions: 1. all operations that update the same key or list element in the + // same object are put into changeOps at the same time (this is needed so that we can update the + // succ columns of the document ops correctly); 2. a run of consecutive insertions is also + // placed into changeOps in one go. + // + // When we have processed all the ops in changeOps we try to see whether there are further + // operations that we can also process while we're at it. Those operations must be for the same + // object, they must be for a key or list element that appears later in the document, they must + // either all be insertions or all be non-insertions, and if insertions, they must be + // consecutive. If these conditions are satisfied, that means the operations can be processed in + // the same pass. If we encounter an operation that does not meet these conditions, we leave + // changeOps empty, and this function returns after having processed any remaining document ops. + // + // Any operations that could not be processed in a single pass remain in changeState; applyOps + // will seek to the appropriate position and then call mergeDocChangeOps again. + if (changeOps.length === 0) { + foundListElem = false - var a = this.clone(); - var b = num.clone(); - a.negative = 0; - b.negative = 0; + let nextOp = changeState.nextOp + while (!changeState.done && nextOp[idActorIdx] === idActorIndex && nextOp[insertIdx] === insert && + nextOp[objActorIdx] === firstOp[objActorIdx] && nextOp[objCtrIdx] === firstOp[objCtrIdx]) { - // Remove common factor of two - for (var shift = 0; a.isEven() && b.isEven(); shift++) { - a.iushrn(1); - b.iushrn(1); - } + // Check if the operation's pred references a previous operation in changeOps + const lastOp = (changeOps.length > 0) ? changeOps[changeOps.length - 1] : null + let isOverwrite = false + for (let i = 0; i < nextOp[predNumIdx]; i++) { + for (let prevOp of changeOps) { + if (nextOp[predActorIdx][i] === prevOp[idActorIdx] && nextOp[predCtrIdx][i] === prevOp[idCtrIdx]) { + isOverwrite = true + } + } + } - do { - while (a.isEven()) { - a.iushrn(1); - } - while (b.isEven()) { - b.iushrn(1); - } + // If any of the following `if` statements is true, we add `nextOp` to `changeOps`. If they + // are all false, we break out of the loop and stop adding to `changeOps`. + if (nextOp === firstOp) { + // First change operation in a mergeDocChangeOps call is always used + } else if (insert && lastOp !== null && nextOp[keyStrIdx] === null && + nextOp[keyActorIdx] === lastOp[idActorIdx] && + nextOp[keyCtrIdx] === lastOp[idCtrIdx]) { + // Collect consecutive insertions + } else if (!insert && lastOp !== null && nextOp[keyStrIdx] !== null && + nextOp[keyStrIdx] === lastOp[keyStrIdx] && !isOverwrite) { + // Collect several updates to the same key + } else if (!insert && lastOp !== null && + nextOp[keyStrIdx] === null && lastOp[keyStrIdx] === null && + nextOp[keyActorIdx] === lastOp[keyActorIdx] && + nextOp[keyCtrIdx] === lastOp[keyCtrIdx] && !isOverwrite) { + // Collect several updates to the same list element + } else if (!insert && lastOp === null && nextOp[keyStrIdx] === null && + docOp && docOp[insertIdx] && docOp[keyStrIdx] === null && + docOp[idActorIdx] === nextOp[keyActorIdx] && + docOp[idCtrIdx] === nextOp[keyCtrIdx]) { + // When updating/deleting list elements, keep going if the next elemId in the change + // equals the next elemId in the doc (i.e. we're updating several consecutive elements) + } else if (!insert && lastOp === null && nextOp[keyStrIdx] !== null && + lastChangeKey !== null && lastChangeKey < nextOp[keyStrIdx]) { + // Allow a single mergeDocChangeOps call to process changes to several keys in the same + // object, provided that they appear in ascending order + } else break - var r = a.cmp(b); - if (r < 0) { - // Swap `a` and `b` to make `a` always bigger than `b` - var t = a; - a = b; - b = t; - } else if (r === 0 || b.cmpn(1) === 0) { - break; + lastChangeKey = (nextOp !== null) ? nextOp[keyStrIdx] : null + changeOps.push(changeState.nextOp) + changeCols.push(changeState.columns) + predSeen.push(new Array(changeState.nextOp[predNumIdx])) + readNextChangeOp(docState, changeState) + nextOp = changeState.nextOp } + } - a.isub(b); - } while (true); - - return b.iushln(shift); - }; - - // Invert number in the field F(num) - BN.prototype.invm = function invm (num) { - return this.egcd(num).a.umod(num); - }; - - BN.prototype.isEven = function isEven () { - return (this.words[0] & 1) === 0; - }; + if (changeOps.length > 0) changeOp = changeOps[0] + const inCorrectObject = docOp && docOp[objActorIdx] === changeOp[objActorIdx] && docOp[objCtrIdx] === changeOp[objCtrIdx] + const keyMatches = docOp && docOp[keyStrIdx] !== null && docOp[keyStrIdx] === changeOp[keyStrIdx] + const listElemMatches = docOp && docOp[keyStrIdx] === null && changeOp[keyStrIdx] === null && + ((!docOp[insertIdx] && docOp[keyActorIdx] === changeOp[keyActorIdx] && docOp[keyCtrIdx] === changeOp[keyCtrIdx]) || + (docOp[insertIdx] && docOp[idActorIdx] === changeOp[keyActorIdx] && docOp[idCtrIdx] === changeOp[keyCtrIdx])) - BN.prototype.isOdd = function isOdd () { - return (this.words[0] & 1) === 1; - }; + // We keep going until we run out of ops in the change, except that even when we run out, we + // keep going until we have processed all doc ops for the current key/list element. + if (changeOps.length === 0 && !(inCorrectObject && (keyMatches || listElemMatches))) break - // And first word and num - BN.prototype.andln = function andln (num) { - return this.words[0] & num; - }; + let takeDocOp = false, takeChangeOps = 0 - // Increment at the bit position in-line - BN.prototype.bincn = function bincn (bit) { - assert(typeof bit === 'number'); - var r = bit % 26; - var s = (bit - r) / 26; - var q = 1 << r; + // The change operations come first if we are inserting list elements (seekToOp already + // determines the correct insertion position), if there is no document operation, if the next + // document operation is for a different object, or if the change op's string key is + // lexicographically first (TODO check ordering of keys beyond the basic multilingual plane). + if (insert || !inCorrectObject || + (docOp[keyStrIdx] === null && changeOp[keyStrIdx] !== null) || + (docOp[keyStrIdx] !== null && changeOp[keyStrIdx] !== null && changeOp[keyStrIdx] < docOp[keyStrIdx])) { + // Take the operations from the change + takeChangeOps = changeOps.length + if (!inCorrectObject && !foundListElem && changeOp[keyStrIdx] === null && !changeOp[insertIdx]) { + // This can happen if we first update one list element, then another one earlier in the + // list. That is not allowed: list element updates must occur in ascending order. + throw new RangeError("could not find list element with ID: " + + `${changeOp[keyCtrIdx]}@${docState.actorIds[changeOp[keyActorIdx]]}`) + } - // Fast case: bit is much higher than all existing words - if (this.length <= s) { - this._expand(s + 1); - this.words[s] |= q; - return this; - } - - // Add bit and propagate, if needed - var carry = q; - for (var i = s; carry !== 0 && i < this.length; i++) { - var w = this.words[i] | 0; - w += carry; - carry = w >>> 26; - w &= 0x3ffffff; - this.words[i] = w; - } - if (carry !== 0) { - this.words[i] = carry; - this.length++; - } - return this; - }; + } else if (keyMatches || listElemMatches || foundListElem) { + // The doc operation is for the same key or list element in the same object as the change + // ops, so we merge them. First, if any of the change ops' `pred` matches the opId of the + // document operation, we update the document operation's `succ` accordingly. + for (let opIndex = 0; opIndex < changeOps.length; opIndex++) { + const op = changeOps[opIndex] + for (let i = 0; i < op[predNumIdx]; i++) { + if (op[predActorIdx][i] === docOp[idActorIdx] && op[predCtrIdx][i] === docOp[idCtrIdx]) { + // Insert into the doc op's succ list such that the lists remains sorted + let j = 0 + while (j < docOp[succNumIdx] && (docOp[succCtrIdx][j] < op[idCtrIdx] || + docOp[succCtrIdx][j] === op[idCtrIdx] && docState.actorIds[docOp[succActorIdx][j]] < idActor)) j++ + docOp[succCtrIdx].splice(j, 0, op[idCtrIdx]) + docOp[succActorIdx].splice(j, 0, idActorIndex) + docOp[succNumIdx]++ + predSeen[opIndex][i] = true + break + } + } + } - BN.prototype.isZero = function isZero () { - return this.length === 1 && this.words[0] === 0; - }; + if (listElemMatches) foundListElem = true - BN.prototype.cmpn = function cmpn (num) { - var negative = num < 0; + if (foundListElem && !listElemMatches) { + // If the previous docOp was for the correct list element, and the current docOp is for + // the wrong list element, then place the current changeOp before the docOp. + takeChangeOps = changeOps.length - if (this.negative !== 0 && !negative) return -1; - if (this.negative === 0 && negative) return 1; + } else if (changeOps.length === 0 || docOp[idCtrIdx] < changeOp[idCtrIdx] || + (docOp[idCtrIdx] === changeOp[idCtrIdx] && docState.actorIds[docOp[idActorIdx]] < idActor)) { + // When we have several operations for the same object and the same key, we want to keep + // them sorted in ascending order by opId. Here we have docOp with a lower opId, so we + // output it first. + takeDocOp = true + updatePatchProperty(patches, newBlock, objectId, docOp, docState, propState, listIndex, docOpOldSuccNum) - this.strip(); + // A deletion op in the change is represented in the document only by its entries in the + // succ list of the operations it overwrites; it has no separate row in the set of ops. + for (let i = changeOps.length - 1; i >= 0; i--) { + let deleted = true + for (let j = 0; j < changeOps[i][predNumIdx]; j++) { + if (!predSeen[i][j]) deleted = false + } + if (ACTIONS[changeOps[i][actionIdx]] === 'del' && deleted) { + changeOps.splice(i, 1) + changeCols.splice(i, 1) + predSeen.splice(i, 1) + } + } - var res; - if (this.length > 1) { - res = 1; - } else { - if (negative) { - num = -num; + } else if (docOp[idCtrIdx] === changeOp[idCtrIdx] && docState.actorIds[docOp[idActorIdx]] === idActor) { + throw new RangeError(`duplicate operation ID: ${changeOp[idCtrIdx]}@${idActor}`) + } else { + // The changeOp has the lower opId, so we output it first. + takeChangeOps = 1 } - - assert(num <= 0x3ffffff, 'Number is too big'); - - var w = this.words[0] | 0; - res = w === num ? 0 : w < num ? -1 : 1; + } else { + // The document operation comes first if its string key is lexicographically first, or if + // we're using opId keys and the keys don't match (i.e. we scan the document until we find a + // matching key). + takeDocOp = true } - if (this.negative !== 0) return -res | 0; - return res; - }; - // Compare two numbers and return: - // 1 - if `this` > `num` - // 0 - if `this` == `num` - // -1 - if `this` < `num` - BN.prototype.cmp = function cmp (num) { - if (this.negative !== 0 && num.negative === 0) return -1; - if (this.negative === 0 && num.negative !== 0) return 1; + if (takeDocOp) { + appendOperation(outCols, docState.blocks[blockIndex].columns, docOp) + addBlockOperation(newBlock, docOp, docState.actorIds, false) - var res = this.ucmp(num); - if (this.negative !== 0) return -res | 0; - return res; - }; + if (docOp[insertIdx] && elemVisible) { + elemVisible = false + listIndex++ + } + if (docOp[succNumIdx] === 0) elemVisible = true + newBlock.numOps++ + ;({ docOp, blockIndex } = readNextDocOp(docState, blockIndex)) + if (docOp !== null) { + docOpsConsumed++ + docOpOldSuccNum = docOp[succNumIdx] + } + } - // Unsigned comparison - BN.prototype.ucmp = function ucmp (num) { - // At this point both numbers have the same sign - if (this.length > num.length) return 1; - if (this.length < num.length) return -1; + if (takeChangeOps > 0) { + for (let i = 0; i < takeChangeOps; i++) { + let op = changeOps[i] + // Check that we've seen all ops mentioned in `pred` (they must all have lower opIds than + // the change op's own opId, so we must have seen them already) + for (let j = 0; j < op[predNumIdx]; j++) { + if (!predSeen[i][j]) { + throw new RangeError(`no matching operation for pred: ${op[predCtrIdx][j]}@${docState.actorIds[op[predActorIdx][j]]}`) + } + } + appendOperation(outCols, changeCols[i], op) + addBlockOperation(newBlock, op, docState.actorIds, true) + updatePatchProperty(patches, newBlock, objectId, op, docState, propState, listIndex) - var res = 0; - for (var i = this.length - 1; i >= 0; i--) { - var a = this.words[i] | 0; - var b = num.words[i] | 0; + if (op[insertIdx]) { + elemVisible = false + listIndex++ + } else { + elemVisible = true + } + } - if (a === b) continue; - if (a < b) { - res = -1; - } else if (a > b) { - res = 1; + if (takeChangeOps === changeOps.length) { + changeOps.length = 0 + changeCols.length = 0 + predSeen.length = 0 + } else { + changeOps.splice(0, takeChangeOps) + changeCols.splice(0, takeChangeOps) + predSeen.splice(0, takeChangeOps) } - break; + newBlock.numOps += takeChangeOps } - return res; - }; + } - BN.prototype.gtn = function gtn (num) { - return this.cmpn(num) === 1; - }; + if (docOp) { + appendOperation(outCols, docState.blocks[blockIndex].columns, docOp) + newBlock.numOps++ + addBlockOperation(newBlock, docOp, docState.actorIds, false) + } + return {docOpsConsumed, blockIndex} +} - BN.prototype.gt = function gt (num) { - return this.cmp(num) === 1; - }; +/** + * Applies operations from the change (or series of changes) in `changeState` to the document + * `docState`. Passing `changeState` to `readNextChangeOp` allows iterating over the change ops. + * `docState` is an object with keys: + * - `actorIds` is an array of actorIds (as hex strings) occurring in the document (values in + * the document's objActor/keyActor/idActor/... columns are indexes into this array). + * - `blocks` is an array of all the blocks of operations in the document. + * - `objectMeta` is a map from objectId to metadata about that object. + * + * `docState` is mutated to contain the updated document state. + * `patches` is a patch object that is mutated to reflect the operations applied by this function. + */ +function applyOps(patches, changeState, docState) { + const [objActorNum, objCtr, keyActorNum, keyCtr, keyStr, idActorNum, idCtr, insert] = changeState.nextOp + const objActor = objActorNum === null ? null : docState.actorIds[objActorNum] + const keyActor = keyActorNum === null ? null : docState.actorIds[keyActorNum] + const ops = { + objActor, objActorNum, objCtr, keyActor, keyActorNum, keyCtr, keyStr, + idActor: docState.actorIds[idActorNum], idCtr, insert, + objId: objActor === null ? '_root' : `${objCtr}@${objActor}` + } - BN.prototype.gten = function gten (num) { - return this.cmpn(num) >= 0; - }; + const {blockIndex, skipCount, visibleCount} = seekToOp(docState, ops) + const block = docState.blocks[blockIndex] + for (let col of block.columns) col.decoder.reset() - BN.prototype.gte = function gte (num) { - return this.cmp(num) >= 0; - }; + const resetFirstVisible = (skipCount === 0) || (block.firstVisibleActor === undefined) || + (!insert && block.firstVisibleActor === keyActorNum && block.firstVisibleCtr === keyCtr) + const newBlock = { + columns: undefined, + bloom: new Uint8Array(block.bloom), + numOps: skipCount, + lastKey: block.lastKey, + numVisible: block.numVisible, + lastObjectActor: block.lastObjectActor, + lastObjectCtr: block.lastObjectCtr, + firstVisibleActor: resetFirstVisible ? undefined : block.firstVisibleActor, + firstVisibleCtr: resetFirstVisible ? undefined : block.firstVisibleCtr, + lastVisibleActor: undefined, + lastVisibleCtr: undefined + } - BN.prototype.ltn = function ltn (num) { - return this.cmpn(num) === -1; - }; + // Copy the operations up to the insertion position (the first skipCount operations) + const outCols = block.columns.map(col => ({columnId: col.columnId, encoder: encoderByColumnId(col.columnId)})) + copyColumns(outCols, block.columns, skipCount) - BN.prototype.lt = function lt (num) { - return this.cmp(num) === -1; - }; + // Apply the operations from the change. This may cause blockIndex to move forwards if the + // property being updated straddles a block boundary. + const {blockIndex: lastBlockIndex, docOpsConsumed} = + mergeDocChangeOps(patches, newBlock, outCols, changeState, docState, visibleCount, blockIndex) - BN.prototype.lten = function lten (num) { - return this.cmpn(num) <= 0; - }; + // Copy the remaining operations after the insertion position + const lastBlock = docState.blocks[lastBlockIndex] + let copyAfterMerge = -skipCount - docOpsConsumed + for (let i = blockIndex; i <= lastBlockIndex; i++) copyAfterMerge += docState.blocks[i].numOps + copyColumns(outCols, lastBlock.columns, copyAfterMerge) + newBlock.numOps += copyAfterMerge - BN.prototype.lte = function lte (num) { - return this.cmp(num) <= 0; - }; + for (let col of lastBlock.columns) { + if (!col.decoder.done) throw new RangeError(`excess ops in column ${col.columnId}`) + } - BN.prototype.eqn = function eqn (num) { - return this.cmpn(num) === 0; - }; + newBlock.columns = outCols.map(col => { + const decoder = decoderByColumnId(col.columnId, col.encoder.buffer) + return {columnId: col.columnId, decoder} + }) - BN.prototype.eq = function eq (num) { - return this.cmp(num) === 0; - }; + if (blockIndex === lastBlockIndex && newBlock.numOps <= MAX_BLOCK_SIZE) { + // The result is just one output block + if (copyAfterMerge > 0 && block.lastVisibleActor !== undefined && block.lastVisibleCtr !== undefined) { + // It's possible that none of the ops after the merge point are visible, in which case the + // lastVisible may not be strictly correct, because it may refer to an operation before the + // merge point rather than a list element inserted by the current change. However, this doesn't + // matter, because the only purpose for which we need it is to check whether one block ends with + // the same visible element as the next block starts with (to avoid double-counting its index); + // if the last list element of a block is invisible, the exact value of lastVisible doesn't + // matter since it will be different from the next block's firstVisible in any case. + newBlock.lastVisibleActor = block.lastVisibleActor + newBlock.lastVisibleCtr = block.lastVisibleCtr + } - // - // A reduce context, could be using montgomery or something better, depending - // on the `m` itself. - // - BN.red = function red (num) { - return new Red(num); - }; + docState.blocks[blockIndex] = newBlock - BN.prototype.toRed = function toRed (ctx) { - assert(!this.red, 'Already a number in reduction context'); - assert(this.negative === 0, 'red works only with positives'); - return ctx.convertTo(this)._forceRed(ctx); - }; + } else { + // Oversized output block must be split into smaller blocks + const newBlocks = splitBlock(newBlock) + docState.blocks.splice(blockIndex, lastBlockIndex - blockIndex + 1, ...newBlocks) + } +} - BN.prototype.fromRed = function fromRed () { - assert(this.red, 'fromRed works only with numbers in reduction context'); - return this.red.convertFrom(this); - }; +/** + * Updates the columns in a document's operation blocks to contain all the columns in a change + * (including any column types we don't recognise, which have been generated by a future version + * of Automerge). + */ +function updateBlockColumns(docState, changeCols) { + // Check that the columns of a change appear at the index at which we expect them to be + if (changeCols[objActorIdx ].columnId !== CHANGE_COLUMNS[objActorIdx ].columnId || CHANGE_COLUMNS[objActorIdx ].columnName !== 'objActor' || + changeCols[objCtrIdx ].columnId !== CHANGE_COLUMNS[objCtrIdx ].columnId || CHANGE_COLUMNS[objCtrIdx ].columnName !== 'objCtr' || + changeCols[keyActorIdx ].columnId !== CHANGE_COLUMNS[keyActorIdx ].columnId || CHANGE_COLUMNS[keyActorIdx ].columnName !== 'keyActor' || + changeCols[keyCtrIdx ].columnId !== CHANGE_COLUMNS[keyCtrIdx ].columnId || CHANGE_COLUMNS[keyCtrIdx ].columnName !== 'keyCtr' || + changeCols[keyStrIdx ].columnId !== CHANGE_COLUMNS[keyStrIdx ].columnId || CHANGE_COLUMNS[keyStrIdx ].columnName !== 'keyStr' || + changeCols[idActorIdx ].columnId !== CHANGE_COLUMNS[idActorIdx ].columnId || CHANGE_COLUMNS[idActorIdx ].columnName !== 'idActor' || + changeCols[idCtrIdx ].columnId !== CHANGE_COLUMNS[idCtrIdx ].columnId || CHANGE_COLUMNS[idCtrIdx ].columnName !== 'idCtr' || + changeCols[insertIdx ].columnId !== CHANGE_COLUMNS[insertIdx ].columnId || CHANGE_COLUMNS[insertIdx ].columnName !== 'insert' || + changeCols[actionIdx ].columnId !== CHANGE_COLUMNS[actionIdx ].columnId || CHANGE_COLUMNS[actionIdx ].columnName !== 'action' || + changeCols[valLenIdx ].columnId !== CHANGE_COLUMNS[valLenIdx ].columnId || CHANGE_COLUMNS[valLenIdx ].columnName !== 'valLen' || + changeCols[valRawIdx ].columnId !== CHANGE_COLUMNS[valRawIdx ].columnId || CHANGE_COLUMNS[valRawIdx ].columnName !== 'valRaw' || + changeCols[predNumIdx ].columnId !== CHANGE_COLUMNS[predNumIdx ].columnId || CHANGE_COLUMNS[predNumIdx ].columnName !== 'predNum' || + changeCols[predActorIdx].columnId !== CHANGE_COLUMNS[predActorIdx].columnId || CHANGE_COLUMNS[predActorIdx].columnName !== 'predActor' || + changeCols[predCtrIdx ].columnId !== CHANGE_COLUMNS[predCtrIdx ].columnId || CHANGE_COLUMNS[predCtrIdx ].columnName !== 'predCtr') { + throw new RangeError('unexpected columnId') + } - BN.prototype._forceRed = function _forceRed (ctx) { - this.red = ctx; - return this; - }; + // Check if there any columns in the change that are not in the document, apart from pred* + const docCols = docState.blocks[0].columns + if (!changeCols.every(changeCol => PRED_COLUMN_IDS.includes(changeCol.columnId) || + docCols.find(docCol => docCol.columnId === changeCol.columnId))) { + let allCols = docCols.map(docCol => ({columnId: docCol.columnId})) + for (let changeCol of changeCols) { + const { columnId } = changeCol + if (!PRED_COLUMN_IDS.includes(columnId) && !docCols.find(docCol => docCol.columnId === columnId)) { + allCols.push({columnId}) + } + } + allCols.sort((a, b) => a.columnId - b.columnId) - BN.prototype.forceRed = function forceRed (ctx) { - assert(!this.red, 'Already a number in reduction context'); - return this._forceRed(ctx); - }; + for (let blockIndex = 0; blockIndex < docState.blocks.length; blockIndex++) { + let block = copyObject(docState.blocks[blockIndex]) + block.columns = makeDecoders(block.columns.map(col => ({columnId: col.columnId, buffer: col.decoder.buf})), allCols) + docState.blocks[blockIndex] = block + } + } +} - BN.prototype.redAdd = function redAdd (num) { - assert(this.red, 'redAdd works only with red numbers'); - return this.red.add(this, num); - }; +/** + * Takes a decoded change header, including an array of actorIds. Returns an object of the form + * `{actorIds, actorTable}`, where `actorIds` is an updated array of actorIds appearing in the + * document (including the new change's actorId). `actorTable` is an array of integers where + * `actorTable[i]` contains the document's actor index for the actor that has index `i` in the + * change (`i == 0` is the author of the change). + */ +function getActorTable(actorIds, change) { + if (actorIds.indexOf(change.actorIds[0]) < 0) { + if (change.seq !== 1) { + throw new RangeError(`Seq ${change.seq} is the first change for actor ${change.actorIds[0]}`) + } + // Use concat, not push, so that the original array is not mutated + actorIds = actorIds.concat([change.actorIds[0]]) + } + const actorTable = [] // translate from change's actor index to doc's actor index + for (let actorId of change.actorIds) { + const index = actorIds.indexOf(actorId) + if (index < 0) { + throw new RangeError(`actorId ${actorId} is not known to document`) + } + actorTable.push(index) + } + return {actorIds, actorTable} +} - BN.prototype.redIAdd = function redIAdd (num) { - assert(this.red, 'redIAdd works only with red numbers'); - return this.red.iadd(this, num); - }; +/** + * Finalises the patch for a change. `patches` is a map from objectIds to patch for that + * particular object, `objectIds` is the array of IDs of objects that are created or updated in the + * change, and `docState` is an object containing various bits of document state, including + * `objectMeta`, a map from objectIds to metadata about that object (such as its parent in the + * document tree). Mutates `patches` such that child objects are linked into their parent object, + * all the way to the root object. + */ +function setupPatches(patches, objectIds, docState) { + for (let objectId of objectIds) { + let meta = docState.objectMeta[objectId], childMeta = null, patchExists = false + while (true) { + const hasChildren = childMeta && Object.keys(meta.children[childMeta.parentKey]).length > 0 + if (!patches[objectId]) patches[objectId] = emptyObjectPatch(objectId, meta.type) - BN.prototype.redSub = function redSub (num) { - assert(this.red, 'redSub works only with red numbers'); - return this.red.sub(this, num); - }; + if (childMeta && hasChildren) { + if (meta.type === 'list' || meta.type === 'text') { + // In list/text objects, parentKey is an elemID. First see if it already appears in an edit + for (let edit of patches[objectId].edits) { + if (edit.opId && meta.children[childMeta.parentKey][edit.opId]) { + patchExists = true + } + } - BN.prototype.redISub = function redISub (num) { - assert(this.red, 'redISub works only with red numbers'); - return this.red.isub(this, num); - }; + // If we need to add an edit, we first have to translate the elemId into an index + if (!patchExists) { + const obj = parseOpId(objectId), elem = parseOpId(childMeta.parentKey) + const seekPos = { + objActor: obj.actorId, objCtr: obj.counter, + keyActor: elem.actorId, keyCtr: elem.counter, + objActorNum: docState.actorIds.indexOf(obj.actorId), + keyActorNum: docState.actorIds.indexOf(elem.actorId), + keyStr: null, insert: false, + objId: objectId + } + const { visibleCount } = seekToOp(docState, seekPos) - BN.prototype.redShl = function redShl (num) { - assert(this.red, 'redShl works only with red numbers'); - return this.red.shl(this, num); - }; + for (let [opId, value] of Object.entries(meta.children[childMeta.parentKey])) { + let patchValue = value + if (value.objectId) { + if (!patches[value.objectId]) patches[value.objectId] = emptyObjectPatch(value.objectId, value.type) + patchValue = patches[value.objectId] + } + const edit = {action: 'update', index: visibleCount, opId, value: patchValue} + appendEdit(patches[objectId].edits, edit) + } + } - BN.prototype.redMul = function redMul (num) { - assert(this.red, 'redMul works only with red numbers'); - this.red._verify2(this, num); - return this.red.mul(this, num); - }; + } else { + // Non-list object: parentKey is the name of the property being updated (a string) + if (!patches[objectId].props[childMeta.parentKey]) { + patches[objectId].props[childMeta.parentKey] = {} + } + let values = patches[objectId].props[childMeta.parentKey] - BN.prototype.redIMul = function redIMul (num) { - assert(this.red, 'redMul works only with red numbers'); - this.red._verify2(this, num); - return this.red.imul(this, num); - }; + for (let [opId, value] of Object.entries(meta.children[childMeta.parentKey])) { + if (values[opId]) { + patchExists = true + } else if (value.objectId) { + if (!patches[value.objectId]) patches[value.objectId] = emptyObjectPatch(value.objectId, value.type) + values[opId] = patches[value.objectId] + } else { + values[opId] = value + } + } + } + } - BN.prototype.redSqr = function redSqr () { - assert(this.red, 'redSqr works only with red numbers'); - this.red._verify1(this); - return this.red.sqr(this); - }; + if (patchExists || !meta.parentObj || (childMeta && !hasChildren)) break + childMeta = meta + objectId = meta.parentObj + meta = docState.objectMeta[objectId] + } + } + return patches +} - BN.prototype.redISqr = function redISqr () { - assert(this.red, 'redISqr works only with red numbers'); - this.red._verify1(this); - return this.red.isqr(this); - }; +/** + * Takes an array of decoded changes and applies them to a document. `docState` contains a bunch of + * fields describing the document state. This function mutates `docState` to contain the updated + * document state, and mutates `patches` to contain a patch to return to the frontend. Only the + * top-level `docState` object is mutated; all nested objects within it are treated as immutable. + * `objectIds` is mutated to contain the IDs of objects that are updated in any of the changes. + * + * The function detects duplicate changes that we've already applied by looking up each change's + * hash in `docState.changeIndexByHash`. If we deferred the hash graph computation, that structure + * will be incomplete, and we run the risk of applying the same change twice. However, we still have + * the sequence numbers for detecting duplicates. If `throwExceptions` is true, we assume that the + * set of change hashes is complete, and therefore a duplicate sequence number indicates illegal + * behaviour. If `throwExceptions` is false, and we detect a possible sequence number reuse, we + * don't throw an exception but instead enqueue all of the changes. This gives us a chance to + * recompute the hash graph and eliminate duplicates before raising an error to the application. + * + * Returns a two-element array `[applied, enqueued]`, where `applied` is an array of changes that + * have been applied to the document, and `enqueued` is an array of changes that have not yet been + * applied because they are missing a dependency. + */ +function applyChanges(patches, decodedChanges, docState, objectIds, throwExceptions) { + let heads = new Set(docState.heads), changeHashes = new Set() + let clock = copyObject(docState.clock) + let applied = [], enqueued = [] - // Square root over p - BN.prototype.redSqrt = function redSqrt () { - assert(this.red, 'redSqrt works only with red numbers'); - this.red._verify1(this); - return this.red.sqrt(this); - }; + for (let change of decodedChanges) { + // Skip any duplicate changes that we have already seen + if (docState.changeIndexByHash[change.hash] !== undefined || changeHashes.has(change.hash)) continue - BN.prototype.redInvm = function redInvm () { - assert(this.red, 'redInvm works only with red numbers'); - this.red._verify1(this); - return this.red.invm(this); - }; + const expectedSeq = (clock[change.actor] || 0) + 1 + let causallyReady = true - // Return negative clone of `this` % `red modulo` - BN.prototype.redNeg = function redNeg () { - assert(this.red, 'redNeg works only with red numbers'); - this.red._verify1(this); - return this.red.neg(this); - }; - - BN.prototype.redPow = function redPow (num) { - assert(this.red && !num.red, 'redPow(normalNum)'); - this.red._verify1(this); - return this.red.pow(this, num); - }; - - // Prime numbers with efficient reduction - var primes = { - k256: null, - p224: null, - p192: null, - p25519: null - }; - - // Pseudo-Mersenne prime - function MPrime (name, p) { - // P = 2 ^ N - K - this.name = name; - this.p = new BN(p, 16); - this.n = this.p.bitLength(); - this.k = new BN(1).iushln(this.n).isub(this.p); - - this.tmp = this._tmp(); - } - - MPrime.prototype._tmp = function _tmp () { - var tmp = new BN(null); - tmp.words = new Array(Math.ceil(this.n / 13)); - return tmp; - }; - - MPrime.prototype.ireduce = function ireduce (num) { - // Assumes that `num` is less than `P^2` - // num = HI * (2 ^ N - K) + HI * K + LO = HI * K + LO (mod P) - var r = num; - var rlen; - - do { - this.split(r, this.tmp); - r = this.imulK(r); - r = r.iadd(this.tmp); - rlen = r.bitLength(); - } while (rlen > this.n); + for (let dep of change.deps) { + const depIndex = docState.changeIndexByHash[dep] + if ((depIndex === undefined || depIndex === -1) && !changeHashes.has(dep)) { + causallyReady = false + } + } - var cmp = rlen < this.n ? -1 : r.ucmp(this.p); - if (cmp === 0) { - r.words[0] = 0; - r.length = 1; - } else if (cmp > 0) { - r.isub(this.p); - } else { - if (r.strip !== undefined) { - // r is BN v4 instance - r.strip(); + if (!causallyReady) { + enqueued.push(change) + } else if (change.seq < expectedSeq) { + if (throwExceptions) { + throw new RangeError(`Reuse of sequence number ${change.seq} for actor ${change.actor}`) } else { - // r is BN v5 instance - r._strip(); + return [[], decodedChanges] } + } else if (change.seq > expectedSeq) { + throw new RangeError(`Skipped sequence number ${expectedSeq} for actor ${change.actor}`) + } else { + clock[change.actor] = change.seq + changeHashes.add(change.hash) + for (let dep of change.deps) heads.delete(dep) + heads.add(change.hash) + applied.push(change) } + } - return r; - }; - - MPrime.prototype.split = function split (input, out) { - input.iushrn(this.n, 0, out); - }; - - MPrime.prototype.imulK = function imulK (num) { - return num.imul(this.k); - }; + if (applied.length > 0) { + let changeState = {changes: applied, changeIndex: -1, objectIds} + readNextChangeOp(docState, changeState) + while (!changeState.done) applyOps(patches, changeState, docState) - function K256 () { - MPrime.call( - this, - 'k256', - 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe fffffc2f'); + docState.heads = [...heads].sort() + docState.clock = clock } - inherits(K256, MPrime); - - K256.prototype.split = function split (input, output) { - // 256 = 9 * 26 + 22 - var mask = 0x3fffff; + return [applied, enqueued] +} - var outLen = Math.min(input.length, 9); - for (var i = 0; i < outLen; i++) { - output.words[i] = input.words[i]; - } - output.length = outLen; +/** + * Scans the operations in a document and generates a patch that can be sent to the frontend to + * instantiate the current state of the document. `objectMeta` is mutated to contain information + * about the parent and children of each object in the document. + */ +function documentPatch(docState) { + for (let col of docState.blocks[0].columns) col.decoder.reset() + let propState = {}, docOp = null, blockIndex = 0 + let patches = {_root: {objectId: '_root', type: 'map', props: {}}} + let lastObjActor = null, lastObjCtr = null, objectId = '_root', elemVisible = false, listIndex = 0 - if (input.length <= 9) { - input.words[0] = 0; - input.length = 1; - return; + while (true) { + ({ docOp, blockIndex } = readNextDocOp(docState, blockIndex)) + if (docOp === null) break + if (docOp[objActorIdx] !== lastObjActor || docOp[objCtrIdx] !== lastObjCtr) { + objectId = `${docOp[objCtrIdx]}@${docState.actorIds[docOp[objActorIdx]]}` + lastObjActor = docOp[objActorIdx] + lastObjCtr = docOp[objCtrIdx] + propState = {} + listIndex = 0 + elemVisible = false } - // Shift by 9 limbs - var prev = input.words[9]; - output.words[output.length++] = prev & mask; - - for (i = 10; i < input.length; i++) { - var next = input.words[i] | 0; - input.words[i - 10] = ((next & mask) << 4) | (prev >>> 22); - prev = next; + if (docOp[insertIdx] && elemVisible) { + elemVisible = false + listIndex++ } - prev >>>= 22; - input.words[i - 10] = prev; - if (prev === 0 && input.length > 10) { - input.length -= 10; - } else { - input.length -= 9; + if (docOp[succNumIdx] === 0) elemVisible = true + if (docOp[idCtrIdx] > docState.maxOp) docState.maxOp = docOp[idCtrIdx] + for (let i = 0; i < docOp[succNumIdx]; i++) { + if (docOp[succCtrIdx][i] > docState.maxOp) docState.maxOp = docOp[succCtrIdx][i] } - }; - K256.prototype.imulK = function imulK (num) { - // K = 0x1000003d1 = [ 0x40, 0x3d1 ] - num.words[num.length] = 0; - num.words[num.length + 1] = 0; - num.length += 2; + updatePatchProperty(patches, null, objectId, docOp, docState, propState, listIndex, docOp[succNumIdx]) + } + return patches._root +} - // bounded at: 0x40 * 0x3ffffff + 0x3d0 = 0x100000390 - var lo = 0; - for (var i = 0; i < num.length; i++) { - var w = num.words[i] | 0; - lo += w * 0x3d1; - num.words[i] = lo & 0x3ffffff; - lo = w * 0x40 + ((lo / 0x4000000) | 0); - } +/** + * Takes an encoded document whose headers have been parsed using `decodeDocumentHeader()` and reads + * from it the list of changes. Returns the document's current vector clock, i.e. an object mapping + * each actor ID (as a hex string) to the number of changes seen from that actor. Also returns an + * array of the actorIds whose most recent change has no dependents (i.e. the actors that + * contributed the current heads of the document), and an array of encoders that has been + * initialised to contain the columns of the changes list. + */ +function readDocumentChanges(doc) { + const columns = makeDecoders(doc.changesColumns, DOCUMENT_COLUMNS) + const actorD = columns[0].decoder, seqD = columns[1].decoder + const depsNumD = columns[5].decoder, depsIndexD = columns[6].decoder + if (columns[0].columnId !== DOCUMENT_COLUMNS[0].columnId || DOCUMENT_COLUMNS[0].columnName !== 'actor' || + columns[1].columnId !== DOCUMENT_COLUMNS[1].columnId || DOCUMENT_COLUMNS[1].columnName !== 'seq' || + columns[5].columnId !== DOCUMENT_COLUMNS[5].columnId || DOCUMENT_COLUMNS[5].columnName !== 'depsNum' || + columns[6].columnId !== DOCUMENT_COLUMNS[6].columnId || DOCUMENT_COLUMNS[6].columnName !== 'depsIndex') { + throw new RangeError('unexpected columnId') + } - // Fast length reduction - if (num.words[num.length - 1] === 0) { - num.length--; - if (num.words[num.length - 1] === 0) { - num.length--; - } + let numChanges = 0, clock = {}, actorNums = [], headIndexes = new Set() + while (!actorD.done) { + const actorNum = actorD.readValue(), seq = seqD.readValue(), depsNum = depsNumD.readValue() + const actorId = doc.actorIds[actorNum] + if (seq !== 1 && seq !== clock[actorId] + 1) { + throw new RangeError(`Expected seq ${clock[actorId] + 1}, got ${seq} for actor ${actorId}`) } - return num; - }; - - function P224 () { - MPrime.call( - this, - 'p224', - 'ffffffff ffffffff ffffffff ffffffff 00000000 00000000 00000001'); + actorNums.push(actorNum) + clock[actorId] = seq + headIndexes.add(numChanges) + for (let j = 0; j < depsNum; j++) headIndexes.delete(depsIndexD.readValue()) + numChanges++ } - inherits(P224, MPrime); + const headActors = [...headIndexes].map(index => doc.actorIds[actorNums[index]]).sort() - function P192 () { - MPrime.call( - this, - 'p192', - 'ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff'); - } - inherits(P192, MPrime); + for (let col of columns) col.decoder.reset() + const encoders = columns.map(col => ({columnId: col.columnId, encoder: encoderByColumnId(col.columnId)})) + copyColumns(encoders, columns, numChanges) + return {clock, headActors, encoders, numChanges} +} - function P25519 () { - // 2 ^ 255 - 19 - MPrime.call( - this, - '25519', - '7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed'); - } - inherits(P25519, MPrime); +/** + * Records the metadata about a change in the appropriate columns. + */ +function appendChange(columns, change, actorIds, changeIndexByHash) { + appendOperation(columns, DOCUMENT_COLUMNS, [ + actorIds.indexOf(change.actor), // actor + change.seq, // seq + change.maxOp, // maxOp + change.time, // time + change.message, // message + change.deps.length, // depsNum + change.deps.map(dep => changeIndexByHash[dep]), // depsIndex + change.extraBytes ? (change.extraBytes.byteLength << 4 | VALUE_TYPE.BYTES) : VALUE_TYPE.BYTES, // extraLen + change.extraBytes // extraRaw + ]) +} - P25519.prototype.imulK = function imulK (num) { - // K = 0x13 - var carry = 0; - for (var i = 0; i < num.length; i++) { - var hi = (num.words[i] | 0) * 0x13 + carry; - var lo = hi & 0x3ffffff; - hi >>>= 26; +class BackendDoc { + constructor(buffer) { + this.maxOp = 0 + this.haveHashGraph = false + this.changes = [] + this.changeIndexByHash = {} + this.dependenciesByHash = {} + this.dependentsByHash = {} + this.hashesByActor = {} + this.actorIds = [] + this.heads = [] + this.clock = {} + this.queue = [] + this.objectMeta = {_root: {parentObj: null, parentKey: null, opId: null, type: 'map', children: {}}} - num.words[i] = lo; - carry = hi; - } - if (carry !== 0) { - num.words[num.length++] = carry; - } - return num; - }; + if (buffer) { + const doc = decodeDocumentHeader(buffer) + const {clock, headActors, encoders, numChanges} = readDocumentChanges(doc) + this.binaryDoc = buffer + this.changes = new Array(numChanges) + this.actorIds = doc.actorIds + this.heads = doc.heads + this.clock = clock + this.changesEncoders = encoders + this.extraBytes = doc.extraBytes - // Exported mostly for testing purposes, use plain name instead - BN._prime = function prime (name) { - // Cached version of prime - if (primes[name]) return primes[name]; + // If there is a single head, we can unambiguously point at the actorId and sequence number of + // the head hash without having to reconstruct the hash graph + if (doc.heads.length === 1 && headActors.length === 1) { + this.hashesByActor[headActors[0]] = [] + this.hashesByActor[headActors[0]][clock[headActors[0]] - 1] = doc.heads[0] + } - var prime; - if (name === 'k256') { - prime = new K256(); - } else if (name === 'p224') { - prime = new P224(); - } else if (name === 'p192') { - prime = new P192(); - } else if (name === 'p25519') { - prime = new P25519(); - } else { - throw new Error('Unknown prime ' + name); - } - primes[name] = prime; + // The encoded document gives each change an index, and expresses dependencies in terms of + // those indexes. Initialise the translation table from hash to index. + if (doc.heads.length === doc.headsIndexes.length) { + for (let i = 0; i < doc.heads.length; i++) { + this.changeIndexByHash[doc.heads[i]] = doc.headsIndexes[i] + } + } else if (doc.heads.length === 1) { + // If there is only one head, it must be the last change + this.changeIndexByHash[doc.heads[0]] = numChanges - 1 + } else { + // We know the heads hashes, but not their indexes + for (let head of doc.heads) this.changeIndexByHash[head] = -1 + } - return prime; - }; + this.blocks = [{columns: makeDecoders(doc.opsColumns, DOC_OPS_COLUMNS)}] + updateBlockMetadata(this.blocks[0]) + if (this.blocks[0].numOps > MAX_BLOCK_SIZE) { + this.blocks = splitBlock(this.blocks[0]) + } + + let docState = {blocks: this.blocks, actorIds: this.actorIds, objectMeta: this.objectMeta, maxOp: 0} + this.initPatch = documentPatch(docState) + this.maxOp = docState.maxOp - // - // Base reduction engine - // - function Red (m) { - if (typeof m === 'string') { - var prime = BN._prime(m); - this.m = prime.p; - this.prime = prime; } else { - assert(m.gtn(1), 'modulus must be greater than 1'); - this.m = m; - this.prime = null; + this.haveHashGraph = true + this.changesEncoders = DOCUMENT_COLUMNS.map(col => ({columnId: col.columnId, encoder: encoderByColumnId(col.columnId)})) + this.blocks = [{ + columns: makeDecoders([], DOC_OPS_COLUMNS), + bloom: new Uint8Array(BLOOM_FILTER_SIZE), + numOps: 0, + lastKey: undefined, + numVisible: undefined, + lastObjectActor: undefined, + lastObjectCtr: undefined, + firstVisibleActor: undefined, + firstVisibleCtr: undefined, + lastVisibleActor: undefined, + lastVisibleCtr: undefined + }] } } - Red.prototype._verify1 = function _verify1 (a) { - assert(a.negative === 0, 'red works only with positives'); - assert(a.red, 'red works only with red numbers'); - }; - - Red.prototype._verify2 = function _verify2 (a, b) { - assert((a.negative | b.negative) === 0, 'red works only with positives'); - assert(a.red && a.red === b.red, - 'red works only with red numbers'); - }; + /** + * Makes a copy of this BackendDoc that can be independently modified. + */ + clone() { + let copy = new BackendDoc() + copy.maxOp = this.maxOp + copy.haveHashGraph = this.haveHashGraph + copy.changes = this.changes.slice() + copy.changeIndexByHash = copyObject(this.changeIndexByHash) + copy.dependenciesByHash = copyObject(this.dependenciesByHash) + copy.dependentsByHash = Object.entries(this.dependentsByHash).reduce((acc, [k, v]) => { acc[k] = v.slice(); return acc }, {}) + copy.hashesByActor = Object.entries(this.hashesByActor).reduce((acc, [k, v]) => { acc[k] = v.slice(); return acc }, {}) + copy.actorIds = this.actorIds // immutable, no copying needed + copy.heads = this.heads // immutable, no copying needed + copy.clock = this.clock // immutable, no copying needed + copy.blocks = this.blocks // immutable, no copying needed + copy.objectMeta = this.objectMeta // immutable, no copying needed + copy.queue = this.queue // immutable, no copying needed + return copy + } - Red.prototype.imod = function imod (a) { - if (this.prime) return this.prime.ireduce(a)._forceRed(this); - return a.umod(this.m)._forceRed(this); - }; + /** + * Parses the changes given as Uint8Arrays in `changeBuffers`, and applies them to the current + * document. Returns a patch to apply to the frontend. If an exception is thrown, the document + * object is not modified. + */ + applyChanges(changeBuffers, isLocal = false) { + // decoded change has the form { actor, seq, startOp, time, message, deps, actorIds, hash, columns, buffer } + let decodedChanges = changeBuffers.map(buffer => { + const decoded = decodeChangeColumns(buffer) + decoded.buffer = buffer + return decoded + }) - Red.prototype.neg = function neg (a) { - if (a.isZero()) { - return a.clone(); + let patches = {_root: {objectId: '_root', type: 'map', props: {}}} + let docState = { + maxOp: this.maxOp, + changeIndexByHash: this.changeIndexByHash, + actorIds: this.actorIds, + heads: this.heads, + clock: this.clock, + blocks: this.blocks.slice(), + objectMeta: Object.assign({}, this.objectMeta) } + let queue = (this.queue.length === 0) ? decodedChanges : decodedChanges.concat(this.queue) + let allApplied = [], objectIds = new Set() - return this.m.sub(a)._forceRed(this); - }; - - Red.prototype.add = function add (a, b) { - this._verify2(a, b); + while (true) { + const [applied, enqueued] = applyChanges(patches, queue, docState, objectIds, this.haveHashGraph) + queue = enqueued + for (let i = 0; i < applied.length; i++) { + docState.changeIndexByHash[applied[i].hash] = this.changes.length + allApplied.length + i + } + if (applied.length > 0) allApplied = allApplied.concat(applied) + if (queue.length === 0) break - var res = a.add(b); - if (res.cmp(this.m) >= 0) { - res.isub(this.m); + // If we are missing a dependency, and we haven't computed the hash graph yet, first compute + // the hashes to see if we actually have it already + if (applied.length === 0) { + if (this.haveHashGraph) break + this.computeHashGraph() + docState.changeIndexByHash = this.changeIndexByHash + } } - return res._forceRed(this); - }; - Red.prototype.iadd = function iadd (a, b) { - this._verify2(a, b); + setupPatches(patches, objectIds, docState) - var res = a.iadd(b); - if (res.cmp(this.m) >= 0) { - res.isub(this.m); + // Update the document state only if `applyChanges` does not throw an exception + for (let change of allApplied) { + this.changes.push(change.buffer) + if (!this.hashesByActor[change.actor]) this.hashesByActor[change.actor] = [] + this.hashesByActor[change.actor][change.seq - 1] = change.hash + this.changeIndexByHash[change.hash] = this.changes.length - 1 + this.dependenciesByHash[change.hash] = change.deps + this.dependentsByHash[change.hash] = [] + for (let dep of change.deps) { + if (!this.dependentsByHash[dep]) this.dependentsByHash[dep] = [] + this.dependentsByHash[dep].push(change.hash) + } + appendChange(this.changesEncoders, change, docState.actorIds, this.changeIndexByHash) } - return res; - }; - Red.prototype.sub = function sub (a, b) { - this._verify2(a, b); + this.maxOp = docState.maxOp + this.actorIds = docState.actorIds + this.heads = docState.heads + this.clock = docState.clock + this.blocks = docState.blocks + this.objectMeta = docState.objectMeta + this.queue = queue + this.binaryDoc = null + this.initPatch = null - var res = a.sub(b); - if (res.cmpn(0) < 0) { - res.iadd(this.m); + let patch = { + maxOp: this.maxOp, clock: this.clock, deps: this.heads, + pendingChanges: this.queue.length, diffs: patches._root } - return res._forceRed(this); - }; - - Red.prototype.isub = function isub (a, b) { - this._verify2(a, b); - - var res = a.isub(b); - if (res.cmpn(0) < 0) { - res.iadd(this.m); + if (isLocal && decodedChanges.length === 1) { + patch.actor = decodedChanges[0].actor + patch.seq = decodedChanges[0].seq } - return res; - }; + return patch + } - Red.prototype.shl = function shl (a, num) { - this._verify1(a); - return this.imod(a.ushln(num)); - }; + /** + * Reconstructs the full change history of a document, and initialises the variables that allow us + * to traverse the hash graph of changes and their dependencies. When a compressed document is + * loaded we defer the computation of this hash graph to make loading faster, but if the hash + * graph is later needed (e.g. for the sync protocol), this function fills it in. + */ + computeHashGraph() { + const binaryDoc = this.save() + this.haveHashGraph = true + this.changes = [] + this.changeIndexByHash = {} + this.dependenciesByHash = {} + this.dependentsByHash = {} + this.hashesByActor = {} + this.clock = {} - Red.prototype.imul = function imul (a, b) { - this._verify2(a, b); - return this.imod(a.imul(b)); - }; - - Red.prototype.mul = function mul (a, b) { - this._verify2(a, b); - return this.imod(a.mul(b)); - }; - - Red.prototype.isqr = function isqr (a) { - return this.imul(a, a.clone()); - }; + for (let change of decodeChanges([binaryDoc])) { + const binaryChange = encodeChange(change) // TODO: avoid decoding and re-encoding again + this.changes.push(binaryChange) + this.changeIndexByHash[change.hash] = this.changes.length - 1 + this.dependenciesByHash[change.hash] = change.deps + this.dependentsByHash[change.hash] = [] + for (let dep of change.deps) this.dependentsByHash[dep].push(change.hash) + if (change.seq === 1) this.hashesByActor[change.actor] = [] + this.hashesByActor[change.actor].push(change.hash) + const expectedSeq = (this.clock[change.actor] || 0) + 1 + if (change.seq !== expectedSeq) { + throw new RangeError(`Expected seq ${expectedSeq}, got seq ${change.seq} from actor ${change.actor}`) + } + this.clock[change.actor] = change.seq + } + } - Red.prototype.sqr = function sqr (a) { - return this.mul(a, a); - }; + /** + * Returns all the changes that need to be sent to another replica. `haveDeps` is a list of change + * hashes (as hex strings) of the heads that the other replica has. The changes in `haveDeps` and + * any of their transitive dependencies will not be returned; any changes later than or concurrent + * to the hashes in `haveDeps` will be returned. If `haveDeps` is an empty array, all changes are + * returned. Throws an exception if any of the given hashes are not known to this replica. + */ + getChanges(haveDeps) { + if (!this.haveHashGraph) this.computeHashGraph() - Red.prototype.sqrt = function sqrt (a) { - if (a.isZero()) return a.clone(); + // If the other replica has nothing, return all changes in history order + if (haveDeps.length === 0) { + return this.changes.slice() + } - var mod3 = this.m.andln(3); - assert(mod3 % 2 === 1); + // Fast path for the common case where all new changes depend only on haveDeps + let stack = [], seenHashes = {}, toReturn = [] + for (let hash of haveDeps) { + seenHashes[hash] = true + const successors = this.dependentsByHash[hash] + if (!successors) throw new RangeError(`hash not found: ${hash}`) + stack.push(...successors) + } - // Fast case - if (mod3 === 3) { - var pow = this.m.add(new BN(1)).iushrn(2); - return this.pow(a, pow); + // Depth-first traversal of the hash graph to find all changes that depend on `haveDeps` + while (stack.length > 0) { + const hash = stack.pop() + seenHashes[hash] = true + toReturn.push(hash) + if (!this.dependenciesByHash[hash].every(dep => seenHashes[dep])) { + // If a change depends on a hash we have not seen, abort the traversal and fall back to the + // slower algorithm. This will sometimes abort even if all new changes depend on `haveDeps`, + // because our depth-first traversal is not necessarily a topological sort of the graph. + break + } + stack.push(...this.dependentsByHash[hash]) } - // Tonelli-Shanks algorithm (Totally unoptimized and slow) - // - // Find Q and S, that Q * 2 ^ S = (P - 1) - var q = this.m.subn(1); - var s = 0; - while (!q.isZero() && q.andln(1) === 0) { - s++; - q.iushrn(1); + // If the traversal above has encountered all the heads, and was not aborted early due to + // a missing dependency, then the set of changes it has found is complete, so we can return it + if (stack.length === 0 && this.heads.every(head => seenHashes[head])) { + return toReturn.map(hash => this.changes[this.changeIndexByHash[hash]]) } - assert(!q.isZero()); - var one = new BN(1).toRed(this); - var nOne = one.redNeg(); + // If we haven't encountered all of the heads, we have to search harder. This will happen if + // changes were added that are concurrent to `haveDeps` + stack = haveDeps.slice() + seenHashes = {} + while (stack.length > 0) { + const hash = stack.pop() + if (!seenHashes[hash]) { + const deps = this.dependenciesByHash[hash] + if (!deps) throw new RangeError(`hash not found: ${hash}`) + stack.push(...deps) + seenHashes[hash] = true + } + } - // Find quadratic non-residue - // NOTE: Max is such because of generalized Riemann hypothesis. - var lpow = this.m.subn(1).iushrn(1); - var z = this.m.bitLength(); - z = new BN(2 * z * z).toRed(this); + return this.changes.filter(change => !seenHashes[decodeChangeMeta(change, true).hash]) + } - while (this.pow(z, lpow).cmp(nOne) !== 0) { - z.redIAdd(nOne); - } + /** + * Returns all changes that are present in this BackendDoc, but not present in the `other` + * BackendDoc. + */ + getChangesAdded(other) { + if (!this.haveHashGraph) this.computeHashGraph() - var c = this.pow(z, q); - var r = this.pow(a, q.addn(1).iushrn(1)); - var t = this.pow(a, q); - var m = s; - while (t.cmp(one) !== 0) { - var tmp = t; - for (var i = 0; tmp.cmp(one) !== 0; i++) { - tmp = tmp.redSqr(); + // Depth-first traversal from the heads through the dependency graph, + // until we reach a change that is already present in opSet1 + let stack = this.heads.slice(), seenHashes = {}, toReturn = [] + while (stack.length > 0) { + const hash = stack.pop() + if (!seenHashes[hash] && other.changeIndexByHash[hash] === undefined) { + seenHashes[hash] = true + toReturn.push(hash) + stack.push(...this.dependenciesByHash[hash]) } - assert(i < m); - var b = this.pow(c, new BN(1).iushln(m - i - 1)); - - r = r.redMul(b); - c = b.redSqr(); - t = t.redMul(c); - m = i; } - return r; - }; + // Return those changes in the reverse of the order in which the depth-first search + // found them. This is not necessarily a topological sort, but should usually be close. + return toReturn.reverse().map(hash => this.changes[this.changeIndexByHash[hash]]) + } - Red.prototype.invm = function invm (a) { - var inv = a._invmp(this.m); - if (inv.negative !== 0) { - inv.negative = 0; - return this.imod(inv).redNeg(); - } else { - return this.imod(inv); - } - }; + getChangeByHash(hash) { + if (!this.haveHashGraph) this.computeHashGraph() + return this.changes[this.changeIndexByHash[hash]] + } - Red.prototype.pow = function pow (a, num) { - if (num.isZero()) return new BN(1).toRed(this); - if (num.cmpn(1) === 0) return a.clone(); + /** + * Returns the hashes of any missing dependencies, i.e. where we have tried to apply a change that + * has a dependency on a change we have not seen. + * + * If the argument `heads` is given (an array of hexadecimal strings representing hashes as + * returned by `getHeads()`), this function also ensures that all of those hashes resolve to + * either a change that has been applied to the document, or that has been enqueued for later + * application once missing dependencies have arrived. Any missing heads hashes are included in + * the returned array. + */ + getMissingDeps(heads = []) { + if (!this.haveHashGraph) this.computeHashGraph() - var windowSize = 4; - var wnd = new Array(1 << windowSize); - wnd[0] = new BN(1).toRed(this); - wnd[1] = a; - for (var i = 2; i < wnd.length; i++) { - wnd[i] = this.mul(wnd[i - 1], a); + let allDeps = new Set(heads), inQueue = new Set() + for (let change of this.queue) { + inQueue.add(change.hash) + for (let dep of change.deps) allDeps.add(dep) } - var res = wnd[0]; - var current = 0; - var currentLen = 0; - var start = num.bitLength() % 26; - if (start === 0) { - start = 26; + let missing = [] + for (let hash of allDeps) { + if (this.changeIndexByHash[hash] === undefined && !inQueue.has(hash)) missing.push(hash) } + return missing.sort() + } - for (i = num.length - 1; i >= 0; i--) { - var word = num.words[i]; - for (var j = start - 1; j >= 0; j--) { - var bit = (word >> j) & 1; - if (res !== wnd[0]) { - res = this.sqr(res); - } + /** + * Serialises the current document state into a single byte array. + */ + save() { + if (this.binaryDoc) return this.binaryDoc - if (bit === 0 && current === 0) { - currentLen = 0; - continue; - } + // Getting the byte array for the changes columns finalises their encoders, after which we can + // no longer append values to them. We therefore copy their data over to fresh encoders. + const newEncoders = this.changesEncoders.map(col => ({columnId: col.columnId, encoder: encoderByColumnId(col.columnId)})) + const decoders = this.changesEncoders.map(col => { + const decoder = decoderByColumnId(col.columnId, col.encoder.buffer) + return {columnId: col.columnId, decoder} + }) + copyColumns(newEncoders, decoders, this.changes.length) - current <<= 1; - current |= bit; - currentLen++; - if (currentLen !== windowSize && (i !== 0 || j !== 0)) continue; + this.binaryDoc = encodeDocumentHeader({ + changesColumns: this.changesEncoders, + opsColumns: concatBlocks(this.blocks), + actorIds: this.actorIds, // TODO: sort actorIds (requires transforming all actorId columns in opsColumns) + heads: this.heads, + headsIndexes: this.heads.map(hash => this.changeIndexByHash[hash]), + extraBytes: this.extraBytes + }) + this.changesEncoders = newEncoders + return this.binaryDoc + } - res = this.mul(res, wnd[current]); - currentLen = 0; - current = 0; - } - start = 26; + /** + * Returns a patch from which we can initialise the current state of the backend. + */ + getPatch() { + const objectMeta = {_root: {parentObj: null, parentKey: null, opId: null, type: 'map', children: {}}} + const docState = {blocks: this.blocks, actorIds: this.actorIds, objectMeta, maxOp: 0} + const diffs = this.initPatch ? this.initPatch : documentPatch(docState) + return { + maxOp: this.maxOp, clock: this.clock, deps: this.heads, + pendingChanges: this.queue.length, diffs } + } +} - return res; - }; - - Red.prototype.convertTo = function convertTo (num) { - var r = num.umod(this.m); - - return r === num ? r.clone() : r; - }; +module.exports = { MAX_BLOCK_SIZE, BackendDoc, bloomFilterContains } - Red.prototype.convertFrom = function convertFrom (num) { - var res = num.clone(); - res.red = null; - return res; - }; +},{"../src/common":82,"./columnar":49}],53:[function(require,module,exports){ +/** + * Implementation of the data synchronisation protocol that brings a local and a remote document + * into the same state. This is typically used when two nodes have been disconnected for some time, + * and need to exchange any changes that happened while they were disconnected. The two nodes that + * are syncing could be client and server, or server and client, or two peers with symmetric roles. + * + * The protocol is based on this paper: Martin Kleppmann and Heidi Howard. Byzantine Eventual + * Consistency and the Fundamental Limits of Peer-to-Peer Databases. https://arxiv.org/abs/2012.00472 + * + * The protocol assumes that every time a node successfully syncs with another node, it remembers + * the current heads (as returned by `Backend.getHeads()`) after the last sync with that node. The + * next time we try to sync with the same node, we start from the assumption that the other node's + * document version is no older than the outcome of the last sync, so we only need to exchange any + * changes that are more recent than the last sync. This assumption may not be true if the other + * node did not correctly persist its state (perhaps it crashed before writing the result of the + * last sync to disk), and we fall back to sending the entire document in this case. + */ - // - // Montgomery method engine - // +const Backend = require('./backend') +const { hexStringToBytes, bytesToHexString, Encoder, Decoder } = require('./encoding') +const { decodeChangeMeta } = require('./columnar') +const { copyObject } = require('../src/common') - BN.mont = function mont (num) { - return new Mont(num); - }; +const HASH_SIZE = 32 // 256 bits = 32 bytes +const MESSAGE_TYPE_SYNC = 0x42 // first byte of a sync message, for identification +const PEER_STATE_TYPE = 0x43 // first byte of an encoded peer state, for identification - function Mont (m) { - Red.call(this, m); +// These constants correspond to a 1% false positive rate. The values can be changed without +// breaking compatibility of the network protocol, since the parameters used for a particular +// Bloom filter are encoded in the wire format. +const BITS_PER_ENTRY = 10, NUM_PROBES = 7 - this.shift = this.m.bitLength(); - if (this.shift % 26 !== 0) { - this.shift += 26 - (this.shift % 26); +/** + * A Bloom filter implementation that can be serialised to a byte array for transmission + * over a network. The entries that are added are assumed to already be SHA-256 hashes, + * so this implementation does not perform its own hashing. + */ +class BloomFilter { + constructor (arg) { + if (Array.isArray(arg)) { + // arg is an array of SHA256 hashes in hexadecimal encoding + this.numEntries = arg.length + this.numBitsPerEntry = BITS_PER_ENTRY + this.numProbes = NUM_PROBES + this.bits = new Uint8Array(Math.ceil(this.numEntries * this.numBitsPerEntry / 8)) + for (let hash of arg) this.addHash(hash) + } else if (arg instanceof Uint8Array) { + if (arg.byteLength === 0) { + this.numEntries = 0 + this.numBitsPerEntry = 0 + this.numProbes = 0 + this.bits = arg + } else { + const decoder = new Decoder(arg) + this.numEntries = decoder.readUint32() + this.numBitsPerEntry = decoder.readUint32() + this.numProbes = decoder.readUint32() + this.bits = decoder.readRawBytes(Math.ceil(this.numEntries * this.numBitsPerEntry / 8)) + } + } else { + throw new TypeError('invalid argument') } - - this.r = new BN(1).iushln(this.shift); - this.r2 = this.imod(this.r.sqr()); - this.rinv = this.r._invmp(this.m); - - this.minv = this.rinv.mul(this.r).isubn(1).div(this.m); - this.minv = this.minv.umod(this.r); - this.minv = this.r.sub(this.minv); } - inherits(Mont, Red); - - Mont.prototype.convertTo = function convertTo (num) { - return this.imod(num.ushln(this.shift)); - }; - Mont.prototype.convertFrom = function convertFrom (num) { - var r = this.imod(num.mul(this.rinv)); - r.red = null; - return r; - }; + /** + * Returns the Bloom filter state, encoded as a byte array. + */ + get bytes() { + if (this.numEntries === 0) return new Uint8Array(0) + const encoder = new Encoder() + encoder.appendUint32(this.numEntries) + encoder.appendUint32(this.numBitsPerEntry) + encoder.appendUint32(this.numProbes) + encoder.appendRawBytes(this.bits) + return encoder.buffer + } - Mont.prototype.imul = function imul (a, b) { - if (a.isZero() || b.isZero()) { - a.words[0] = 0; - a.length = 1; - return a; + /** + * Given a SHA-256 hash (as hex string), returns an array of probe indexes indicating which bits + * in the Bloom filter need to be tested or set for this particular entry. We do this by + * interpreting the first 12 bytes of the hash as three little-endian 32-bit unsigned integers, + * and then using triple hashing to compute the probe indexes. The algorithm comes from: + * + * Peter C. Dillinger and Panagiotis Manolios. Bloom Filters in Probabilistic Verification. + * 5th International Conference on Formal Methods in Computer-Aided Design (FMCAD), November 2004. + * http://www.ccis.northeastern.edu/home/pete/pub/bloom-filters-verification.pdf + */ + getProbes(hash) { + const hashBytes = hexStringToBytes(hash), modulo = 8 * this.bits.byteLength + if (hashBytes.byteLength !== 32) throw new RangeError(`Not a 256-bit hash: ${hash}`) + // on the next three lines, the right shift means interpret value as unsigned + let x = ((hashBytes[0] | hashBytes[1] << 8 | hashBytes[2] << 16 | hashBytes[3] << 24) >>> 0) % modulo + let y = ((hashBytes[4] | hashBytes[5] << 8 | hashBytes[6] << 16 | hashBytes[7] << 24) >>> 0) % modulo + let z = ((hashBytes[8] | hashBytes[9] << 8 | hashBytes[10] << 16 | hashBytes[11] << 24) >>> 0) % modulo + const probes = [x] + for (let i = 1; i < this.numProbes; i++) { + x = (x + y) % modulo + y = (y + z) % modulo + probes.push(x) } + return probes + } - var t = a.imul(b); - var c = t.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m); - var u = t.isub(c).iushrn(this.shift); - var res = u; - - if (u.cmp(this.m) >= 0) { - res = u.isub(this.m); - } else if (u.cmpn(0) < 0) { - res = u.iadd(this.m); + /** + * Sets the Bloom filter bits corresponding to a given SHA-256 hash (given as hex string). + */ + addHash(hash) { + for (let probe of this.getProbes(hash)) { + this.bits[probe >>> 3] |= 1 << (probe & 7) } + } - return res._forceRed(this); - }; - - Mont.prototype.mul = function mul (a, b) { - if (a.isZero() || b.isZero()) return new BN(0)._forceRed(this); - - var t = a.mul(b); - var c = t.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m); - var u = t.isub(c).iushrn(this.shift); - var res = u; - if (u.cmp(this.m) >= 0) { - res = u.isub(this.m); - } else if (u.cmpn(0) < 0) { - res = u.iadd(this.m); + /** + * Tests whether a given SHA-256 hash (given as hex string) is contained in the Bloom filter. + */ + containsHash(hash) { + if (this.numEntries === 0) return false + for (let probe of this.getProbes(hash)) { + if ((this.bits[probe >>> 3] & (1 << (probe & 7))) === 0) { + return false + } } - - return res._forceRed(this); - }; - - Mont.prototype.invm = function invm (a) { - // (AR)^-1 * R^2 = (A^-1 * R^-1) * R^2 = A^-1 * R - var res = this.imod(a._invmp(this.m).mul(this.r2)); - return res._forceRed(this); - }; -})(typeof module === 'undefined' || module, this); - -},{"buffer":93}],48:[function(require,module,exports){ -const { encodeChange } = require('./columnar') -const { BackendDoc } = require('./new') -const { backendState } = require('./util') + return true + } +} /** - * Returns an empty node state. + * Encodes a sorted array of SHA-256 hashes (as hexadecimal strings) into a byte array. */ -function init() { - return {state: new BackendDoc(), heads: []} -} - -function clone(backend) { - return {state: backendState(backend).clone(), heads: backend.heads} -} - -function free(backend) { - backend.state = null - backend.frozen = true +function encodeHashes(encoder, hashes) { + if (!Array.isArray(hashes)) throw new TypeError('hashes must be an array') + encoder.appendUint32(hashes.length) + for (let i = 0; i < hashes.length; i++) { + if (i > 0 && hashes[i - 1] >= hashes[i]) throw new RangeError('hashes must be sorted') + const bytes = hexStringToBytes(hashes[i]) + if (bytes.byteLength !== HASH_SIZE) throw new TypeError('heads hashes must be 256 bits') + encoder.appendRawBytes(bytes) + } } /** - * Applies a list of `changes` from remote nodes to the node state `backend`. - * Returns a two-element array `[state, patch]` where `state` is the updated - * node state, and `patch` describes the modifications that need to be made - * to the document objects to reflect these changes. + * Decodes a byte array in the format returned by encodeHashes(), and returns its content as an + * array of hex strings. */ -function applyChanges(backend, changes) { - const state = backendState(backend) - const patch = state.applyChanges(changes) - backend.frozen = true - return [{state, heads: state.heads}, patch] +function decodeHashes(decoder) { + let length = decoder.readUint32(), hashes = [] + for (let i = 0; i < length; i++) { + hashes.push(bytesToHexString(decoder.readRawBytes(HASH_SIZE))) + } + return hashes } -function hashByActor(state, actorId, index) { - if (state.hashesByActor[actorId] && state.hashesByActor[actorId][index]) { - return state.hashesByActor[actorId][index] +/** + * Takes a sync message of the form `{heads, need, have, changes}` and encodes it as a byte array for + * transmission. + */ +function encodeSyncMessage(message) { + const encoder = new Encoder() + encoder.appendByte(MESSAGE_TYPE_SYNC) + encodeHashes(encoder, message.heads) + encodeHashes(encoder, message.need) + encoder.appendUint32(message.have.length) + for (let have of message.have) { + encodeHashes(encoder, have.lastSync) + encoder.appendPrefixedBytes(have.bloom) } - if (!state.haveHashGraph) { - state.computeHashGraph() - if (state.hashesByActor[actorId] && state.hashesByActor[actorId][index]) { - return state.hashesByActor[actorId][index] - } + encoder.appendUint32(message.changes.length) + for (let change of message.changes) { + encoder.appendPrefixedBytes(change) } - throw new RangeError(`Unknown change: actorId = ${actorId}, seq = ${index + 1}`) + return encoder.buffer } /** - * Takes a single change request `request` made by the local user, and applies - * it to the node state `backend`. Returns a three-element array `[backend, patch, binaryChange]` - * where `backend` is the updated node state,`patch` confirms the - * modifications to the document objects, and `binaryChange` is a binary-encoded form of - * the change submitted. + * Takes a binary-encoded sync message and decodes it into the form `{heads, need, have, changes}`. */ -function applyLocalChange(backend, change) { - const state = backendState(backend) - if (change.seq <= state.clock[change.actor] || 0) { - throw new RangeError('Change request has already been applied') +function decodeSyncMessage(bytes) { + const decoder = new Decoder(bytes) + const messageType = decoder.readByte() + if (messageType !== MESSAGE_TYPE_SYNC) { + throw new RangeError(`Unexpected message type: ${messageType}`) } - - // Add the local actor's last change hash to deps. We do this because when frontend - // and backend are on separate threads, the frontend may fire off several local - // changes in sequence before getting a response from the backend; since the binary - // encoding and hashing is done by the backend, the frontend does not know the hash - // of its own last change in this case. Rather than handle this situation as a - // special case, we say that the frontend includes only specifies other actors' - // deps in changes it generates, and the dependency from the local actor's last - // change is always added here in the backend. - // - // Strictly speaking, we should check whether the local actor's last change is - // indirectly reachable through a different actor's change; in that case, it is not - // necessary to add this dependency. However, it doesn't do any harm either (only - // using a few extra bytes of storage). - if (change.seq > 1) { - const lastHash = hashByActor(state, change.actor, change.seq - 2) - if (!lastHash) { - throw new RangeError(`Cannot find hash of localChange before seq=${change.seq}`) - } - let deps = {[lastHash]: true} - for (let hash of change.deps) deps[hash] = true - change.deps = Object.keys(deps).sort() + const heads = decodeHashes(decoder) + const need = decodeHashes(decoder) + const haveCount = decoder.readUint32() + let message = {heads, need, have: [], changes: []} + for (let i = 0; i < haveCount; i++) { + const lastSync = decodeHashes(decoder) + const bloom = decoder.readPrefixedBytes(decoder) + message.have.push({lastSync, bloom}) } - - const binaryChange = encodeChange(change) - const patch = state.applyChanges([binaryChange], true) - backend.frozen = true - - // On the patch we send out, omit the last local change hash - const lastHash = hashByActor(state, change.actor, change.seq - 1) - patch.deps = patch.deps.filter(head => head !== lastHash) - return [{state, heads: state.heads}, patch, binaryChange] + const changeCount = decoder.readUint32() + for (let i = 0; i < changeCount; i++) { + const change = decoder.readPrefixedBytes() + message.changes.push(change) + } + // Ignore any trailing bytes -- they can be used for extensions by future versions of the protocol + return message } /** - * Returns the state of the document serialised to an Uint8Array. + * Takes a SyncState and encodes as a byte array those parts of the state that should persist across + * an application restart or disconnect and reconnect. The ephemeral parts of the state that should + * be cleared on reconnect are not encoded. */ -function save(backend) { - return backendState(backend).save() +function encodeSyncState(syncState) { + const encoder = new Encoder() + encoder.appendByte(PEER_STATE_TYPE) + encodeHashes(encoder, syncState.sharedHeads) + return encoder.buffer } /** - * Loads the document and/or changes contained in an Uint8Array, and returns a - * backend initialised with this state. + * Takes a persisted peer state as encoded by `encodeSyncState` and decodes it into a SyncState + * object. The parts of the peer state that were not encoded are initialised with default values. */ -function load(data) { - const state = new BackendDoc(data) - return {state, heads: state.heads} +function decodeSyncState(bytes) { + const decoder = new Decoder(bytes) + const recordType = decoder.readByte() + if (recordType !== PEER_STATE_TYPE) { + throw new RangeError(`Unexpected record type: ${recordType}`) + } + const sharedHeads = decodeHashes(decoder) + return Object.assign(initSyncState(), { sharedHeads }) } /** - * Applies a list of `changes` to the node state `backend`, and returns the updated - * state with those changes incorporated. Unlike `applyChanges()`, this function - * does not produce a patch describing the incremental modifications, making it - * a little faster when loading a document from disk. When all the changes have - * been loaded, you can use `getPatch()` to construct the latest document state. + * Constructs a Bloom filter containing all changes that are not one of the hashes in + * `lastSync` or its transitive dependencies. In other words, the filter contains those + * changes that have been applied since the version identified by `lastSync`. Returns + * an object of the form `{lastSync, bloom}` as required for the `have` field of a sync + * message. */ -function loadChanges(backend, changes) { - const state = backendState(backend) - state.applyChanges(changes) - backend.frozen = true - return {state, heads: state.heads} +function makeBloomFilter(backend, lastSync) { + const newChanges = Backend.getChanges(backend, lastSync) + const hashes = newChanges.map(change => decodeChangeMeta(change, true).hash) + return {lastSync, bloom: new BloomFilter(hashes).bytes} } /** - * Returns a patch that, when applied to an empty document, constructs the - * document tree in the state described by the node state `backend`. + * Call this function when a sync message is received from another node. The `message` argument + * needs to already have been decoded using `decodeSyncMessage()`. This function determines the + * changes that we need to send to the other node in response. Returns an array of changes (as + * byte arrays). */ -function getPatch(backend) { - return backendState(backend).getPatch() -} +function getChangesToSend(backend, have, need) { + if (have.length === 0) { + return need.map(hash => Backend.getChangeByHash(backend, hash)).filter(change => change !== undefined) + } -/** - * Returns an array of hashes of the current "head" changes (i.e. those changes - * that no other change depends on). - */ -function getHeads(backend) { - return backend.heads -} + let lastSyncHashes = {}, bloomFilters = [] + for (let h of have) { + for (let hash of h.lastSync) lastSyncHashes[hash] = true + bloomFilters.push(new BloomFilter(h.bloom)) + } -/** - * Returns the full history of changes that have been applied to a document. - */ -function getAllChanges(backend) { - return getChanges(backend, []) -} + // Get all changes that were added since the last sync + const changes = Backend.getChanges(backend, Object.keys(lastSyncHashes)) + .map(change => decodeChangeMeta(change, true)) -/** - * Returns all changes that are newer than or concurrent to the changes - * identified by the hashes in `haveDeps`. If `haveDeps` is an empty array, all - * changes are returned. Throws an exception if any of the given hashes is unknown. - */ -function getChanges(backend, haveDeps) { - if (!Array.isArray(haveDeps)) { - throw new TypeError('Pass an array of hashes to Backend.getChanges()') + let changeHashes = {}, dependents = {}, hashesToSend = {} + for (let change of changes) { + changeHashes[change.hash] = true + + // For each change, make a list of changes that depend on it + for (let dep of change.deps) { + if (!dependents[dep]) dependents[dep] = [] + dependents[dep].push(change.hash) + } + + // Exclude any change hashes contained in one or more Bloom filters + if (bloomFilters.every(bloom => !bloom.containsHash(change.hash))) { + hashesToSend[change.hash] = true + } } - return backendState(backend).getChanges(haveDeps) + + // Include any changes that depend on a Bloom-negative change + let stack = Object.keys(hashesToSend) + while (stack.length > 0) { + const hash = stack.pop() + if (dependents[hash]) { + for (let dep of dependents[hash]) { + if (!hashesToSend[dep]) { + hashesToSend[dep] = true + stack.push(dep) + } + } + } + } + + // Include any explicitly requested changes + let changesToSend = [] + for (let hash of need) { + hashesToSend[hash] = true + if (!changeHashes[hash]) { // Change is not among those returned by getMissingChanges()? + const change = Backend.getChangeByHash(backend, hash) + if (change) changesToSend.push(change) + } + } + + // Return changes in the order they were returned by getMissingChanges() + for (let change of changes) { + if (hashesToSend[change.hash]) changesToSend.push(change.change) + } + return changesToSend } -/** - * Returns all changes that are present in `backend2` but not in `backend1`. - * Intended for use in situations where the two backends are for different actors. - * To get the changes added between an older and a newer document state of the same - * actor, use `getChanges()` instead. `getChangesAdded()` throws an exception if - * one of the backend states is frozen (i.e. if it is not the latest state of that - * backend instance; this distinction matters when the backend is mutable). - */ -function getChangesAdded(backend1, backend2) { - return backendState(backend2).getChangesAdded(backendState(backend1)) +function initSyncState() { + return { + sharedHeads: [], + lastSentHeads: [], + theirHeads: null, + theirNeed: null, + theirHave: null, + sentHashes: {}, + } } -/** - * If the backend has applied a change with the given `hash` (given as a - * hexadecimal string), returns that change (as a byte array). Returns undefined - * if no change with that hash has been applied. A change with missing - * dependencies does not count as having been applied. - */ -function getChangeByHash(backend, hash) { - return backendState(backend).getChangeByHash(hash) +function compareArrays(a, b) { + return (a.length === b.length) && a.every((v, i) => v === b[i]) } /** - * Returns the hashes of any missing dependencies, i.e. where we have applied a - * change that has a dependency on a change we have not seen. - * - * If the argument `heads` is given (an array of hexadecimal strings representing - * hashes as returned by `getHeads()`), this function also ensures that all of - * those hashes resolve to either a change that has been applied to the document, - * or that has been enqueued for later application once missing dependencies have - * arrived. Any missing heads hashes are included in the returned array. + * Given a backend and what we believe to be the state of our peer, generate a message which tells + * them about we have and includes any changes we believe they need */ -function getMissingDeps(backend, heads = []) { - return backendState(backend).getMissingDeps(heads) -} +function generateSyncMessage(backend, syncState) { + if (!backend) { + throw new Error("generateSyncMessage called with no Automerge document") + } + if (!syncState) { + throw new Error("generateSyncMessage requires a syncState, which can be created with initSyncState()") + } -module.exports = { - init, clone, free, applyChanges, applyLocalChange, save, load, loadChanges, getPatch, - getHeads, getAllChanges, getChanges, getChangesAdded, getChangeByHash, getMissingDeps -} + let { sharedHeads, lastSentHeads, theirHeads, theirNeed, theirHave, sentHashes } = syncState + const ourHeads = Backend.getHeads(backend) -},{"./columnar":49,"./new":52,"./util":54}],49:[function(require,module,exports){ -const pako = require('pako') -const { copyObject, parseOpId, equalBytes } = require('../src/common') -const { - utf8ToString, hexStringToBytes, bytesToHexString, - Encoder, Decoder, RLEEncoder, RLEDecoder, DeltaEncoder, DeltaDecoder, BooleanEncoder, BooleanDecoder -} = require('./encoding') + // Hashes to explicitly request from the remote peer: any missing dependencies of unapplied + // changes, and any of the remote peer's heads that we don't know about + const ourNeed = Backend.getMissingDeps(backend, theirHeads || []) -// Maybe we should be using the platform's built-in hash implementation? -// Node has the crypto module: https://nodejs.org/api/crypto.html and browsers have -// https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/digest -// However, the WebCrypto API is asynchronous (returns promises), which would -// force all our APIs to become asynchronous as well, which would be annoying. -// -// I think on balance, it's safe enough to use a random library off npm: -// - We only need one hash function (not a full suite of crypto algorithms); -// - SHA256 is quite simple and has fairly few opportunities for subtle bugs -// (compared to asymmetric cryptography anyway); -// - It does not need a secure source of random bits and does not need to be -// constant-time; -// - I have reviewed the source code and it seems pretty reasonable. -const { Hash } = require('fast-sha256') + // There are two reasons why ourNeed may be nonempty: 1. we might be missing dependencies due to + // Bloom filter false positives; 2. we might be missing heads that the other peer mentioned + // because they (intentionally) only sent us a subset of changes. In case 1, we leave the `have` + // field of the message empty because we just want to fill in the missing dependencies for now. + // In case 2, or if ourNeed is empty, we send a Bloom filter to request any unsent changes. + let ourHave = [] + if (!theirHeads || ourNeed.every(hash => theirHeads.includes(hash))) { + ourHave = [makeBloomFilter(backend, sharedHeads)] + } -// These bytes don't mean anything, they were generated randomly -const MAGIC_BYTES = new Uint8Array([0x85, 0x6f, 0x4a, 0x83]) + // Fall back to a full re-sync if the sender's last sync state includes hashes + // that we don't know. This could happen if we crashed after the last sync and + // failed to persist changes that the other node already sent us. + if (theirHave && theirHave.length > 0) { + const lastSync = theirHave[0].lastSync + if (!lastSync.every(hash => Backend.getChangeByHash(backend, hash))) { + // we need to queue them to send us a fresh sync message, the one they sent is uninteligible so we don't know what they need + const resetMsg = {heads: ourHeads, need: [], have: [{ lastSync: [], bloom: new Uint8Array(0) }], changes: []} + return [syncState, encodeSyncMessage(resetMsg)] + } + } -const CHUNK_TYPE_DOCUMENT = 0 -const CHUNK_TYPE_CHANGE = 1 -const CHUNK_TYPE_DEFLATE = 2 // like CHUNK_TYPE_CHANGE but with DEFLATE compression + // XXX: we should limit ourselves to only sending a subset of all the messages, probably limited by a total message size + // these changes should ideally be RLE encoded but we haven't implemented that yet. + let changesToSend = Array.isArray(theirHave) && Array.isArray(theirNeed) ? getChangesToSend(backend, theirHave, theirNeed) : [] -// Minimum number of bytes in a value before we enable DEFLATE compression (there is no point -// compressing very short values since compression may actually make them bigger) -const DEFLATE_MIN_SIZE = 256 + // If the heads are equal, we're in sync and don't need to do anything further + const headsUnchanged = Array.isArray(lastSentHeads) && compareArrays(ourHeads, lastSentHeads) + const headsEqual = Array.isArray(theirHeads) && compareArrays(ourHeads, theirHeads) + if (headsUnchanged && headsEqual && changesToSend.length === 0) { + // no need to send a sync message if we know we're synced! + return [syncState, null] + } -// The least-significant 3 bits of a columnId indicate its datatype -const COLUMN_TYPE = { - GROUP_CARD: 0, ACTOR_ID: 1, INT_RLE: 2, INT_DELTA: 3, BOOLEAN: 4, - STRING_RLE: 5, VALUE_LEN: 6, VALUE_RAW: 7 -} + // TODO: this recomputes the SHA-256 hash of each change; we should restructure this to avoid the + // unnecessary recomputation + changesToSend = changesToSend.filter(change => !sentHashes[decodeChangeMeta(change, true).hash]) -// The 4th-least-significant bit of a columnId is set if the column is DEFLATE-compressed -const COLUMN_TYPE_DEFLATE = 8 + // Regular response to a sync message: send any changes that the other node + // doesn't have. We leave the "have" field empty because the previous message + // generated by `syncStart` already indicated what changes we have. + const syncMessage = {heads: ourHeads, have: ourHave, need: ourNeed, changes: changesToSend} + if (changesToSend.length > 0) { + sentHashes = copyObject(sentHashes) + for (const change of changesToSend) { + sentHashes[decodeChangeMeta(change, true).hash] = true + } + } -// In the values in a column of type VALUE_LEN, the bottom four bits indicate the type of the value, -// one of the following types in VALUE_TYPE. The higher bits indicate the length of the value in the -// associated VALUE_RAW column (in bytes). -const VALUE_TYPE = { - NULL: 0, FALSE: 1, TRUE: 2, LEB128_UINT: 3, LEB128_INT: 4, IEEE754: 5, - UTF8: 6, BYTES: 7, COUNTER: 8, TIMESTAMP: 9, MIN_UNKNOWN: 10, MAX_UNKNOWN: 15 + syncState = Object.assign({}, syncState, {lastSentHeads: ourHeads, sentHashes}) + return [syncState, encodeSyncMessage(syncMessage)] } -// make* actions must be at even-numbered indexes in this list -const ACTIONS = ['makeMap', 'set', 'makeList', 'del', 'makeText', 'inc', 'makeTable', 'link'] - -const OBJECT_TYPE = {makeMap: 'map', makeList: 'list', makeText: 'text', makeTable: 'table'} - -const COMMON_COLUMNS = [ - {columnName: 'objActor', columnId: 0 << 4 | COLUMN_TYPE.ACTOR_ID}, - {columnName: 'objCtr', columnId: 0 << 4 | COLUMN_TYPE.INT_RLE}, - {columnName: 'keyActor', columnId: 1 << 4 | COLUMN_TYPE.ACTOR_ID}, - {columnName: 'keyCtr', columnId: 1 << 4 | COLUMN_TYPE.INT_DELTA}, - {columnName: 'keyStr', columnId: 1 << 4 | COLUMN_TYPE.STRING_RLE}, - {columnName: 'idActor', columnId: 2 << 4 | COLUMN_TYPE.ACTOR_ID}, - {columnName: 'idCtr', columnId: 2 << 4 | COLUMN_TYPE.INT_DELTA}, - {columnName: 'insert', columnId: 3 << 4 | COLUMN_TYPE.BOOLEAN}, - {columnName: 'action', columnId: 4 << 4 | COLUMN_TYPE.INT_RLE}, - {columnName: 'valLen', columnId: 5 << 4 | COLUMN_TYPE.VALUE_LEN}, - {columnName: 'valRaw', columnId: 5 << 4 | COLUMN_TYPE.VALUE_RAW}, - {columnName: 'chldActor', columnId: 6 << 4 | COLUMN_TYPE.ACTOR_ID}, - {columnName: 'chldCtr', columnId: 6 << 4 | COLUMN_TYPE.INT_DELTA} -] - -const CHANGE_COLUMNS = COMMON_COLUMNS.concat([ - {columnName: 'predNum', columnId: 7 << 4 | COLUMN_TYPE.GROUP_CARD}, - {columnName: 'predActor', columnId: 7 << 4 | COLUMN_TYPE.ACTOR_ID}, - {columnName: 'predCtr', columnId: 7 << 4 | COLUMN_TYPE.INT_DELTA} -]) - -const DOC_OPS_COLUMNS = COMMON_COLUMNS.concat([ - {columnName: 'succNum', columnId: 8 << 4 | COLUMN_TYPE.GROUP_CARD}, - {columnName: 'succActor', columnId: 8 << 4 | COLUMN_TYPE.ACTOR_ID}, - {columnName: 'succCtr', columnId: 8 << 4 | COLUMN_TYPE.INT_DELTA} -]) - -const DOCUMENT_COLUMNS = [ - {columnName: 'actor', columnId: 0 << 4 | COLUMN_TYPE.ACTOR_ID}, - {columnName: 'seq', columnId: 0 << 4 | COLUMN_TYPE.INT_DELTA}, - {columnName: 'maxOp', columnId: 1 << 4 | COLUMN_TYPE.INT_DELTA}, - {columnName: 'time', columnId: 2 << 4 | COLUMN_TYPE.INT_DELTA}, - {columnName: 'message', columnId: 3 << 4 | COLUMN_TYPE.STRING_RLE}, - {columnName: 'depsNum', columnId: 4 << 4 | COLUMN_TYPE.GROUP_CARD}, - {columnName: 'depsIndex', columnId: 4 << 4 | COLUMN_TYPE.INT_DELTA}, - {columnName: 'extraLen', columnId: 5 << 4 | COLUMN_TYPE.VALUE_LEN}, - {columnName: 'extraRaw', columnId: 5 << 4 | COLUMN_TYPE.VALUE_RAW} -] - /** - * Maps an opId of the form {counter: 12345, actorId: 'someActorId'} to the form - * {counter: 12345, actorNum: 123, actorId: 'someActorId'}, where the actorNum - * is the index into the `actorIds` array. + * Computes the heads that we share with a peer after we have just received some changes from that + * peer and applied them. This may not be sufficient to bring our heads in sync with the other + * peer's heads, since they may have only sent us a subset of their outstanding changes. + * + * `myOldHeads` are the local heads before the most recent changes were applied, `myNewHeads` are + * the local heads after those changes were applied, and `ourOldSharedHeads` is the previous set of + * shared heads. Applying the changes will have replaced some heads with others, but some heads may + * have remained unchanged (because they are for branches on which no changes have been added). Any + * such unchanged heads remain in the sharedHeads. Any sharedHeads that were replaced by applying + * changes are also replaced as sharedHeads. This is safe because if we received some changes from + * another peer, that means that peer had those changes, and therefore we now both know about them. */ -function actorIdToActorNum(opId, actorIds) { - if (!opId || !opId.actorId) return opId - const counter = opId.counter - const actorNum = actorIds.indexOf(opId.actorId) - if (actorNum < 0) throw new RangeError('missing actorId') // should not happen - return {counter, actorNum, actorId: opId.actorId} +function advanceHeads(myOldHeads, myNewHeads, ourOldSharedHeads) { + const newHeads = myNewHeads.filter((head) => !myOldHeads.includes(head)) + const commonHeads = ourOldSharedHeads.filter((head) => myNewHeads.includes(head)) + const advancedHeads = [...new Set([...newHeads, ...commonHeads])].sort() + return advancedHeads } -/** - * Comparison function to pass to Array.sort(), which compares two opIds in the - * form produced by `actorIdToActorNum` so that they are sorted in increasing - * Lamport timestamp order (sorted first by counter, then by actorId). - */ -function compareParsedOpIds(id1, id2) { - if (id1.counter < id2.counter) return -1 - if (id1.counter > id2.counter) return +1 - if (id1.actorId < id2.actorId) return -1 - if (id1.actorId > id2.actorId) return +1 - return 0 -} /** - * Takes `changes`, an array of changes (represented as JS objects). Returns an - * object `{changes, actorIds}`, where `changes` is a copy of the argument in - * which all string opIds have been replaced with `{counter, actorNum}` objects, - * and where `actorIds` is a lexicographically sorted array of actor IDs occurring - * in any of the operations. `actorNum` is an index into that array of actorIds. - * If `single` is true, the actorId of the author of the change is moved to the - * beginning of the array of actorIds, so that `actorNum` is zero when referencing - * the author of the change itself. This special-casing is omitted if `single` is - * false. + * Given a backend, a message message and the state of our peer, apply any changes, update what + * we believe about the peer, and (if there were applied changes) produce a patch for the frontend */ -function parseAllOpIds(changes, single) { - const actors = {}, newChanges = [] - for (let change of changes) { - change = copyObject(change) - actors[change.actor] = true - change.ops = expandMultiOps(change.ops, change.startOp, change.actor) - change.ops = change.ops.map(op => { - op = copyObject(op) - if (op.obj !== '_root') op.obj = parseOpId(op.obj) - if (op.elemId && op.elemId !== '_head') op.elemId = parseOpId(op.elemId) - if (op.child) op.child = parseOpId(op.child) - if (op.pred) op.pred = op.pred.map(parseOpId) - if (op.obj.actorId) actors[op.obj.actorId] = true - if (op.elemId && op.elemId.actorId) actors[op.elemId.actorId] = true - if (op.child && op.child.actorId) actors[op.child.actorId] = true - for (let pred of op.pred) actors[pred.actorId] = true - return op - }) - newChanges.push(change) +function receiveSyncMessage(backend, oldSyncState, binaryMessage) { + if (!backend) { + throw new Error("generateSyncMessage called with no Automerge document") + } + if (!oldSyncState) { + throw new Error("generateSyncMessage requires a syncState, which can be created with initSyncState()") } - let actorIds = Object.keys(actors).sort() - if (single) { - actorIds = [changes[0].actor].concat(actorIds.filter(actor => actor !== changes[0].actor)) + let { sharedHeads, lastSentHeads, sentHashes } = oldSyncState, patch = null + const message = decodeSyncMessage(binaryMessage) + const beforeHeads = Backend.getHeads(backend) + + // If we received changes, we try to apply them to the document. There may still be missing + // dependencies due to Bloom filter false positives, in which case the backend will enqueue the + // changes without applying them. The set of changes may also be incomplete if the sender decided + // to break a large set of changes into chunks. + if (message.changes.length > 0) { + [backend, patch] = Backend.applyChanges(backend, message.changes) + sharedHeads = advanceHeads(beforeHeads, Backend.getHeads(backend), sharedHeads) } - for (let change of newChanges) { - change.actorNum = actorIds.indexOf(change.actor) - for (let i = 0; i < change.ops.length; i++) { - let op = change.ops[i] - op.id = {counter: change.startOp + i, actorNum: change.actorNum, actorId: change.actor} - op.obj = actorIdToActorNum(op.obj, actorIds) - op.elemId = actorIdToActorNum(op.elemId, actorIds) - op.child = actorIdToActorNum(op.child, actorIds) - op.pred = op.pred.map(pred => actorIdToActorNum(pred, actorIds)) - } + + // If heads are equal, indicate we don't need to send a response message + if (message.changes.length === 0 && compareArrays(message.heads, beforeHeads)) { + lastSentHeads = message.heads } - return {changes: newChanges, actorIds} -} -/** - * Encodes the `obj` property of operation `op` into the two columns - * `objActor` and `objCtr`. - */ -function encodeObjectId(op, columns) { - if (op.obj === '_root') { - columns.objActor.appendValue(null) - columns.objCtr.appendValue(null) - } else if (op.obj.actorNum >= 0 && op.obj.counter > 0) { - columns.objActor.appendValue(op.obj.actorNum) - columns.objCtr.appendValue(op.obj.counter) + // If all of the remote heads are known to us, that means either our heads are equal, or we are + // ahead of the remote peer. In this case, take the remote heads to be our shared heads. + const knownHeads = message.heads.filter(head => Backend.getChangeByHash(backend, head)) + if (knownHeads.length === message.heads.length) { + sharedHeads = message.heads + // If the remote peer has lost all its data, reset our state to perform a full resync + if (message.heads.length === 0) { + lastSentHeads = [] + sentHashes = [] + } } else { - throw new RangeError(`Unexpected objectId reference: ${JSON.stringify(op.obj)}`) + // If some remote heads are unknown to us, we add all the remote heads we know to + // sharedHeads, but don't remove anything from sharedHeads. This might cause sharedHeads to + // contain some redundant hashes (where one hash is actually a transitive dependency of + // another), but this will be cleared up as soon as we know all the remote heads. + sharedHeads = [...new Set(knownHeads.concat(sharedHeads))].sort() } -} -/** - * Encodes the `key` and `elemId` properties of operation `op` into the three - * columns `keyActor`, `keyCtr`, and `keyStr`. - */ -function encodeOperationKey(op, columns) { - if (op.key) { - columns.keyActor.appendValue(null) - columns.keyCtr.appendValue(null) - columns.keyStr.appendValue(op.key) - } else if (op.elemId === '_head' && op.insert) { - columns.keyActor.appendValue(null) - columns.keyCtr.appendValue(0) - columns.keyStr.appendValue(null) - } else if (op.elemId && op.elemId.actorNum >= 0 && op.elemId.counter > 0) { - columns.keyActor.appendValue(op.elemId.actorNum) - columns.keyCtr.appendValue(op.elemId.counter) - columns.keyStr.appendValue(null) - } else { - throw new RangeError(`Unexpected operation key: ${JSON.stringify(op)}`) + const syncState = { + sharedHeads, // what we have in common to generate an efficient bloom filter + lastSentHeads, + theirHave: message.have, // the information we need to calculate the changes they need + theirHeads: message.heads, + theirNeed: message.need, + sentHashes } + return [backend, syncState, patch] } -/** - * Encodes the `action` property of operation `op` into the `action` column. - */ -function encodeOperationAction(op, columns) { - const actionCode = ACTIONS.indexOf(op.action) - if (actionCode >= 0) { - columns.action.appendValue(actionCode) - } else if (typeof op.action === 'number') { - columns.action.appendValue(op.action) - } else { - throw new RangeError(`Unexpected operation action: ${op.action}`) +module.exports = { + receiveSyncMessage, generateSyncMessage, + encodeSyncMessage, decodeSyncMessage, + initSyncState, encodeSyncState, decodeSyncState, + BloomFilter // BloomFilter is a private API, exported only for testing purposes +} + +},{"../src/common":82,"./backend":48,"./columnar":49,"./encoding":50}],54:[function(require,module,exports){ +function backendState(backend) { + if (backend.frozen) { + throw new Error( + 'Attempting to use an outdated Automerge document that has already been updated. ' + + 'Please use the latest document state, or call Automerge.clone() if you really ' + + 'need to use this old document state.' + ) } + return backend.state +} + +module.exports = { + backendState } +},{}],55:[function(require,module,exports){ +const { isObject, copyObject, parseOpId } = require('../src/common') +const { OBJECT_ID, CONFLICTS, ELEM_IDS } = require('./constants') +const { instantiateText } = require('./text') +const { instantiateTable } = require('./table') +const { Counter } = require('./counter') + /** - * Given the datatype for a number, determine the typeTag and the value to encode - * otherwise guess + * Reconstructs the value from the patch object `patch`. */ -function getNumberTypeAndValue(op) { - switch (op.datatype) { - case "counter": - return [ VALUE_TYPE.COUNTER, op.value ] - case "timestamp": - return [ VALUE_TYPE.TIMESTAMP, op.value ] - case "uint": - return [ VALUE_TYPE.LEB128_UINT, op.value ] - case "int": - return [ VALUE_TYPE.LEB128_INT, op.value ] - case "float64": { - const buf64 = new ArrayBuffer(8), view64 = new DataView(buf64) - view64.setFloat64(0, op.value, true) - return [ VALUE_TYPE.IEEE754, new Uint8Array(buf64) ] +function getValue(patch, object, updated) { + if (patch.objectId) { + // If the objectId of the existing object does not match the objectId in the patch, + // that means the patch is replacing the object with a new one made from scratch + if (object && object[OBJECT_ID] !== patch.objectId) { + object = undefined } - default: - // increment operators get resolved here ... - if (Number.isInteger(op.value) && op.value <= Number.MAX_SAFE_INTEGER && op.value >= Number.MIN_SAFE_INTEGER) { - return [ VALUE_TYPE.LEB128_INT, op.value ] - } else { - const buf64 = new ArrayBuffer(8), view64 = new DataView(buf64) - view64.setFloat64(0, op.value, true) - return [ VALUE_TYPE.IEEE754, new Uint8Array(buf64) ] - } + return interpretPatch(patch, object, updated) + } else if (patch.datatype === 'timestamp') { + // Timestamp: value is milliseconds since 1970 epoch + return new Date(patch.value) + } else if (patch.datatype === 'counter') { + return new Counter(patch.value) + } else { + // Primitive value (int, uint, float64, string, boolean, or null) + return patch.value } } /** - * Encodes the `value` property of operation `op` into the two columns - * `valLen` and `valRaw`. + * Compares two strings, interpreted as Lamport timestamps of the form + * 'counter@actorId'. Returns 1 if ts1 is greater, or -1 if ts2 is greater. */ -function encodeValue(op, columns) { - if ((op.action !== 'set' && op.action !== 'inc') || op.value === null) { - columns.valLen.appendValue(VALUE_TYPE.NULL) - } else if (op.value === false) { - columns.valLen.appendValue(VALUE_TYPE.FALSE) - } else if (op.value === true) { - columns.valLen.appendValue(VALUE_TYPE.TRUE) - } else if (typeof op.value === 'string') { - const numBytes = columns.valRaw.appendRawString(op.value) - columns.valLen.appendValue(numBytes << 4 | VALUE_TYPE.UTF8) - } else if (ArrayBuffer.isView(op.value)) { - const numBytes = columns.valRaw.appendRawBytes(new Uint8Array(op.value.buffer)) - columns.valLen.appendValue(numBytes << 4 | VALUE_TYPE.BYTES) - } else if (typeof op.value === 'number') { - let [typeTag, value] = getNumberTypeAndValue(op) - let numBytes - if (typeTag === VALUE_TYPE.LEB128_UINT) { - numBytes = columns.valRaw.appendUint53(value) - } else if (typeTag === VALUE_TYPE.IEEE754) { - numBytes = columns.valRaw.appendRawBytes(value) - } else { - numBytes = columns.valRaw.appendInt53(value) - } - columns.valLen.appendValue(numBytes << 4 | typeTag) - } else if (typeof op.datatype === 'number' && op.datatype >= VALUE_TYPE.MIN_UNKNOWN && - op.datatype <= VALUE_TYPE.MAX_UNKNOWN && op.value instanceof Uint8Array) { - const numBytes = columns.valRaw.appendRawBytes(op.value) - columns.valLen.appendValue(numBytes << 4 | op.datatype) - } else if (op.datatype) { - throw new RangeError(`Unknown datatype ${op.datatype} for value ${op.value}`) - } else { - throw new RangeError(`Unsupported value in operation: ${op.value}`) - } +function lamportCompare(ts1, ts2) { + const regex = /^(\d+)@(.*)$/ + const time1 = regex.test(ts1) ? parseOpId(ts1) : {counter: 0, actorId: ts1} + const time2 = regex.test(ts2) ? parseOpId(ts2) : {counter: 0, actorId: ts2} + if (time1.counter < time2.counter) return -1 + if (time1.counter > time2.counter) return 1 + if (time1.actorId < time2.actorId) return -1 + if (time1.actorId > time2.actorId) return 1 + return 0 } /** - * Given `sizeTag` (an unsigned integer read from a VALUE_LEN column) and `bytes` (a Uint8Array - * read from a VALUE_RAW column, with length `sizeTag >> 4`), this function returns an object of the - * form `{value: value, datatype: datatypeTag}` where `value` is a JavaScript primitive datatype - * corresponding to the value, and `datatypeTag` is a datatype annotation such as 'counter'. + * `props` is an object of the form: + * `{key1: {opId1: {...}, opId2: {...}}, key2: {opId3: {...}}}` + * where the outer object is a mapping from property names to inner objects, + * and the inner objects are a mapping from operation ID to sub-patch. + * This function interprets that structure and updates the objects `object` and + * `conflicts` to reflect it. For each key, the greatest opId (by Lamport TS + * order) is chosen as the default resolution; that op's value is assigned + * to `object[key]`. Moreover, all the opIds and values are packed into a + * conflicts object of the form `{opId1: value1, opId2: value2}` and assigned + * to `conflicts[key]`. If there is no conflict, the conflicts object contains + * just a single opId-value mapping. */ -function decodeValue(sizeTag, bytes) { - if (sizeTag === VALUE_TYPE.NULL) { - return {value: null} - } else if (sizeTag === VALUE_TYPE.FALSE) { - return {value: false} - } else if (sizeTag === VALUE_TYPE.TRUE) { - return {value: true} - } else if (sizeTag % 16 === VALUE_TYPE.UTF8) { - return {value: utf8ToString(bytes)} - } else { - if (sizeTag % 16 === VALUE_TYPE.LEB128_UINT) { - return {value: new Decoder(bytes).readUint53(), datatype: "uint"} - } else if (sizeTag % 16 === VALUE_TYPE.LEB128_INT) { - return {value: new Decoder(bytes).readInt53(), datatype: "int"} - } else if (sizeTag % 16 === VALUE_TYPE.IEEE754) { - const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength) - if (bytes.byteLength === 8) { - return {value: view.getFloat64(0, true), datatype: "float64"} +function applyProperties(props, object, conflicts, updated) { + if (!props) return + + for (let key of Object.keys(props)) { + const values = {}, opIds = Object.keys(props[key]).sort(lamportCompare).reverse() + for (let opId of opIds) { + const subpatch = props[key][opId] + if (conflicts[key] && conflicts[key][opId]) { + values[opId] = getValue(subpatch, conflicts[key][opId], updated) } else { - throw new RangeError(`Invalid length for floating point number: ${bytes.byteLength}`) + values[opId] = getValue(subpatch, undefined, updated) } - } else if (sizeTag % 16 === VALUE_TYPE.COUNTER) { - return {value: new Decoder(bytes).readInt53(), datatype: 'counter'} - } else if (sizeTag % 16 === VALUE_TYPE.TIMESTAMP) { - return {value: new Decoder(bytes).readInt53(), datatype: 'timestamp'} + } + + if (opIds.length === 0) { + delete object[key] + delete conflicts[key] } else { - return {value: bytes, datatype: sizeTag % 16} + object[key] = values[opIds[0]] + conflicts[key] = values } } } /** - * Reads one value from the column `columns[colIndex]` and interprets it based - * on the column type. `actorIds` is a list of actors that appear in the change; - * `actorIds[0]` is the actorId of the change's author. Mutates the `result` - * object with the value, and returns the number of columns processed (this is 2 - * in the case of a pair of VALUE_LEN and VALUE_RAW columns, which are processed - * in one go). + * Creates a writable copy of an immutable map object. If `originalObject` + * is undefined, creates an empty object with ID `objectId`. */ -function decodeValueColumns(columns, colIndex, actorIds, result) { - const { columnId, columnName, decoder } = columns[colIndex] - if (columnId % 8 === COLUMN_TYPE.VALUE_LEN && colIndex + 1 < columns.length && - columns[colIndex + 1].columnId === columnId + 1) { - const sizeTag = decoder.readValue() - const rawValue = columns[colIndex + 1].decoder.readRawBytes(sizeTag >> 4) - const { value, datatype } = decodeValue(sizeTag, rawValue) - result[columnName] = value - if (datatype) result[columnName + '_datatype'] = datatype - return 2 - } else if (columnId % 8 === COLUMN_TYPE.ACTOR_ID) { - const actorNum = decoder.readValue() - if (actorNum === null) { - result[columnName] = null - } else { - if (!actorIds[actorNum]) throw new RangeError(`No actor index ${actorNum}`) - result[columnName] = actorIds[actorNum] - } - } else { - result[columnName] = decoder.readValue() - } - return 1 +function cloneMapObject(originalObject, objectId) { + const object = copyObject(originalObject) + const conflicts = copyObject(originalObject ? originalObject[CONFLICTS] : undefined) + Object.defineProperty(object, OBJECT_ID, {value: objectId}) + Object.defineProperty(object, CONFLICTS, {value: conflicts}) + return object } /** - * Encodes an array of operations in a set of columns. The operations need to - * be parsed with `parseAllOpIds()` beforehand. If `forDocument` is true, we use - * the column structure of a whole document, otherwise we use the column - * structure for an individual change. Returns an array of - * `{columnId, columnName, encoder}` objects. + * Updates the map object `obj` according to the modifications described in + * `patch`, or creates a new object if `obj` is undefined. Mutates `updated` + * to map the objectId to the new object, and returns the new object. */ -function encodeOps(ops, forDocument) { - const columns = { - objActor : new RLEEncoder('uint'), - objCtr : new RLEEncoder('uint'), - keyActor : new RLEEncoder('uint'), - keyCtr : new DeltaEncoder(), - keyStr : new RLEEncoder('utf8'), - insert : new BooleanEncoder(), - action : new RLEEncoder('uint'), - valLen : new RLEEncoder('uint'), - valRaw : new Encoder(), - chldActor : new RLEEncoder('uint'), - chldCtr : new DeltaEncoder() +function updateMapObject(patch, obj, updated) { + const objectId = patch.objectId + if (!updated[objectId]) { + updated[objectId] = cloneMapObject(obj, objectId) } - if (forDocument) { - columns.idActor = new RLEEncoder('uint') - columns.idCtr = new DeltaEncoder() - columns.succNum = new RLEEncoder('uint') - columns.succActor = new RLEEncoder('uint') - columns.succCtr = new DeltaEncoder() - } else { - columns.predNum = new RLEEncoder('uint') - columns.predCtr = new DeltaEncoder() - columns.predActor = new RLEEncoder('uint') + const object = updated[objectId] + applyProperties(patch.props, object, object[CONFLICTS], updated) + return object +} + +/** + * Updates the table object `obj` according to the modifications described in + * `patch`, or creates a new object if `obj` is undefined. Mutates `updated` + * to map the objectId to the new object, and returns the new object. + */ +function updateTableObject(patch, obj, updated) { + const objectId = patch.objectId + if (!updated[objectId]) { + updated[objectId] = obj ? obj._clone() : instantiateTable(objectId) } - for (let op of ops) { - encodeObjectId(op, columns) - encodeOperationKey(op, columns) - columns.insert.appendValue(!!op.insert) - encodeOperationAction(op, columns) - encodeValue(op, columns) + const object = updated[objectId] - if (op.child && op.child.counter) { - columns.chldActor.appendValue(op.child.actorNum) - columns.chldCtr.appendValue(op.child.counter) - } else { - columns.chldActor.appendValue(null) - columns.chldCtr.appendValue(null) - } + for (let key of Object.keys(patch.props || {})) { + const opIds = Object.keys(patch.props[key]) - if (forDocument) { - columns.idActor.appendValue(op.id.actorNum) - columns.idCtr.appendValue(op.id.counter) - columns.succNum.appendValue(op.succ.length) - op.succ.sort(compareParsedOpIds) - for (let i = 0; i < op.succ.length; i++) { - columns.succActor.appendValue(op.succ[i].actorNum) - columns.succCtr.appendValue(op.succ[i].counter) - } + if (opIds.length === 0) { + object.remove(key) + } else if (opIds.length === 1) { + const subpatch = patch.props[key][opIds[0]] + object._set(key, getValue(subpatch, object.byId(key), updated), opIds[0]) } else { - columns.predNum.appendValue(op.pred.length) - op.pred.sort(compareParsedOpIds) - for (let i = 0; i < op.pred.length; i++) { - columns.predActor.appendValue(op.pred[i].actorNum) - columns.predCtr.appendValue(op.pred[i].counter) - } + throw new RangeError('Conflicts are not supported on properties of a table') } } + return object +} - let columnList = [] - for (let {columnName, columnId} of forDocument ? DOC_OPS_COLUMNS : CHANGE_COLUMNS) { - if (columns[columnName]) columnList.push({columnId, columnName, encoder: columns[columnName]}) - } - return columnList.sort((a, b) => a.columnId - b.columnId) +/** + * Creates a writable copy of an immutable list object. If `originalList` is + * undefined, creates an empty list with ID `objectId`. + */ +function cloneListObject(originalList, objectId) { + const list = originalList ? originalList.slice() : [] // slice() makes a shallow clone + const conflicts = (originalList && originalList[CONFLICTS]) ? originalList[CONFLICTS].slice() : [] + const elemIds = (originalList && originalList[ELEM_IDS]) ? originalList[ELEM_IDS].slice() : [] + Object.defineProperty(list, OBJECT_ID, {value: objectId}) + Object.defineProperty(list, CONFLICTS, {value: conflicts}) + Object.defineProperty(list, ELEM_IDS, {value: elemIds}) + return list } -function validDatatype(value, datatype) { - if (datatype === undefined) { - return (typeof value === 'string' || typeof value === 'boolean' || value === null) - } else { - return typeof value === 'number' +/** + * Updates the list object `obj` according to the modifications described in + * `patch`, or creates a new object if `obj` is undefined. Mutates `updated` + * to map the objectId to the new object, and returns the new object. + */ +function updateListObject(patch, obj, updated) { + const objectId = patch.objectId + if (!updated[objectId]) { + updated[objectId] = cloneListObject(obj, objectId) } -} -function expandMultiOps(ops, startOp, actor) { - let opNum = startOp - let expandedOps = [] - for (const op of ops) { - if (op.action === 'set' && op.values && op.insert) { - if (op.pred.length !== 0) throw new RangeError('multi-insert pred must be empty') - let lastElemId = op.elemId - const datatype = op.datatype - for (const value of op.values) { - if (!validDatatype(value, datatype)) throw new RangeError(`Decode failed: bad value/datatype association (${value},${datatype})`) - expandedOps.push({action: 'set', obj: op.obj, elemId: lastElemId, datatype, value, pred: [], insert: true}) - lastElemId = `${opNum}@${actor}` - opNum += 1 + const list = updated[objectId], conflicts = list[CONFLICTS], elemIds = list[ELEM_IDS] + for (let i = 0; i < patch.edits.length; i++) { + const edit = patch.edits[i] + + if (edit.action === 'insert' || edit.action === 'update') { + const oldValue = conflicts[edit.index] && conflicts[edit.index][edit.opId] + let lastValue = getValue(edit.value, oldValue, updated) + let values = {[edit.opId]: lastValue} + + // Successive updates for the same index are an indication of a conflict on that list element. + // Edits are sorted in increasing order by Lamport timestamp, so the last value (with the + // greatest timestamp) is the default resolution of the conflict. + while (i < patch.edits.length - 1 && patch.edits[i + 1].index === edit.index && + patch.edits[i + 1].action === 'update') { + i++ + const conflict = patch.edits[i] + const oldValue2 = conflicts[conflict.index] && conflicts[conflict.index][conflict.opId] + lastValue = getValue(conflict.value, oldValue2, updated) + values[conflict.opId] = lastValue } - } else if (op.action === 'del' && op.multiOp > 1) { - if (op.pred.length !== 1) throw new RangeError('multiOp deletion must have exactly one pred') - const startElemId = parseOpId(op.elemId), startPred = parseOpId(op.pred[0]) - for (let i = 0; i < op.multiOp; i++) { - const elemId = `${startElemId.counter + i}@${startElemId.actorId}` - const pred = [`${startPred.counter + i}@${startPred.actorId}`] - expandedOps.push({action: 'del', obj: op.obj, elemId, pred}) - opNum += 1 + + if (edit.action === 'insert') { + list.splice(edit.index, 0, lastValue) + conflicts.splice(edit.index, 0, values) + elemIds.splice(edit.index, 0, edit.elemId) + } else { + list[edit.index] = lastValue + conflicts[edit.index] = values } - } else { - expandedOps.push(op) - opNum += 1 + + } else if (edit.action === 'multi-insert') { + const startElemId = parseOpId(edit.elemId), newElems = [], newValues = [], newConflicts = [] + const datatype = edit.datatype + edit.values.forEach((value, index) => { + const elemId = `${startElemId.counter + index}@${startElemId.actorId}` + value = getValue({ value, datatype }, undefined, updated) + newValues.push(value) + newConflicts.push({[elemId]: {value, datatype, type: 'value'}}) + newElems.push(elemId) + }) + list.splice(edit.index, 0, ...newValues) + conflicts.splice(edit.index, 0, ...newConflicts) + elemIds.splice(edit.index, 0, ...newElems) + + } else if (edit.action === 'remove') { + list.splice(edit.index, edit.count) + conflicts.splice(edit.index, edit.count) + elemIds.splice(edit.index, edit.count) } } - return expandedOps + return list } /** - * Takes a change as decoded by `decodeColumns`, and changes it into the form - * expected by the rest of the backend. If `forDocument` is true, we use the op - * structure of a whole document, otherwise we use the op structure for an - * individual change. + * Updates the text object `obj` according to the modifications described in + * `patch`, or creates a new object if `obj` is undefined. Mutates `updated` + * to map the objectId to the new object, and returns the new object. */ -function decodeOps(ops, forDocument) { - const newOps = [] - for (let op of ops) { - const obj = (op.objCtr === null) ? '_root' : `${op.objCtr}@${op.objActor}` - const elemId = op.keyStr ? undefined : (op.keyCtr === 0 ? '_head' : `${op.keyCtr}@${op.keyActor}`) - const action = ACTIONS[op.action] || op.action - const newOp = elemId ? {obj, elemId, action} : {obj, key: op.keyStr, action} - newOp.insert = !!op.insert - if (ACTIONS[op.action] === 'set' || ACTIONS[op.action] === 'inc') { - newOp.value = op.valLen - if (op.valLen_datatype) newOp.datatype = op.valLen_datatype - } - if (!!op.chldCtr !== !!op.chldActor) { - throw new RangeError(`Mismatched child columns: ${op.chldCtr} and ${op.chldActor}`) - } - if (op.chldCtr !== null) newOp.child = `${op.chldCtr}@${op.chldActor}` - if (forDocument) { - newOp.id = `${op.idCtr}@${op.idActor}` - newOp.succ = op.succNum.map(succ => `${succ.succCtr}@${succ.succActor}`) - checkSortedOpIds(op.succNum.map(succ => ({counter: succ.succCtr, actorId: succ.succActor}))) - } else { - newOp.pred = op.predNum.map(pred => `${pred.predCtr}@${pred.predActor}`) - checkSortedOpIds(op.predNum.map(pred => ({counter: pred.predCtr, actorId: pred.predActor}))) +function updateTextObject(patch, obj, updated) { + const objectId = patch.objectId + let elems + if (updated[objectId]) { + elems = updated[objectId].elems + } else if (obj) { + elems = obj.elems.slice() + } else { + elems = [] + } + + for (const edit of patch.edits) { + if (edit.action === 'insert') { + const value = getValue(edit.value, undefined, updated) + const elem = {elemId: edit.elemId, pred: [edit.opId], value} + elems.splice(edit.index, 0, elem) + + } else if (edit.action === 'multi-insert') { + const startElemId = parseOpId(edit.elemId) + const datatype = edit.datatype + const newElems = edit.values.map((value, index) => { + value = getValue({ datatype, value }, undefined, updated) + const elemId = `${startElemId.counter + index}@${startElemId.actorId}` + return {elemId, pred: [elemId], value} + }) + elems.splice(edit.index, 0, ...newElems) + + } else if (edit.action === 'update') { + const elemId = elems[edit.index].elemId + const value = getValue(edit.value, elems[edit.index].value, updated) + elems[edit.index] = {elemId, pred: [edit.opId], value} + + } else if (edit.action === 'remove') { + elems.splice(edit.index, edit.count) } - newOps.push(newOp) } - return newOps + + updated[objectId] = instantiateText(objectId, elems) + return updated[objectId] } /** - * Throws an exception if the opIds in the given array are not in sorted order. + * Applies the patch object `patch` to the read-only document object `obj`. + * Clones a writable copy of `obj` and places it in `updated` (indexed by + * objectId), if that has not already been done. Returns the updated object. */ -function checkSortedOpIds(opIds) { - let last = null - for (let opId of opIds) { - if (last && compareParsedOpIds(last, opId) !== -1) { - throw new RangeError('operation IDs are not in ascending order') - } - last = opId +function interpretPatch(patch, obj, updated) { + // Return original object if it already exists and isn't being modified + if (isObject(obj) && (!patch.props || Object.keys(patch.props).length === 0) && + (!patch.edits || patch.edits.length === 0) && !updated[patch.objectId]) { + return obj } -} -function encoderByColumnId(columnId) { - if ((columnId & 7) === COLUMN_TYPE.INT_DELTA) { - return new DeltaEncoder() - } else if ((columnId & 7) === COLUMN_TYPE.BOOLEAN) { - return new BooleanEncoder() - } else if ((columnId & 7) === COLUMN_TYPE.STRING_RLE) { - return new RLEEncoder('utf8') - } else if ((columnId & 7) === COLUMN_TYPE.VALUE_RAW) { - return new Encoder() + if (patch.type === 'map') { + return updateMapObject(patch, obj, updated) + } else if (patch.type === 'table') { + return updateTableObject(patch, obj, updated) + } else if (patch.type === 'list') { + return updateListObject(patch, obj, updated) + } else if (patch.type === 'text') { + return updateTextObject(patch, obj, updated) } else { - return new RLEEncoder('uint') + throw new TypeError(`Unknown object type: ${patch.type}`) } } -function decoderByColumnId(columnId, buffer) { - if ((columnId & 7) === COLUMN_TYPE.INT_DELTA) { - return new DeltaDecoder(buffer) - } else if ((columnId & 7) === COLUMN_TYPE.BOOLEAN) { - return new BooleanDecoder(buffer) - } else if ((columnId & 7) === COLUMN_TYPE.STRING_RLE) { - return new RLEDecoder('utf8', buffer) - } else if ((columnId & 7) === COLUMN_TYPE.VALUE_RAW) { - return new Decoder(buffer) - } else { - return new RLEDecoder('uint', buffer) +/** + * Creates a writable copy of the immutable document root object `root`. + */ +function cloneRootObject(root) { + if (root[OBJECT_ID] !== '_root') { + throw new RangeError(`Not the root object: ${root[OBJECT_ID]}`) } + return cloneMapObject(root, '_root') } -function makeDecoders(columns, columnSpec) { - const emptyBuf = new Uint8Array(0) - let decoders = [], columnIndex = 0, specIndex = 0 +module.exports = { + interpretPatch, cloneRootObject +} - while (columnIndex < columns.length || specIndex < columnSpec.length) { - if (columnIndex === columns.length || - (specIndex < columnSpec.length && columnSpec[specIndex].columnId < columns[columnIndex].columnId)) { - const {columnId, columnName} = columnSpec[specIndex] - decoders.push({columnId, columnName, decoder: decoderByColumnId(columnId, emptyBuf)}) - specIndex++ - } else if (specIndex === columnSpec.length || columns[columnIndex].columnId < columnSpec[specIndex].columnId) { - const {columnId, buffer} = columns[columnIndex] - decoders.push({columnId, decoder: decoderByColumnId(columnId, buffer)}) - columnIndex++ - } else { // columns[columnIndex].columnId === columnSpec[specIndex].columnId - const {columnId, buffer} = columns[columnIndex], {columnName} = columnSpec[specIndex] - decoders.push({columnId, columnName, decoder: decoderByColumnId(columnId, buffer)}) - columnIndex++ - specIndex++ +},{"../src/common":82,"./constants":56,"./counter":58,"./table":63,"./text":64}],56:[function(require,module,exports){ +// Properties of the document root object +const OPTIONS = Symbol('_options') // object containing options passed to init() +const CACHE = Symbol('_cache') // map from objectId to immutable object +const STATE = Symbol('_state') // object containing metadata about current state (e.g. sequence numbers) + +// Properties of all Automerge objects +const OBJECT_ID = Symbol('_objectId') // the object ID of the current object (string) +const CONFLICTS = Symbol('_conflicts') // map or list (depending on object type) of conflicts +const CHANGE = Symbol('_change') // the context object on proxy objects used in change callback +const ELEM_IDS = Symbol('_elemIds') // list containing the element ID of each list element + +module.exports = { + OPTIONS, CACHE, STATE, OBJECT_ID, CONFLICTS, CHANGE, ELEM_IDS +} + +},{}],57:[function(require,module,exports){ +const { CACHE, OBJECT_ID, CONFLICTS, ELEM_IDS, STATE } = require('./constants') +const { interpretPatch } = require('./apply_patch') +const { Text } = require('./text') +const { Table } = require('./table') +const { Counter, getWriteableCounter } = require('./counter') +const { Int, Uint, Float64 } = require('./numbers') +const { isObject, parseOpId, createArrayOfNulls } = require('../src/common') +const uuid = require('../src/uuid') + + +/** + * An instance of this class is passed to `rootObjectProxy()`. The methods are + * called by proxy object mutation functions to query the current object state + * and to apply the requested changes. + */ +class Context { + constructor (doc, actorId, applyPatch) { + this.actorId = actorId + this.nextOpNum = doc[STATE].maxOp + 1 + this.cache = doc[CACHE] + this.updated = {} + this.ops = [] + this.applyPatch = applyPatch ? applyPatch : interpretPatch + } + + /** + * Adds an operation object to the list of changes made in the current context. + */ + addOp(operation) { + this.ops.push(operation) + + if (operation.action === 'set' && operation.values) { + this.nextOpNum += operation.values.length + } else if (operation.action === 'del' && operation.multiOp) { + this.nextOpNum += operation.multiOp + } else { + this.nextOpNum += 1 } } - return decoders -} -function decodeColumns(columns, actorIds, columnSpec) { - columns = makeDecoders(columns, columnSpec) - let parsedRows = [] - while (columns.some(col => !col.decoder.done)) { - let row = {}, col = 0 - while (col < columns.length) { - const columnId = columns[col].columnId - let groupId = columnId >> 4, groupCols = 1 - while (col + groupCols < columns.length && columns[col + groupCols].columnId >> 4 === groupId) { - groupCols++ - } + /** + * Returns the operation ID of the next operation to be added to the context. + */ + nextOpId() { + return `${this.nextOpNum}@${this.actorId}` + } - if (columnId % 8 === COLUMN_TYPE.GROUP_CARD) { - const values = [], count = columns[col].decoder.readValue() - for (let i = 0; i < count; i++) { - let value = {} - for (let colOffset = 1; colOffset < groupCols; colOffset++) { - decodeValueColumns(columns, col + colOffset, actorIds, value) - } - values.push(value) + /** + * Takes a value and returns an object describing the value (in the format used by patches). + */ + getValueDescription(value) { + if (!['object', 'boolean', 'number', 'string'].includes(typeof value)) { + throw new TypeError(`Unsupported type of value: ${typeof value}`) + } + + if (isObject(value)) { + if (value instanceof Date) { + // Date object, represented as milliseconds since epoch + return {type: 'value', value: value.getTime(), datatype: 'timestamp'} + + } else if (value instanceof Int) { + return {type: 'value', value: value.value, datatype: 'int'} + } else if (value instanceof Uint) { + return {type: 'value', value: value.value, datatype: 'uint'} + } else if (value instanceof Float64) { + return {type: 'value', value: value.value, datatype: 'float64'} + } else if (value instanceof Counter) { + // Counter object + return {type: 'value', value: value.value, datatype: 'counter'} + + } else { + // Nested object (map, list, text, or table) + const objectId = value[OBJECT_ID], type = this.getObjectType(objectId) + if (!objectId) { + throw new RangeError(`Object ${JSON.stringify(value)} has no objectId`) } - row[columns[col].columnName] = values - col += groupCols + if (type === 'list' || type === 'text') { + return {objectId, type, edits: []} + } else { + return {objectId, type, props: {}} + } + } + } else if (typeof value === 'number') { + if (Number.isInteger(value) && value <= Number.MAX_SAFE_INTEGER && value >= Number.MIN_SAFE_INTEGER) { + return {type: 'value', value, datatype: 'int'} } else { - col += decodeValueColumns(columns, col, actorIds, row) + return {type: 'value', value, datatype: 'float64'} } + } else { + // Primitive value (string, boolean, or null) + return {type: 'value', value} } - parsedRows.push(row) } - return parsedRows -} - -function decodeColumnInfo(decoder) { - // A number that is all 1 bits except for the bit that indicates whether a column is - // deflate-compressed. We ignore this bit when checking whether columns are sorted by ID. - const COLUMN_ID_MASK = (-1 ^ COLUMN_TYPE_DEFLATE) >>> 0 - let lastColumnId = -1, columns = [], numColumns = decoder.readUint53() - for (let i = 0; i < numColumns; i++) { - const columnId = decoder.readUint53(), bufferLen = decoder.readUint53() - if ((columnId & COLUMN_ID_MASK) <= (lastColumnId & COLUMN_ID_MASK)) { - throw new RangeError('Columns must be in ascending order') + /** + * Builds the values structure describing a single property in a patch. Finds all the values of + * property `key` of `object` (there might be multiple values in the case of a conflict), and + * returns an object that maps operation IDs to descriptions of values. + */ + getValuesDescriptions(path, object, key) { + if (object instanceof Table) { + // Table objects don't have conflicts, since rows are identified by their unique objectId + const value = object.byId(key) + const opId = object.opIds[key] + return value ? {[opId]: this.getValueDescription(value)} : {} + } else if (object instanceof Text) { + // Text objects don't support conflicts + const value = object.get(key) + const elemId = object.getElemId(key) + return value ? {[elemId]: this.getValueDescription(value)} : {} + } else { + // Map or list objects + const conflicts = object[CONFLICTS][key], values = {} + if (!conflicts) { + throw new RangeError(`No children at key ${key} of path ${JSON.stringify(path)}`) + } + for (let opId of Object.keys(conflicts)) { + values[opId] = this.getValueDescription(conflicts[opId]) + } + return values } - lastColumnId = columnId - columns.push({columnId, bufferLen}) } - return columns -} -function encodeColumnInfo(encoder, columns) { - const nonEmptyColumns = columns.filter(column => column.encoder.buffer.byteLength > 0) - encoder.appendUint53(nonEmptyColumns.length) - for (let column of nonEmptyColumns) { - encoder.appendUint53(column.columnId) - encoder.appendUint53(column.encoder.buffer.byteLength) + /** + * Returns the value at property `key` of object `object`. In the case of a conflict, returns + * the value whose assignment operation has the ID `opId`. + */ + getPropertyValue(object, key, opId) { + if (object instanceof Table) { + return object.byId(key) + } else if (object instanceof Text) { + return object.get(key) + } else { + return object[CONFLICTS][key][opId] + } } -} -function decodeChangeHeader(decoder) { - const numDeps = decoder.readUint53(), deps = [] - for (let i = 0; i < numDeps; i++) { - deps.push(bytesToHexString(decoder.readRawBytes(32))) - } - let change = { - actor: decoder.readHexString(), - seq: decoder.readUint53(), - startOp: decoder.readUint53(), - time: decoder.readInt53(), - message: decoder.readPrefixedString(), - deps - } - const actorIds = [change.actor], numActorIds = decoder.readUint53() - for (let i = 0; i < numActorIds; i++) actorIds.push(decoder.readHexString()) - change.actorIds = actorIds - return change -} + /** + * Recurses along `path` into the patch object `patch`, creating nodes along the way as needed + * by mutating the patch object. Returns the subpatch at the given path. + */ + getSubpatch(patch, path) { + if (path.length == 0) return patch + let subpatch = patch, object = this.getObject('_root') -/** - * Assembles a chunk of encoded data containing a checksum, headers, and a - * series of encoded columns. Calls `encodeHeaderCallback` with an encoder that - * should be used to add the headers. The columns should be given as `columns`. - */ -function encodeContainer(chunkType, encodeContentsCallback) { - const CHECKSUM_SIZE = 4 // checksum is first 4 bytes of SHA-256 hash of the rest of the data - const HEADER_SPACE = MAGIC_BYTES.byteLength + CHECKSUM_SIZE + 1 + 5 // 1 byte type + 5 bytes length - const body = new Encoder() - // Make space for the header at the beginning of the body buffer. We will - // copy the header in here later. This is cheaper than copying the body since - // the body is likely to be much larger than the header. - body.appendRawBytes(new Uint8Array(HEADER_SPACE)) - encodeContentsCallback(body) + for (let pathElem of path) { + let values = this.getValuesDescriptions(path, object, pathElem.key) + if (subpatch.props) { + if (!subpatch.props[pathElem.key]) { + subpatch.props[pathElem.key] = values + } + } else if (subpatch.edits) { + for (const opId of Object.keys(values)) { + subpatch.edits.push({action: 'update', index: pathElem.key, opId, value: values[opId]}) + } + } - const bodyBuf = body.buffer - const header = new Encoder() - header.appendByte(chunkType) - header.appendUint53(bodyBuf.byteLength - HEADER_SPACE) + let nextOpId = null + for (let opId of Object.keys(values)) { + if (values[opId].objectId === pathElem.objectId) { + nextOpId = opId + } + } + if (!nextOpId) { + throw new RangeError(`Cannot find path object with objectId ${pathElem.objectId}`) + } - // Compute the hash over chunkType, length, and body - const headerBuf = header.buffer - const sha256 = new Hash() - sha256.update(headerBuf) - sha256.update(bodyBuf.subarray(HEADER_SPACE)) - const hash = sha256.digest(), checksum = hash.subarray(0, CHECKSUM_SIZE) + subpatch = values[nextOpId] + object = this.getPropertyValue(object, pathElem.key, nextOpId) + } - // Copy header into the body buffer so that they are contiguous - bodyBuf.set(MAGIC_BYTES, HEADER_SPACE - headerBuf.byteLength - CHECKSUM_SIZE - MAGIC_BYTES.byteLength) - bodyBuf.set(checksum, HEADER_SPACE - headerBuf.byteLength - CHECKSUM_SIZE) - bodyBuf.set(headerBuf, HEADER_SPACE - headerBuf.byteLength) - return {hash, bytes: bodyBuf.subarray(HEADER_SPACE - headerBuf.byteLength - CHECKSUM_SIZE - MAGIC_BYTES.byteLength)} -} + return subpatch + } -function decodeContainerHeader(decoder, computeHash) { - if (!equalBytes(decoder.readRawBytes(MAGIC_BYTES.byteLength), MAGIC_BYTES)) { - throw new RangeError('Data does not begin with magic bytes 85 6f 4a 83') + /** + * Returns an object (not proxied) from the cache or updated set, as appropriate. + */ + getObject(objectId) { + const object = this.updated[objectId] || this.cache[objectId] + if (!object) throw new RangeError(`Target object does not exist: ${objectId}`) + return object } - const expectedHash = decoder.readRawBytes(4) - const hashStartOffset = decoder.offset - const chunkType = decoder.readByte() - const chunkLength = decoder.readUint53() - const header = {chunkType, chunkLength, chunkData: decoder.readRawBytes(chunkLength)} - if (computeHash) { - const sha256 = new Hash() - sha256.update(decoder.buf.subarray(hashStartOffset, decoder.offset)) - const binaryHash = sha256.digest() - if (!equalBytes(binaryHash.subarray(0, 4), expectedHash)) { - throw new RangeError('checksum does not match data') - } - header.hash = bytesToHexString(binaryHash) + /** + * Returns a string that is either 'map', 'table', 'list', or 'text', indicating + * the type of the object with ID `objectId`. + */ + getObjectType(objectId) { + if (objectId === '_root') return 'map' + const object = this.getObject(objectId) + if (object instanceof Text) return 'text' + if (object instanceof Table) return 'table' + if (Array.isArray(object)) return 'list' + return 'map' } - return header -} -function encodeChange(changeObj) { - const { changes, actorIds } = parseAllOpIds([changeObj], true) - const change = changes[0] + /** + * Returns the value associated with the property named `key` on the object + * at path `path`. If the value is an object, returns a proxy for it. + */ + getObjectField(path, objectId, key) { + if (!['string', 'number'].includes(typeof key)) return + const object = this.getObject(objectId) - const { hash, bytes } = encodeContainer(CHUNK_TYPE_CHANGE, encoder => { - if (!Array.isArray(change.deps)) throw new TypeError('deps is not an array') - encoder.appendUint53(change.deps.length) - for (let hash of change.deps.slice().sort()) { - encoder.appendRawBytes(hexStringToBytes(hash)) - } - encoder.appendHexString(change.actor) - encoder.appendUint53(change.seq) - encoder.appendUint53(change.startOp) - encoder.appendInt53(change.time) - encoder.appendPrefixedString(change.message || '') - encoder.appendUint53(actorIds.length - 1) - for (let actor of actorIds.slice(1)) encoder.appendHexString(actor) + if (object[key] instanceof Counter) { + return getWriteableCounter(object[key].value, this, path, objectId, key) - const columns = encodeOps(change.ops, false) - encodeColumnInfo(encoder, columns) - for (let column of columns) encoder.appendRawBytes(column.encoder.buffer) - if (change.extraBytes) encoder.appendRawBytes(change.extraBytes) - }) + } else if (isObject(object[key])) { + const childId = object[key][OBJECT_ID] + const subpath = path.concat([{key, objectId: childId}]) + // The instantiateObject function is added to the context object by rootObjectProxy() + return this.instantiateObject(subpath, childId) - const hexHash = bytesToHexString(hash) - if (changeObj.hash && changeObj.hash !== hexHash) { - throw new RangeError(`Change hash does not match encoding: ${changeObj.hash} != ${hexHash}`) + } else { + return object[key] + } } - return (bytes.byteLength >= DEFLATE_MIN_SIZE) ? deflateChange(bytes) : bytes -} - -function decodeChangeColumns(buffer) { - if (buffer[8] === CHUNK_TYPE_DEFLATE) buffer = inflateChange(buffer) - const decoder = new Decoder(buffer) - const header = decodeContainerHeader(decoder, true) - const chunkDecoder = new Decoder(header.chunkData) - if (!decoder.done) throw new RangeError('Encoded change has trailing data') - if (header.chunkType !== CHUNK_TYPE_CHANGE) throw new RangeError(`Unexpected chunk type: ${header.chunkType}`) - const change = decodeChangeHeader(chunkDecoder) - const columns = decodeColumnInfo(chunkDecoder) - for (let i = 0; i < columns.length; i++) { - if ((columns[i].columnId & COLUMN_TYPE_DEFLATE) !== 0) { - throw new RangeError('change must not contain deflated columns') + /** + * Recursively creates Automerge versions of all the objects and nested objects in `value`, + * constructing a patch and operations that describe the object tree. The new object is + * assigned to the property `key` in the object with ID `obj`. If the object is a list or + * text, `key` must be set to the list index being updated, and `elemId` must be set to the + * elemId of the element being updated. If `insert` is true, we insert a new list element + * (or text character) at index `key`, and `elemId` must be the elemId of the immediate + * predecessor element (or the string '_head' if inserting at index 0). If the assignment + * overwrites a previous value at this key/element, `pred` must be set to the array of the + * prior operations we are overwriting (empty array if there is no existing value). + */ + createNestedObjects(obj, key, value, insert, pred, elemId) { + if (value[OBJECT_ID]) { + throw new RangeError('Cannot create a reference to an existing document object') } - columns[i].buffer = chunkDecoder.readRawBytes(columns[i].bufferLen) - } - if (!chunkDecoder.done) { - const restLen = chunkDecoder.buf.byteLength - chunkDecoder.offset - change.extraBytes = chunkDecoder.readRawBytes(restLen) - } + const objectId = this.nextOpId() - change.columns = columns - change.hash = header.hash - return change -} + if (value instanceof Text) { + // Create a new Text object + this.addOp(elemId ? {action: 'makeText', obj, elemId, insert, pred} + : {action: 'makeText', obj, key, insert, pred}) + const subpatch = {objectId, type: 'text', edits: []} + this.insertListItems(subpatch, 0, [...value], true) + return subpatch -/** - * Decodes one change in binary format into its JS object representation. - */ -function decodeChange(buffer) { - const change = decodeChangeColumns(buffer) - change.ops = decodeOps(decodeColumns(change.columns, change.actorIds, CHANGE_COLUMNS), false) - delete change.actorIds - delete change.columns - return change -} + } else if (value instanceof Table) { + // Create a new Table object + if (value.count > 0) { + throw new RangeError('Assigning a non-empty Table object is not supported') + } + this.addOp(elemId ? {action: 'makeTable', obj, elemId, insert, pred} + : {action: 'makeTable', obj, key, insert, pred}) + return {objectId, type: 'table', props: {}} -/** - * Decodes the header fields of a change in binary format, but does not decode - * the operations. Saves work when we only need to inspect the headers. Only - * computes the hash of the change if `computeHash` is true. - */ -function decodeChangeMeta(buffer, computeHash) { - if (buffer[8] === CHUNK_TYPE_DEFLATE) buffer = inflateChange(buffer) - const header = decodeContainerHeader(new Decoder(buffer), computeHash) - if (header.chunkType !== CHUNK_TYPE_CHANGE) { - throw new RangeError('Buffer chunk type is not a change') + } else if (Array.isArray(value)) { + // Create a new list object + this.addOp(elemId ? {action: 'makeList', obj, elemId, insert, pred} + : {action: 'makeList', obj, key, insert, pred}) + const subpatch = {objectId, type: 'list', edits: []} + this.insertListItems(subpatch, 0, value, true) + return subpatch + + } else { + // Create a new map object + this.addOp(elemId ? {action: 'makeMap', obj, elemId, insert, pred} + : {action: 'makeMap', obj, key, insert, pred}) + let props = {} + for (let nested of Object.keys(value).sort()) { + const opId = this.nextOpId() + const valuePatch = this.setValue(objectId, nested, value[nested], false, []) + props[nested] = {[opId]: valuePatch} + } + return {objectId, type: 'map', props} + } } - const meta = decodeChangeHeader(new Decoder(header.chunkData)) - meta.change = buffer - if (computeHash) meta.hash = header.hash - return meta -} -/** - * Compresses a binary change using DEFLATE. - */ -function deflateChange(buffer) { - const header = decodeContainerHeader(new Decoder(buffer), false) - if (header.chunkType !== CHUNK_TYPE_CHANGE) throw new RangeError(`Unexpected chunk type: ${header.chunkType}`) - const compressed = pako.deflateRaw(header.chunkData) - const encoder = new Encoder() - encoder.appendRawBytes(buffer.subarray(0, 8)) // copy MAGIC_BYTES and checksum - encoder.appendByte(CHUNK_TYPE_DEFLATE) - encoder.appendUint53(compressed.byteLength) - encoder.appendRawBytes(compressed) - return encoder.buffer -} + /** + * Records an assignment to a particular key in a map, or a particular index in a list. + * `objectId` is the ID of the object being modified, `key` is the property name or list + * index being updated, and `value` is the new value being assigned. If `insert` is true, + * a new list element is inserted at index `key`, and `value` is assigned to that new list + * element. `pred` is an array of opIds for previous values of the property being assigned, + * which are overwritten by this operation. If the object being modified is a list or text, + * `elemId` is the element ID of the list element being updated (if insert=false), or the + * element ID of the list element immediately preceding the insertion (if insert=true). + * + * Returns a patch describing the new value. The return value is of the form + * `{objectId, type, props}` if `value` is an object, or `{value, datatype}` if it is a + * primitive value. For string, number, boolean, or null the datatype is omitted. + */ + setValue(objectId, key, value, insert, pred, elemId) { + if (!objectId) { + throw new RangeError('setValue needs an objectId') + } + if (key === '') { + throw new RangeError('The key of a map entry must not be an empty string') + } -/** - * Decompresses a binary change that has been compressed with DEFLATE. - */ -function inflateChange(buffer) { - const header = decodeContainerHeader(new Decoder(buffer), false) - if (header.chunkType !== CHUNK_TYPE_DEFLATE) throw new RangeError(`Unexpected chunk type: ${header.chunkType}`) - const decompressed = pako.inflateRaw(header.chunkData) - const encoder = new Encoder() - encoder.appendRawBytes(buffer.subarray(0, 8)) // copy MAGIC_BYTES and checksum - encoder.appendByte(CHUNK_TYPE_CHANGE) - encoder.appendUint53(decompressed.byteLength) - encoder.appendRawBytes(decompressed) - return encoder.buffer -} + if (isObject(value) && !(value instanceof Date) && !(value instanceof Counter) && !(value instanceof Int) && !(value instanceof Uint) && !(value instanceof Float64)) { + // Nested object (map, list, text, or table) + return this.createNestedObjects(objectId, key, value, insert, pred, elemId) + } else { + // Date or counter object, or primitive value (number, string, boolean, or null) + const description = this.getValueDescription(value) + const op = {action: 'set', obj: objectId, insert, value: description.value, pred} + if (elemId) op.elemId = elemId; else op.key = key + if (description.datatype) op.datatype = description.datatype + this.addOp(op) + return description + } + } -/** - * Takes an Uint8Array that may contain multiple concatenated changes, and - * returns an array of subarrays, each subarray containing one change. - */ -function splitContainers(buffer) { - let decoder = new Decoder(buffer), chunks = [], startOffset = 0 - while (!decoder.done) { - decodeContainerHeader(decoder, false) - chunks.push(buffer.subarray(startOffset, decoder.offset)) - startOffset = decoder.offset + /** + * Constructs a new patch, calls `callback` with the subpatch at the location `path`, + * and then immediately applies the patch to the document. + */ + applyAtPath(path, callback) { + let diff = {objectId: '_root', type: 'map', props: {}} + callback(this.getSubpatch(diff, path)) + this.applyPatch(diff, this.cache._root, this.updated) } - return chunks -} -/** - * Decodes a list of changes from the binary format into JS objects. - * `binaryChanges` is an array of `Uint8Array` objects. - */ -function decodeChanges(binaryChanges) { - let decoded = [] - for (let binaryChange of binaryChanges) { - for (let chunk of splitContainers(binaryChange)) { - if (chunk[8] === CHUNK_TYPE_DOCUMENT) { - decoded = decoded.concat(decodeDocument(chunk)) - } else if (chunk[8] === CHUNK_TYPE_CHANGE || chunk[8] === CHUNK_TYPE_DEFLATE) { - decoded.push(decodeChange(chunk)) - } else { - // ignoring chunk of unknown type - } + /** + * Updates the map object at path `path`, setting the property with name + * `key` to `value`. + */ + setMapKey(path, key, value) { + if (typeof key !== 'string') { + throw new RangeError(`The key of a map entry must be a string, not ${typeof key}`) } - } - return decoded -} -function sortOpIds(a, b) { - if (a === b) return 0 - if (a === '_root') return -1 - if (b === '_root') return +1 - const a_ = parseOpId(a), b_ = parseOpId(b) - if (a_.counter < b_.counter) return -1 - if (a_.counter > b_.counter) return +1 - if (a_.actorId < b_.actorId) return -1 - if (a_.actorId > b_.actorId) return +1 - return 0 -} + const objectId = path.length === 0 ? '_root' : path[path.length - 1].objectId + const object = this.getObject(objectId) + if (object[key] instanceof Counter) { + throw new RangeError('Cannot overwrite a Counter object; use .increment() or .decrement() to change its value.') + } -/** - * Takes a set of operations `ops` loaded from an encoded document, and - * reconstructs the changes that they originally came from. - * Does not return anything, only mutates `changes`. - */ -function groupChangeOps(changes, ops) { - let changesByActor = {} // map from actorId to array of changes by that actor - for (let change of changes) { - change.ops = [] - if (!changesByActor[change.actor]) changesByActor[change.actor] = [] - if (change.seq !== changesByActor[change.actor].length + 1) { - throw new RangeError(`Expected seq = ${changesByActor[change.actor].length + 1}, got ${change.seq}`) + // If the assigned field value is the same as the existing value, and + // the assignment does not resolve a conflict, do nothing + if (object[key] !== value || Object.keys(object[CONFLICTS][key] || {}).length > 1 || value === undefined) { + this.applyAtPath(path, subpatch => { + const pred = getPred(object, key) + const opId = this.nextOpId() + const valuePatch = this.setValue(objectId, key, value, false, pred) + subpatch.props[key] = {[opId]: valuePatch} + }) } - if (change.seq > 1 && changesByActor[change.actor][change.seq - 2].maxOp > change.maxOp) { - throw new RangeError('maxOp must increase monotonically per actor') + } + + /** + * Updates the map object at path `path`, deleting the property `key`. + */ + deleteMapKey(path, key) { + const objectId = path.length === 0 ? '_root' : path[path.length - 1].objectId + const object = this.getObject(objectId) + + if (object[key] !== undefined) { + const pred = getPred(object, key) + this.addOp({action: 'del', obj: objectId, key, insert: false, pred}) + this.applyAtPath(path, subpatch => { + subpatch.props[key] = {} + }) } - changesByActor[change.actor].push(change) } - let opsById = {} - for (let op of ops) { - if (op.action === 'del') throw new RangeError('document should not contain del operations') - op.pred = opsById[op.id] ? opsById[op.id].pred : [] - opsById[op.id] = op - for (let succ of op.succ) { - if (!opsById[succ]) { - if (op.elemId) { - const elemId = op.insert ? op.id : op.elemId - opsById[succ] = {id: succ, action: 'del', obj: op.obj, elemId, pred: []} - } else { - opsById[succ] = {id: succ, action: 'del', obj: op.obj, key: op.key, pred: []} - } + /** + * Inserts a sequence of new list elements `values` into a list, starting at position `index`. + * `newObject` is true if we are creating a new list object, and false if we are updating an + * existing one. `subpatch` is the patch for the list object being modified. Mutates + * `subpatch` to reflect the sequence of values. + */ + insertListItems(subpatch, index, values, newObject) { + const list = newObject ? [] : this.getObject(subpatch.objectId) + if (index < 0 || index > list.length) { + throw new RangeError(`List index ${index} is out of bounds for list of length ${list.length}`) + } + if (values.length === 0) return + + let elemId = getElemId(list, index, true) + const allPrimitive = values.every(v => typeof v === 'string' || typeof v === 'number' || + typeof v === 'boolean' || v === null || + (isObject(v) && (v instanceof Date || v instanceof Counter || v instanceof Int || + v instanceof Uint || v instanceof Float64))) + const allValueDescriptions = allPrimitive ? values.map(v => this.getValueDescription(v)) : [] + const allDatatypesSame = allValueDescriptions.every(t => t.datatype === allValueDescriptions[0].datatype) + + if (allPrimitive && allDatatypesSame && values.length > 1) { + const nextElemId = this.nextOpId() + const datatype = allValueDescriptions[0].datatype + const values = allValueDescriptions.map(v => v.value) + const op = {action: 'set', obj: subpatch.objectId, elemId, insert: true, values, pred: []} + const edit = {action: 'multi-insert', elemId: nextElemId, index, values} + if (datatype) { + op.datatype = datatype + edit.datatype = datatype + } + this.addOp(op) + subpatch.edits.push(edit) + } else { + for (let offset = 0; offset < values.length; offset++) { + let nextElemId = this.nextOpId() + const valuePatch = this.setValue(subpatch.objectId, index + offset, values[offset], true, [], elemId) + elemId = nextElemId + subpatch.edits.push({action: 'insert', index: index + offset, elemId, opId: elemId, value: valuePatch}) } - opsById[succ].pred.push(op.id) } - delete op.succ - } - for (let op of Object.values(opsById)) { - if (op.action === 'del') ops.push(op) } - for (let op of ops) { - const { counter, actorId } = parseOpId(op.id) - const actorChanges = changesByActor[actorId] - // Binary search to find the change that should contain this operation - let left = 0, right = actorChanges.length - while (left < right) { - const index = Math.floor((left + right) / 2) - if (actorChanges[index].maxOp < counter) { - left = index + 1 - } else { - right = index - } + /** + * Updates the list object at path `path`, replacing the current value at + * position `index` with the new value `value`. + */ + setListIndex(path, index, value) { + const objectId = path.length === 0 ? '_root' : path[path.length - 1].objectId + const list = this.getObject(objectId) + + // Assignment past the end of the list => insert nulls followed by new value + if (index >= list.length) { + const insertions = createArrayOfNulls(index - list.length) + insertions.push(value) + return this.splice(path, list.length, 0, insertions) } - if (left >= actorChanges.length) { - throw new RangeError(`Operation ID ${op.id} outside of allowed range`) + if (list[index] instanceof Counter) { + throw new RangeError('Cannot overwrite a Counter object; use .increment() or .decrement() to change its value.') } - actorChanges[left].ops.push(op) - } - for (let change of changes) { - change.ops.sort((op1, op2) => sortOpIds(op1.id, op2.id)) - change.startOp = change.maxOp - change.ops.length + 1 - delete change.maxOp - for (let i = 0; i < change.ops.length; i++) { - const op = change.ops[i], expectedId = `${change.startOp + i}@${change.actor}` - if (op.id !== expectedId) { - throw new RangeError(`Expected opId ${expectedId}, got ${op.id}`) - } - delete op.id + // If the assigned list element value is the same as the existing value, and + // the assignment does not resolve a conflict, do nothing + if (list[index] !== value || Object.keys(list[CONFLICTS][index] || {}).length > 1 || value === undefined) { + this.applyAtPath(path, subpatch => { + const pred = getPred(list, index) + const opId = this.nextOpId() + const valuePatch = this.setValue(objectId, index, value, false, pred, getElemId(list, index)) + subpatch.edits.push({action: 'update', index, opId, value: valuePatch}) + }) } } -} -function decodeDocumentChanges(changes, expectedHeads) { - let heads = {} // change hashes that are not a dependency of any other change - for (let i = 0; i < changes.length; i++) { - let change = changes[i] - change.deps = [] - for (let index of change.depsNum.map(d => d.depsIndex)) { - if (!changes[index] || !changes[index].hash) { - throw new RangeError(`No hash for index ${index} while processing index ${i}`) - } - const hash = changes[index].hash - change.deps.push(hash) - if (heads[hash]) delete heads[hash] + /** + * Updates the list object at path `path`, deleting `deletions` list elements starting from + * list index `start`, and inserting the list of new elements `insertions` at that position. + */ + splice(path, start, deletions, insertions) { + const objectId = path.length === 0 ? '_root' : path[path.length - 1].objectId + let list = this.getObject(objectId) + if (start < 0 || deletions < 0 || start > list.length - deletions) { + throw new RangeError(`${deletions} deletions starting at index ${start} are out of bounds for list of length ${list.length}`) } - change.deps.sort() - delete change.depsNum + if (deletions === 0 && insertions.length === 0) return - if (change.extraLen_datatype !== VALUE_TYPE.BYTES) { - throw new RangeError(`Bad datatype for extra bytes: ${VALUE_TYPE.BYTES}`) + let patch = {diffs: {objectId: '_root', type: 'map', props: {}}} + let subpatch = this.getSubpatch(patch.diffs, path) + + if (deletions > 0) { + let op, lastElemParsed, lastPredParsed + for (let i = 0; i < deletions; i++) { + if (this.getObjectField(path, objectId, start + i) instanceof Counter) { + // This may seem bizarre, but it's really fiddly to implement deletion of counters from + // lists, and I doubt anyone ever needs to do this, so I'm just going to throw an + // exception for now. The reason is: a counter is created by a set operation with counter + // datatype, and subsequent increment ops are successors to the set operation. Normally, a + // set operation with successor indicates a value that has been overwritten, so a set + // operation with successors is normally invisible. Counters are an exception, because the + // increment operations don't make the set operation invisible. When a counter appears in + // a map, this is not too bad: if all successors are increments, then the counter remains + // visible; if one or more successors are deletions, it goes away. However, when deleting + // a list element, we have the additional challenge that we need to distinguish between a + // list element that is being deleted by the current change (in which case we need to put + // a 'remove' action in the patch's edits for that list) and a list element that was + // already deleted previously (in which case the patch should not reflect the deletion). + // This can be done, but as I said, it's fiddly. If someone wants to pick this up in the + // future, hopefully the above description will be enough to get you started. Good luck! + throw new TypeError('Unsupported operation: deleting a counter from a list') + } + + // Any sequences of deletions with consecutive elemId and pred values get combined into a + // single multiOp; any others become individual deletion operations. This optimisation only + // kicks in if the user deletes a sequence of elements at once (in a single call to splice); + // it might be nice to also detect such runs of deletions in the case where the user deletes + // a sequence of list elements one by one. + const thisElem = getElemId(list, start + i), thisElemParsed = parseOpId(thisElem) + const thisPred = getPred(list, start + i) + const thisPredParsed = (thisPred.length === 1) ? parseOpId(thisPred[0]) : undefined + + if (op && lastElemParsed && lastPredParsed && thisPredParsed && + lastElemParsed.actorId === thisElemParsed.actorId && lastElemParsed.counter + 1 === thisElemParsed.counter && + lastPredParsed.actorId === thisPredParsed.actorId && lastPredParsed.counter + 1 === thisPredParsed.counter) { + op.multiOp = (op.multiOp || 1) + 1 + } else { + if (op) this.addOp(op) + op = {action: 'del', obj: objectId, elemId: thisElem, insert: false, pred: thisPred} + } + lastElemParsed = thisElemParsed + lastPredParsed = thisPredParsed + } + this.addOp(op) + subpatch.edits.push({action: 'remove', index: start, count: deletions}) } - change.extraBytes = change.extraLen - delete change.extraLen_datatype - // Encoding and decoding again to compute the hash of the change - changes[i] = decodeChange(encodeChange(change)) - heads[changes[i].hash] = true + if (insertions.length > 0) { + this.insertListItems(subpatch, start, insertions, false) + } + this.applyPatch(patch.diffs, this.cache._root, this.updated) } - const actualHeads = Object.keys(heads).sort() - let headsEqual = (actualHeads.length === expectedHeads.length), i = 0 - while (headsEqual && i < actualHeads.length) { - headsEqual = (actualHeads[i] === expectedHeads[i]) - i++ - } - if (!headsEqual) { - throw new RangeError(`Mismatched heads hashes: expected ${expectedHeads.join(', ')}, got ${actualHeads.join(', ')}`) + /** + * Updates the table object at path `path`, adding a new entry `row`. + * Returns the objectId of the new row. + */ + addTableRow(path, row) { + if (!isObject(row) || Array.isArray(row)) { + throw new TypeError('A table row must be an object') + } + if (row[OBJECT_ID]) { + throw new TypeError('Cannot reuse an existing object as table row') + } + if (row.id) { + throw new TypeError('A table row must not have an "id" property; it is generated automatically') + } + + const id = uuid() + const valuePatch = this.setValue(path[path.length - 1].objectId, id, row, false, []) + this.applyAtPath(path, subpatch => { + subpatch.props[id] = {[valuePatch.objectId]: valuePatch} + }) + return id } -} -function encodeDocumentHeader(doc) { - const { changesColumns, opsColumns, actorIds, heads, headsIndexes, extraBytes } = doc - for (let column of changesColumns) deflateColumn(column) - for (let column of opsColumns) deflateColumn(column) + /** + * Updates the table object at path `path`, deleting the row with ID `rowId`. + * `pred` is the opId of the operation that originally created the row. + */ + deleteTableRow(path, rowId, pred) { + const objectId = path[path.length - 1].objectId, table = this.getObject(objectId) - return encodeContainer(CHUNK_TYPE_DOCUMENT, encoder => { - encoder.appendUint53(actorIds.length) - for (let actor of actorIds) { - encoder.appendHexString(actor) + if (table.byId(rowId)) { + this.addOp({action: 'del', obj: objectId, key: rowId, insert: false, pred: [pred]}) + this.applyAtPath(path, subpatch => { + subpatch.props[rowId] = {} + }) } - encoder.appendUint53(heads.length) - for (let head of heads.sort()) { - encoder.appendRawBytes(hexStringToBytes(head)) + } + + /** + * Adds the integer `delta` to the value of the counter located at property + * `key` in the object at path `path`. + */ + increment(path, key, delta) { + const objectId = path.length === 0 ? '_root' : path[path.length - 1].objectId + const object = this.getObject(objectId) + if (!(object[key] instanceof Counter)) { + throw new TypeError('Only counter values can be incremented') } - encodeColumnInfo(encoder, changesColumns) - encodeColumnInfo(encoder, opsColumns) - for (let column of changesColumns) encoder.appendRawBytes(column.encoder.buffer) - for (let column of opsColumns) encoder.appendRawBytes(column.encoder.buffer) - for (let index of headsIndexes) encoder.appendUint53(index) - if (extraBytes) encoder.appendRawBytes(extraBytes) - }).bytes -} -function decodeDocumentHeader(buffer) { - const documentDecoder = new Decoder(buffer) - const header = decodeContainerHeader(documentDecoder, true) - const decoder = new Decoder(header.chunkData) - if (!documentDecoder.done) throw new RangeError('Encoded document has trailing data') - if (header.chunkType !== CHUNK_TYPE_DOCUMENT) throw new RangeError(`Unexpected chunk type: ${header.chunkType}`) + // TODO what if there is a conflicting value on the same key as the counter? + const type = this.getObjectType(objectId) + const value = object[key].value + delta + const opId = this.nextOpId() + const pred = getPred(object, key) - const actorIds = [], numActors = decoder.readUint53() - for (let i = 0; i < numActors; i++) { - actorIds.push(decoder.readHexString()) - } - const heads = [], headsIndexes = [], numHeads = decoder.readUint53() - for (let i = 0; i < numHeads; i++) { - heads.push(bytesToHexString(decoder.readRawBytes(32))) - } + if (type === 'list' || type === 'text') { + const elemId = getElemId(object, key, false) + this.addOp({action: 'inc', obj: objectId, elemId, value: delta, insert: false, pred}) + } else { + this.addOp({action: 'inc', obj: objectId, key, value: delta, insert: false, pred}) + } - const changesColumns = decodeColumnInfo(decoder) - const opsColumns = decodeColumnInfo(decoder) - for (let i = 0; i < changesColumns.length; i++) { - changesColumns[i].buffer = decoder.readRawBytes(changesColumns[i].bufferLen) - inflateColumn(changesColumns[i]) - } - for (let i = 0; i < opsColumns.length; i++) { - opsColumns[i].buffer = decoder.readRawBytes(opsColumns[i].bufferLen) - inflateColumn(opsColumns[i]) - } - if (!decoder.done) { - for (let i = 0; i < numHeads; i++) headsIndexes.push(decoder.readUint53()) + this.applyAtPath(path, subpatch => { + if (type === 'list' || type === 'text') { + subpatch.edits.push({action: 'update', index: key, opId, value: {value, datatype: 'counter'}}) + } else { + subpatch.props[key] = {[opId]: {value, datatype: 'counter'}} + } + }) } - - const extraBytes = decoder.readRawBytes(decoder.buf.byteLength - decoder.offset) - return { changesColumns, opsColumns, actorIds, heads, headsIndexes, extraBytes } -} - -function decodeDocument(buffer) { - const { changesColumns, opsColumns, actorIds, heads } = decodeDocumentHeader(buffer) - const changes = decodeColumns(changesColumns, actorIds, DOCUMENT_COLUMNS) - const ops = decodeOps(decodeColumns(opsColumns, actorIds, DOC_OPS_COLUMNS), true) - groupChangeOps(changes, ops) - decodeDocumentChanges(changes, heads) - return changes } -/** - * DEFLATE-compresses the given column if it is large enough to make the compression worthwhile. - */ -function deflateColumn(column) { - if (column.encoder.buffer.byteLength >= DEFLATE_MIN_SIZE) { - column.encoder = {buffer: pako.deflateRaw(column.encoder.buffer)} - column.columnId |= COLUMN_TYPE_DEFLATE +function getPred(object, key) { + if (object instanceof Table) { + return [object.opIds[key]] + } else if (object instanceof Text) { + return object.elems[key].pred + } else if (object[CONFLICTS]) { + return object[CONFLICTS][key] ? Object.keys(object[CONFLICTS][key]) : [] + } else { + return [] } } -/** - * Decompresses the given column if it is DEFLATE-compressed. - */ -function inflateColumn(column) { - if ((column.columnId & COLUMN_TYPE_DEFLATE) !== 0) { - column.buffer = pako.inflateRaw(column.buffer) - column.columnId ^= COLUMN_TYPE_DEFLATE +function getElemId(list, index, insert = false) { + if (insert) { + if (index === 0) return '_head' + index -= 1 } + if (list[ELEM_IDS]) return list[ELEM_IDS][index] + if (list.getElemId) return list.getElemId(index) + throw new RangeError(`Cannot find elemId at list index ${index}`) } module.exports = { - COLUMN_TYPE, VALUE_TYPE, ACTIONS, OBJECT_TYPE, DOC_OPS_COLUMNS, CHANGE_COLUMNS, DOCUMENT_COLUMNS, - encoderByColumnId, decoderByColumnId, makeDecoders, decodeValue, - splitContainers, encodeChange, decodeChangeColumns, decodeChange, decodeChangeMeta, decodeChanges, - encodeDocumentHeader, decodeDocumentHeader, decodeDocument + Context } -},{"../src/common":87,"./encoding":50,"fast-sha256":213,"pako":65}],50:[function(require,module,exports){ +},{"../src/common":82,"../src/uuid":83,"./apply_patch":55,"./constants":56,"./counter":58,"./numbers":60,"./table":63,"./text":64}],58:[function(require,module,exports){ /** - * UTF-8 decoding and encoding using API that is supported in Node >= 12 and modern browsers: - * https://developer.mozilla.org/en-US/docs/Web/API/TextEncoder/encode - * https://developer.mozilla.org/en-US/docs/Web/API/TextDecoder/decode - * If you're running in an environment where it's not available, please use a polyfill, such as: - * https://github.com/anonyco/FastestSmallestTextEncoderDecoder - */ -const utf8encoder = new TextEncoder() -const utf8decoder = new TextDecoder('utf-8') - -function stringToUtf8(string) { - return utf8encoder.encode(string) -} - -function utf8ToString(buffer) { - return utf8decoder.decode(buffer) -} - -/** - * Converts a string consisting of hexadecimal digits into an Uint8Array. - */ -function hexStringToBytes(value) { - if (typeof value !== 'string') { - throw new TypeError('value is not a string') - } - if (!/^([0-9a-f][0-9a-f])*$/.test(value)) { - throw new RangeError('value is not hexadecimal') - } - if (value === '') { - return new Uint8Array(0) - } else { - return new Uint8Array(value.match(/../g).map(b => parseInt(b, 16))) - } -} - -const NIBBLE_TO_HEX = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'] -const BYTE_TO_HEX = new Array(256) -for (let i = 0; i < 256; i++) { - BYTE_TO_HEX[i] = `${NIBBLE_TO_HEX[(i >>> 4) & 0xf]}${NIBBLE_TO_HEX[i & 0xf]}`; -} - -/** - * Converts a Uint8Array into the equivalent hexadecimal string. - */ -function bytesToHexString(bytes) { - let hex = '', len = bytes.byteLength - for (let i = 0; i < len; i++) { - hex += BYTE_TO_HEX[bytes[i]] - } - return hex -} - -/** - * Wrapper around an Uint8Array that allows values to be appended to the buffer, - * and that automatically grows the buffer when space runs out. + * The most basic CRDT: an integer value that can be changed only by + * incrementing and decrementing. Since addition of integers is commutative, + * the value trivially converges. */ -class Encoder { - constructor() { - this.buf = new Uint8Array(16) - this.offset = 0 +class Counter { + constructor(value) { + this.value = value || 0 + Object.freeze(this) } /** - * Returns the byte array containing the encoded data. + * A peculiar JavaScript language feature from its early days: if the object + * `x` has a `valueOf()` method that returns a number, you can use numerical + * operators on the object `x` directly, such as `x + 1` or `x < 4`. + * This method is also called when coercing a value to a string by + * concatenating it with another string, as in `x + ''`. + * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/valueOf */ - get buffer() { - this.finish() - return this.buf.subarray(0, this.offset) + valueOf() { + return this.value } /** - * Reallocates the encoder's buffer to be bigger. + * Returns the counter value as a decimal string. If `x` is a counter object, + * this method is called e.g. when you do `['value: ', x].join('')` or when + * you use string interpolation: `value: ${x}`. */ - grow(minSize = 0) { - let newSize = this.buf.byteLength * 4 - while (newSize < minSize) newSize *= 2 - const newBuf = new Uint8Array(newSize) - newBuf.set(this.buf, 0) - this.buf = newBuf - return this + toString() { + return this.valueOf().toString() } /** - * Appends one byte (0 to 255) to the buffer. + * Returns the counter value, so that a JSON serialization of an Automerge + * document represents the counter simply as an integer. */ - appendByte(value) { - if (this.offset >= this.buf.byteLength) this.grow() - this.buf[this.offset] = value - this.offset += 1 + toJSON() { + return this.value } +} +/** + * An instance of this class is used when a counter is accessed within a change + * callback. + */ +class WriteableCounter extends Counter { /** - * Encodes a 32-bit nonnegative integer in a variable number of bytes using - * the LEB128 encoding scheme (https://en.wikipedia.org/wiki/LEB128) and - * appends it to the buffer. Returns the number of bytes written. + * Increases the value of the counter by `delta`. If `delta` is not given, + * increases the value of the counter by 1. */ - appendUint32(value) { - if (!Number.isInteger(value)) throw new RangeError('value is not an integer') - if (value < 0 || value > 0xffffffff) throw new RangeError('number out of range') - - const numBytes = Math.max(1, Math.ceil((32 - Math.clz32(value)) / 7)) - if (this.offset + numBytes > this.buf.byteLength) this.grow() - - for (let i = 0; i < numBytes; i++) { - this.buf[this.offset + i] = (value & 0x7f) | (i === numBytes - 1 ? 0x00 : 0x80) - value >>>= 7 // zero-filling right shift - } - this.offset += numBytes - return numBytes + increment(delta) { + delta = typeof delta === 'number' ? delta : 1 + this.context.increment(this.path, this.key, delta) + this.value += delta + return this.value } /** - * Encodes a 32-bit signed integer in a variable number of bytes using the - * LEB128 encoding scheme (https://en.wikipedia.org/wiki/LEB128) and appends - * it to the buffer. Returns the number of bytes written. + * Decreases the value of the counter by `delta`. If `delta` is not given, + * decreases the value of the counter by 1. */ - appendInt32(value) { - if (!Number.isInteger(value)) throw new RangeError('value is not an integer') - if (value < -0x80000000 || value > 0x7fffffff) throw new RangeError('number out of range') - - const numBytes = Math.ceil((33 - Math.clz32(value >= 0 ? value : -value - 1)) / 7) - if (this.offset + numBytes > this.buf.byteLength) this.grow() - - for (let i = 0; i < numBytes; i++) { - this.buf[this.offset + i] = (value & 0x7f) | (i === numBytes - 1 ? 0x00 : 0x80) - value >>= 7 // sign-propagating right shift - } - this.offset += numBytes - return numBytes + decrement(delta) { + return this.increment(typeof delta === 'number' ? -delta : -1) } +} - /** - * Encodes a nonnegative integer in a variable number of bytes using the LEB128 - * encoding scheme, up to the maximum size of integers supported by JavaScript - * (53 bits). - */ - appendUint53(value) { - if (!Number.isInteger(value)) throw new RangeError('value is not an integer') - if (value < 0 || value > Number.MAX_SAFE_INTEGER) { - throw new RangeError('number out of range') - } - const high32 = Math.floor(value / 0x100000000) - const low32 = (value & 0xffffffff) >>> 0 // right shift to interpret as unsigned - return this.appendUint64(high32, low32) - } +/** + * Returns an instance of `WriteableCounter` for use in a change callback. + * `context` is the proxy context that keeps track of the mutations. + * `objectId` is the ID of the object containing the counter, and `key` is + * the property name (key in map, or index in list) where the counter is + * located. +*/ +function getWriteableCounter(value, context, path, objectId, key) { + const instance = Object.create(WriteableCounter.prototype) + instance.value = value + instance.context = context + instance.path = path + instance.objectId = objectId + instance.key = key + return instance +} - /** - * Encodes a signed integer in a variable number of bytes using the LEB128 - * encoding scheme, up to the maximum size of integers supported by JavaScript - * (53 bits). - */ - appendInt53(value) { - if (!Number.isInteger(value)) throw new RangeError('value is not an integer') - if (value < Number.MIN_SAFE_INTEGER || value > Number.MAX_SAFE_INTEGER) { - throw new RangeError('number out of range') - } - const high32 = Math.floor(value / 0x100000000) - const low32 = (value & 0xffffffff) >>> 0 // right shift to interpret as unsigned - return this.appendInt64(high32, low32) - } +module.exports = { Counter, getWriteableCounter } - /** - * Encodes a 64-bit nonnegative integer in a variable number of bytes using - * the LEB128 encoding scheme, and appends it to the buffer. The number is - * given as two 32-bit halves since JavaScript cannot accurately represent - * integers with more than 53 bits in a single variable. - */ - appendUint64(high32, low32) { - if (!Number.isInteger(high32) || !Number.isInteger(low32)) { - throw new RangeError('value is not an integer') - } - if (high32 < 0 || high32 > 0xffffffff || low32 < 0 || low32 > 0xffffffff) { - throw new RangeError('number out of range') - } - if (high32 === 0) return this.appendUint32(low32) +},{}],59:[function(require,module,exports){ +const { OPTIONS, CACHE, STATE, OBJECT_ID, CONFLICTS, CHANGE, ELEM_IDS } = require('./constants') +const { isObject, copyObject } = require('../src/common') +const uuid = require('../src/uuid') +const { interpretPatch, cloneRootObject } = require('./apply_patch') +const { rootObjectProxy } = require('./proxies') +const { Context } = require('./context') +const { Text } = require('./text') +const { Table } = require('./table') +const { Counter } = require('./counter') +const { Float64, Int, Uint } = require('./numbers') +const { Observable } = require('./observable') - const numBytes = Math.ceil((64 - Math.clz32(high32)) / 7) - if (this.offset + numBytes > this.buf.byteLength) this.grow() - for (let i = 0; i < 4; i++) { - this.buf[this.offset + i] = (low32 & 0x7f) | 0x80 - low32 >>>= 7 // zero-filling right shift - } - this.buf[this.offset + 4] = (low32 & 0x0f) | ((high32 & 0x07) << 4) | (numBytes === 5 ? 0x00 : 0x80) - high32 >>>= 3 - for (let i = 5; i < numBytes; i++) { - this.buf[this.offset + i] = (high32 & 0x7f) | (i === numBytes - 1 ? 0x00 : 0x80) - high32 >>>= 7 - } - this.offset += numBytes - return numBytes +/** + * Actor IDs must consist only of hexadecimal digits so that they can be encoded + * compactly in binary form. + */ +function checkActorId(actorId) { + if (typeof actorId !== 'string') { + throw new TypeError(`Unsupported type of actorId: ${typeof actorId}`) } + if (!/^[0-9a-f]+$/.test(actorId)) { + throw new RangeError('actorId must consist only of lowercase hex digits') + } + if (actorId.length % 2 !== 0) { + throw new RangeError('actorId must consist of an even number of digits') + } +} - /** - * Encodes a 64-bit signed integer in a variable number of bytes using the - * LEB128 encoding scheme, and appends it to the buffer. The number is given - * as two 32-bit halves since JavaScript cannot accurately represent integers - * with more than 53 bits in a single variable. The sign of the 64-bit - * number is determined by the sign of the `high32` half; the sign of the - * `low32` half is ignored. - */ - appendInt64(high32, low32) { - if (!Number.isInteger(high32) || !Number.isInteger(low32)) { - throw new RangeError('value is not an integer') - } - if (high32 < -0x80000000 || high32 > 0x7fffffff || low32 < -0x80000000 || low32 > 0xffffffff) { - throw new RangeError('number out of range') - } - low32 >>>= 0 // interpret as unsigned - if (high32 === 0 && low32 <= 0x7fffffff) return this.appendInt32(low32) - if (high32 === -1 && low32 >= 0x80000000) return this.appendInt32(low32 - 0x100000000) +/** + * Takes a set of objects that have been updated (in `updated`) and an updated state object + * `state`, and returns a new immutable document root object based on `doc` that reflects + * those updates. + */ +function updateRootObject(doc, updated, state) { + let newDoc = updated._root + if (!newDoc) { + newDoc = cloneRootObject(doc[CACHE]._root) + updated._root = newDoc + } + Object.defineProperty(newDoc, OPTIONS, {value: doc[OPTIONS]}) + Object.defineProperty(newDoc, CACHE, {value: updated}) + Object.defineProperty(newDoc, STATE, {value: state}) - const numBytes = Math.ceil((65 - Math.clz32(high32 >= 0 ? high32 : -high32 - 1)) / 7) - if (this.offset + numBytes > this.buf.byteLength) this.grow() - for (let i = 0; i < 4; i++) { - this.buf[this.offset + i] = (low32 & 0x7f) | 0x80 - low32 >>>= 7 // zero-filling right shift - } - this.buf[this.offset + 4] = (low32 & 0x0f) | ((high32 & 0x07) << 4) | (numBytes === 5 ? 0x00 : 0x80) - high32 >>= 3 // sign-propagating right shift - for (let i = 5; i < numBytes; i++) { - this.buf[this.offset + i] = (high32 & 0x7f) | (i === numBytes - 1 ? 0x00 : 0x80) - high32 >>= 7 + if (doc[OPTIONS].freeze) { + for (let objectId of Object.keys(updated)) { + if (updated[objectId] instanceof Table) { + updated[objectId]._freeze() + } else if (updated[objectId] instanceof Text) { + Object.freeze(updated[objectId].elems) + Object.freeze(updated[objectId]) + } else { + Object.freeze(updated[objectId]) + Object.freeze(updated[objectId][CONFLICTS]) + } } - this.offset += numBytes - return numBytes } - /** - * Appends the contents of byte buffer `data` to the buffer. Returns the - * number of bytes appended. - */ - appendRawBytes(data) { - if (this.offset + data.byteLength > this.buf.byteLength) { - this.grow(this.offset + data.byteLength) + for (let objectId of Object.keys(doc[CACHE])) { + if (!updated[objectId]) { + updated[objectId] = doc[CACHE][objectId] } - this.buf.set(data, this.offset) - this.offset += data.byteLength - return data.byteLength } - /** - * Appends a UTF-8 string to the buffer, without any metadata. Returns the - * number of bytes appended. - */ - appendRawString(value) { - if (typeof value !== 'string') throw new TypeError('value is not a string') - return this.appendRawBytes(stringToUtf8(value)) + if (doc[OPTIONS].freeze) { + Object.freeze(updated) } + return newDoc +} - /** - * Appends the contents of byte buffer `data` to the buffer, prefixed with the - * number of bytes in the buffer (as a LEB128-encoded unsigned integer). - */ - appendPrefixedBytes(data) { - this.appendUint53(data.byteLength) - this.appendRawBytes(data) - return this +/** + * Adds a new change request to the list of pending requests, and returns an + * updated document root object. + * The details of the change are taken from the context object `context`. + * `options` contains properties that may affect how the change is processed; in + * particular, the `message` property of `options` is an optional human-readable + * string describing the change. + */ +function makeChange(doc, context, options) { + const actor = getActorId(doc) + if (!actor) { + throw new Error('Actor ID must be initialized with setActorId() before making a change') } + const state = copyObject(doc[STATE]) + state.seq += 1 - /** - * Appends a UTF-8 string to the buffer, prefixed with its length in bytes - * (where the length is encoded as an unsigned LEB128 integer). - */ - appendPrefixedString(value) { - if (typeof value !== 'string') throw new TypeError('value is not a string') - this.appendPrefixedBytes(stringToUtf8(value)) - return this + const change = { + actor, + seq: state.seq, + startOp: state.maxOp + 1, + deps: state.deps, + time: (options && typeof options.time === 'number') ? options.time + : Math.round(new Date().getTime() / 1000), + message: (options && typeof options.message === 'string') ? options.message : '', + ops: context.ops } - /** - * Takes a value, which must be a string consisting only of hexadecimal - * digits, maps it to a byte array, and appends it to the buffer, prefixed - * with its length in bytes. - */ - appendHexString(value) { - this.appendPrefixedBytes(hexStringToBytes(value)) - return this + if (doc[OPTIONS].backend) { + const [backendState, patch, binaryChange] = doc[OPTIONS].backend.applyLocalChange(state.backendState, change) + state.backendState = backendState + state.lastLocalChange = binaryChange + // NOTE: When performing a local change, the patch is effectively applied twice -- once by the + // context invoking interpretPatch as soon as any change is made, and the second time here + // (after a round-trip through the backend). This is perhaps more robust, as changes only take + // effect in the form processed by the backend, but the downside is a performance cost. + // Should we change this? + const newDoc = applyPatchToDoc(doc, patch, state, true) + const patchCallback = options && options.patchCallback || doc[OPTIONS].patchCallback + if (patchCallback) patchCallback(patch, doc, newDoc, true, [binaryChange]) + return [newDoc, change] + + } else { + const queuedRequest = {actor, seq: change.seq, before: doc} + state.requests = state.requests.concat([queuedRequest]) + state.maxOp = state.maxOp + countOps(change.ops) + state.deps = [] + return [updateRootObject(doc, context ? context.updated : {}, state), change] } +} - /** - * Flushes any unwritten data to the buffer. Call this before reading from - * the buffer constructed by this Encoder. - */ - finish() { +function countOps(ops) { + let count = 0 + for (const op of ops) { + if (op.action === 'set' && op.values) { + count += op.values.length + } else { + count += 1 + } } + return count } /** - * Counterpart to Encoder. Wraps a Uint8Array buffer with a cursor indicating - * the current decoding position, and allows values to be incrementally read by - * decoding the bytes at the current position. + * Returns the binary encoding of the last change made by the local actor. */ -class Decoder { - constructor(buffer) { - if (!(buffer instanceof Uint8Array)) { - throw new TypeError(`Not a byte array: ${buffer}`) +function getLastLocalChange(doc) { + return doc[STATE] && doc[STATE].lastLocalChange ? doc[STATE].lastLocalChange : null +} + +/** + * Applies the changes described in `patch` to the document with root object + * `doc`. The state object `state` is attached to the new root object. + * `fromBackend` should be set to `true` if the patch came from the backend, + * and to `false` if the patch is a transient local (optimistically applied) + * change from the frontend. + */ +function applyPatchToDoc(doc, patch, state, fromBackend) { + const actor = getActorId(doc) + const updated = {} + interpretPatch(patch.diffs, doc, updated) + + if (fromBackend) { + if (!patch.clock) throw new RangeError('patch is missing clock field') + if (patch.clock[actor] && patch.clock[actor] > state.seq) { + state.seq = patch.clock[actor] } - this.buf = buffer - this.offset = 0 + state.clock = patch.clock + state.deps = patch.deps + state.maxOp = Math.max(state.maxOp, patch.maxOp) } + return updateRootObject(doc, updated, state) +} - /** - * Returns false if there is still data to be read at the current decoding - * position, and true if we are at the end of the buffer. - */ - get done() { - return this.offset === this.buf.byteLength +/** + * Creates an empty document object with no changes. + */ +function init(options) { + if (typeof options === 'string') { + options = {actorId: options} + } else if (typeof options === 'undefined') { + options = {} + } else if (!isObject(options)) { + throw new TypeError(`Unsupported value for init() options: ${options}`) } - /** - * Resets the cursor position, so that the next read goes back to the - * beginning of the buffer. - */ - reset() { - this.offset = 0 + if (!options.deferActorId) { + if (options.actorId === undefined) { + options.actorId = uuid() + } + checkActorId(options.actorId) } - /** - * Moves the current decoding position forward by the specified number of - * bytes, without decoding anything. - */ - skip(bytes) { - if (this.offset + bytes > this.buf.byteLength) { - throw new RangeError('cannot skip beyond end of buffer') + if (options.observable) { + const patchCallback = options.patchCallback, observable = options.observable + options.patchCallback = (patch, before, after, local, changes) => { + if (patchCallback) patchCallback(patch, before, after, local, changes) + observable.patchCallback(patch, before, after, local, changes) } - this.offset += bytes } - /** - * Reads one byte (0 to 255) from the buffer. - */ - readByte() { - this.offset += 1 - return this.buf[this.offset - 1] + const root = {}, cache = {_root: root} + const state = {seq: 0, maxOp: 0, requests: [], clock: {}, deps: []} + if (options.backend) { + state.backendState = options.backend.init() + state.lastLocalChange = null } + Object.defineProperty(root, OBJECT_ID, {value: '_root'}) + Object.defineProperty(root, OPTIONS, {value: Object.freeze(options)}) + Object.defineProperty(root, CONFLICTS, {value: Object.freeze({})}) + Object.defineProperty(root, CACHE, {value: Object.freeze(cache)}) + Object.defineProperty(root, STATE, {value: Object.freeze(state)}) + return Object.freeze(root) +} - /** - * Reads a LEB128-encoded unsigned integer from the current position in the buffer. - * Throws an exception if the value doesn't fit in a 32-bit unsigned int. - */ - readUint32() { - let result = 0, shift = 0 - while (this.offset < this.buf.byteLength) { - const nextByte = this.buf[this.offset] - if (shift === 28 && (nextByte & 0xf0) !== 0) { // more than 5 bytes, or value > 0xffffffff - throw new RangeError('number out of range') - } - result = (result | (nextByte & 0x7f) << shift) >>> 0 // right shift to interpret value as unsigned - shift += 7 - this.offset++ - if ((nextByte & 0x80) === 0) return result - } - throw new RangeError('buffer ended with incomplete number') +/** + * Returns a new document object initialized with the given state. + */ +function from(initialState, options) { + return change(init(options), 'Initialization', doc => Object.assign(doc, initialState)) +} + + +/** + * Changes a document `doc` according to actions taken by the local user. + * `options` is an object that can contain the following properties: + * - `message`: an optional descriptive string that is attached to the change. + * If `options` is a string, it is treated as `message`. + * + * The actual change is made within the callback function `callback`, which is + * given a mutable version of the document as argument. Returns a two-element + * array `[doc, request]` where `doc` is the updated document, and `request` + * is the change request to send to the backend. If nothing was actually + * changed, returns the original `doc` and a `null` change request. + */ +function change(doc, options, callback) { + if (doc[OBJECT_ID] !== '_root') { + throw new TypeError('The first argument to Automerge.change must be the document root') + } + if (doc[CHANGE]) { + throw new TypeError('Calls to Automerge.change cannot be nested') + } + if (typeof options === 'function' && callback === undefined) { + [options, callback] = [callback, options] + } + if (typeof options === 'string') { + options = {message: options} + } + if (options !== undefined && !isObject(options)) { + throw new TypeError('Unsupported type of options') } - /** - * Reads a LEB128-encoded signed integer from the current position in the buffer. - * Throws an exception if the value doesn't fit in a 32-bit signed int. - */ - readInt32() { - let result = 0, shift = 0 - while (this.offset < this.buf.byteLength) { - const nextByte = this.buf[this.offset] - if ((shift === 28 && (nextByte & 0x80) !== 0) || // more than 5 bytes - (shift === 28 && (nextByte & 0x40) === 0 && (nextByte & 0x38) !== 0) || // positive int > 0x7fffffff - (shift === 28 && (nextByte & 0x40) !== 0 && (nextByte & 0x38) !== 0x38)) { // negative int < -0x80000000 - throw new RangeError('number out of range') - } - result |= (nextByte & 0x7f) << shift - shift += 7 - this.offset++ + const actorId = getActorId(doc) + if (!actorId) { + throw new Error('Actor ID must be initialized with setActorId() before making a change') + } + const context = new Context(doc, actorId) + callback(rootObjectProxy(context)) - if ((nextByte & 0x80) === 0) { - if ((nextByte & 0x40) === 0 || shift > 28) { - return result // positive, or negative value that doesn't need sign-extending - } else { - return result | (-1 << shift) // sign-extend negative integer - } - } - } - throw new RangeError('buffer ended with incomplete number') + if (Object.keys(context.updated).length === 0) { + // If the callback didn't change anything, return the original document object unchanged + return [doc, null] + } else { + return makeChange(doc, context, options) } +} - /** - * Reads a LEB128-encoded unsigned integer from the current position in the - * buffer. Allows any integer that can be safely represented by JavaScript - * (up to 2^53 - 1), and throws an exception outside of that range. - */ - readUint53() { - const { low32, high32 } = this.readUint64() - if (high32 < 0 || high32 > 0x1fffff) { - throw new RangeError('number out of range') - } - return high32 * 0x100000000 + low32 +/** + * Triggers a new change request on the document `doc` without actually + * modifying its data. `options` is an object as described in the documentation + * for the `change` function. This function can be useful for acknowledging the + * receipt of some message (as it's incorported into the `deps` field of the + * change). Returns a two-element array `[doc, request]` where `doc` is the + * updated document, and `request` is the change request to send to the backend. + */ +function emptyChange(doc, options) { + if (doc[OBJECT_ID] !== '_root') { + throw new TypeError('The first argument to Automerge.emptyChange must be the document root') + } + if (typeof options === 'string') { + options = {message: options} + } + if (options !== undefined && !isObject(options)) { + throw new TypeError('Unsupported type of options') } - /** - * Reads a LEB128-encoded signed integer from the current position in the - * buffer. Allows any integer that can be safely represented by JavaScript - * (between -(2^53 - 1) and 2^53 - 1), throws an exception outside of that range. - */ - readInt53() { - const { low32, high32 } = this.readInt64() - if (high32 < -0x200000 || (high32 === -0x200000 && low32 === 0) || high32 > 0x1fffff) { - throw new RangeError('number out of range') - } - return high32 * 0x100000000 + low32 + const actorId = getActorId(doc) + if (!actorId) { + throw new Error('Actor ID must be initialized with setActorId() before making a change') } + return makeChange(doc, new Context(doc, actorId), options) +} - /** - * Reads a LEB128-encoded unsigned integer from the current position in the - * buffer. Throws an exception if the value doesn't fit in a 64-bit unsigned - * int. Returns the number in two 32-bit halves, as an object of the form - * `{high32, low32}`. - */ - readUint64() { - let low32 = 0, high32 = 0, shift = 0 - while (this.offset < this.buf.byteLength && shift <= 28) { - const nextByte = this.buf[this.offset] - low32 = (low32 | (nextByte & 0x7f) << shift) >>> 0 // right shift to interpret value as unsigned - if (shift === 28) { - high32 = (nextByte & 0x70) >>> 4 - } - shift += 7 - this.offset++ - if ((nextByte & 0x80) === 0) return { high32, low32 } - } +/** + * Applies `patch` to the document root object `doc`. This patch must come + * from the backend; it may be the result of a local change or a remote change. + * If it is the result of a local change, the `seq` field from the change + * request should be included in the patch, so that we can match them up here. + */ +function applyPatch(doc, patch, backendState = undefined) { + if (doc[OBJECT_ID] !== '_root') { + throw new TypeError('The first argument to Frontend.applyPatch must be the document root') + } + const state = copyObject(doc[STATE]) - shift = 3 - while (this.offset < this.buf.byteLength) { - const nextByte = this.buf[this.offset] - if (shift === 31 && (nextByte & 0xfe) !== 0) { // more than 10 bytes, or value > 2^64 - 1 - throw new RangeError('number out of range') - } - high32 = (high32 | (nextByte & 0x7f) << shift) >>> 0 - shift += 7 - this.offset++ - if ((nextByte & 0x80) === 0) return { high32, low32 } + if (doc[OPTIONS].backend) { + if (!backendState) { + throw new RangeError('applyPatch must be called with the updated backend state') } - throw new RangeError('buffer ended with incomplete number') + state.backendState = backendState + return applyPatchToDoc(doc, patch, state, true) } - /** - * Reads a LEB128-encoded signed integer from the current position in the - * buffer. Throws an exception if the value doesn't fit in a 64-bit signed - * int. Returns the number in two 32-bit halves, as an object of the form - * `{high32, low32}`. The `low32` half is always non-negative, and the - * sign of the `high32` half indicates the sign of the 64-bit number. - */ - readInt64() { - let low32 = 0, high32 = 0, shift = 0 - while (this.offset < this.buf.byteLength && shift <= 28) { - const nextByte = this.buf[this.offset] - low32 = (low32 | (nextByte & 0x7f) << shift) >>> 0 // right shift to interpret value as unsigned - if (shift === 28) { - high32 = (nextByte & 0x70) >>> 4 - } - shift += 7 - this.offset++ - if ((nextByte & 0x80) === 0) { - if ((nextByte & 0x40) !== 0) { // sign-extend negative integer - if (shift < 32) low32 = (low32 | (-1 << shift)) >>> 0 - high32 |= -1 << Math.max(shift - 32, 0) - } - return { high32, low32 } - } - } + let baseDoc - shift = 3 - while (this.offset < this.buf.byteLength) { - const nextByte = this.buf[this.offset] - // On the 10th byte there are only two valid values: all 7 value bits zero - // (if the value is positive) or all 7 bits one (if the value is negative) - if (shift === 31 && nextByte !== 0 && nextByte !== 0x7f) { - throw new RangeError('number out of range') - } - high32 |= (nextByte & 0x7f) << shift - shift += 7 - this.offset++ - if ((nextByte & 0x80) === 0) { - if ((nextByte & 0x40) !== 0 && shift < 32) { // sign-extend negative integer - high32 |= -1 << shift - } - return { high32, low32 } + if (state.requests.length > 0) { + baseDoc = state.requests[0].before + if (patch.actor === getActorId(doc)) { + if (state.requests[0].seq !== patch.seq) { + throw new RangeError(`Mismatched sequence number: patch ${patch.seq} does not match next request ${state.requests[0].seq}`) } + state.requests = state.requests.slice(1) + } else { + state.requests = state.requests.slice() } - throw new RangeError('buffer ended with incomplete number') + } else { + baseDoc = doc + state.requests = [] } - /** - * Extracts a subarray `length` bytes in size, starting from the current - * position in the buffer, and moves the position forward. - */ - readRawBytes(length) { - const start = this.offset - if (start + length > this.buf.byteLength) { - throw new RangeError('subarray exceeds buffer size') + let newDoc = applyPatchToDoc(baseDoc, patch, state, true) + if (state.requests.length === 0) { + return newDoc + } else { + state.requests[0] = copyObject(state.requests[0]) + state.requests[0].before = newDoc + return updateRootObject(doc, {}, state) + } +} + +/** + * Returns the Automerge object ID of the given object. + */ +function getObjectId(object) { + return object[OBJECT_ID] +} + +/** + * Returns the object with the given Automerge object ID. Note: when called + * within a change callback, the returned object is read-only (not a mutable + * proxy object). + */ +function getObjectById(doc, objectId) { + // It would be nice to return a proxied object in a change callback. + // However, that requires knowing the path from the root to the current + // object, which we don't have if we jumped straight to the object by its ID. + // If we maintained an index from object ID to parent ID we could work out the path. + if (doc[CHANGE]) { + throw new TypeError('Cannot use getObjectById in a change callback') + } + return doc[CACHE][objectId] +} + +/** + * Returns the Automerge actor ID of the given document. + */ +function getActorId(doc) { + return doc[STATE].actorId || doc[OPTIONS].actorId +} + +/** + * Sets the Automerge actor ID on the document object `doc`, returning a + * document object with updated metadata. + */ +function setActorId(doc, actorId) { + checkActorId(actorId) + const state = Object.assign({}, doc[STATE], {actorId}) + return updateRootObject(doc, {}, state) +} + +/** + * Fetches the conflicts on the property `key` of `object`, which may be any + * object in a document. If `object` is a list, then `key` must be a list + * index; if `object` is a map, then `key` must be a property name. + */ +function getConflicts(object, key) { + if (object[CONFLICTS] && object[CONFLICTS][key] && + Object.keys(object[CONFLICTS][key]).length > 1) { + return object[CONFLICTS][key] + } +} + +/** + * Returns the backend state associated with the document `doc` (only used if + * a backend implementation is passed to `init()`). + */ +function getBackendState(doc, callerName = null, argPos = 'first') { + if (doc[OBJECT_ID] !== '_root') { + // Most likely cause of passing an array here is forgetting to deconstruct the return value of + // Automerge.applyChanges(). + const extraMsg = Array.isArray(doc) ? '. Note: Automerge.applyChanges now returns an array.' : '' + if (callerName) { + throw new TypeError(`The ${argPos} argument to Automerge.${callerName} must be the document root${extraMsg}`) + } else { + throw new TypeError(`Argument is not an Automerge document root${extraMsg}`) } - this.offset += length - return this.buf.subarray(start, this.offset) } + return doc[STATE].backendState +} - /** - * Extracts `length` bytes from the buffer, starting from the current position, - * and returns the UTF-8 string decoding of those bytes. - */ - readRawString(length) { - return utf8ToString(this.readRawBytes(length)) +/** + * Given an array or text object from an Automerge document, returns an array + * containing the unique element ID of each list element/character. + */ +function getElementIds(list) { + if (list instanceof Text) { + return list.elems.map(elem => elem.elemId) + } else { + return list[ELEM_IDS] } +} - /** - * Extracts a subarray from the current position in the buffer, prefixed with - * its length in bytes (encoded as an unsigned LEB128 integer). - */ - readPrefixedBytes() { - return this.readRawBytes(this.readUint53()) +module.exports = { + init, from, change, emptyChange, applyPatch, + getObjectId, getObjectById, getActorId, setActorId, getConflicts, getLastLocalChange, + getBackendState, getElementIds, + Text, Table, Counter, Observable, Float64, Int, Uint +} + +},{"../src/common":82,"../src/uuid":83,"./apply_patch":55,"./constants":56,"./context":57,"./counter":58,"./numbers":60,"./observable":61,"./proxies":62,"./table":63,"./text":64}],60:[function(require,module,exports){ +// Convience classes to allow users to stricly specify the number type they want + +class Int { + constructor(value) { + if (!(Number.isInteger(value) && value <= Number.MAX_SAFE_INTEGER && value >= Number.MIN_SAFE_INTEGER)) { + throw new RangeError(`Value ${value} cannot be a uint`) + } + this.value = value + Object.freeze(this) } +} - /** - * Reads a UTF-8 string from the current position in the buffer, prefixed with its - * length in bytes (where the length is encoded as an unsigned LEB128 integer). - */ - readPrefixedString() { - return utf8ToString(this.readPrefixedBytes()) +class Uint { + constructor(value) { + if (!(Number.isInteger(value) && value <= Number.MAX_SAFE_INTEGER && value >= 0)) { + throw new RangeError(`Value ${value} cannot be a uint`) + } + this.value = value + Object.freeze(this) } +} - /** - * Reads a byte array from the current position in the buffer, prefixed with its - * length in bytes. Returns that byte array converted to a hexadecimal string. - */ - readHexString() { - return bytesToHexString(this.readPrefixedBytes()) +class Float64 { + constructor(value) { + if (typeof value !== 'number') { + throw new RangeError(`Value ${value} cannot be a float64`) + } + this.value = value || 0.0 + Object.freeze(this) } } +module.exports = { Int, Uint, Float64 } + +},{}],61:[function(require,module,exports){ +const { OBJECT_ID, CONFLICTS } = require('./constants') + /** - * An encoder that uses run-length encoding to compress sequences of repeated - * values. The constructor argument specifies the type of values, which may be - * either 'int', 'uint', or 'utf8'. Besides valid values of the selected - * datatype, values may also be null. - * - * The encoded buffer starts with a LEB128-encoded signed integer, the - * repetition count. The interpretation of the following values depends on this - * repetition count: - * - If this number is a positive value n, the next value in the buffer - * (encoded as the specified datatype) is repeated n times in the sequence. - * - If the repetition count is a negative value -n, then the next n values - * (encoded as the specified datatype) in the buffer are treated as a - * literal, i.e. they appear in the sequence without any further - * interpretation or repetition. - * - If the repetition count is zero, then the next value in the buffer is a - * LEB128-encoded unsigned integer indicating the number of null values - * that appear at the current position in the sequence. + * Allows an application to register a callback when a particular object in + * a document changes. * - * After one of these three has completed, the process repeats, starting again - * with a repetition count, until we reach the end of the buffer. + * NOTE: This API is experimental and may change without warning in minor releases. */ -class RLEEncoder extends Encoder { - constructor(type) { - super() - this.type = type - this.state = 'empty' - this.lastValue = undefined - this.count = 0 - this.literal = [] +class Observable { + constructor() { + this.observers = {} // map from objectId to array of observers for that object } /** - * Appends a new value to the sequence. If `repetitions` is given, the value is repeated - * `repetitions` times. + * Called by an Automerge document when `patch` is applied. `before` is the + * state of the document before the patch, and `after` is the state after + * applying it. `local` is true if the update is a result of locally calling + * `Automerge.change()`, and false otherwise. `changes` is an array of + * changes that were applied to the document (as Uint8Arrays). */ - appendValue(value, repetitions = 1) { - this._appendValue(value, repetitions) + patchCallback(patch, before, after, local, changes) { + this._objectUpdate(patch.diffs, before, after, local, changes) } /** - * Like `appendValue()`, but this method is not overridden by `DeltaEncoder`. + * Recursively walks a patch and calls the callbacks for all objects that + * appear in the patch. */ - _appendValue(value, repetitions = 1) { - if (repetitions <= 0) return - if (this.state === 'empty') { - this.state = (value === null ? 'nulls' : (repetitions === 1 ? 'loneValue' : 'repetition')) - this.lastValue = value - this.count = repetitions - } else if (this.state === 'loneValue') { - if (value === null) { - this.flush() - this.state = 'nulls' - this.count = repetitions - } else if (value === this.lastValue) { - this.state = 'repetition' - this.count = 1 + repetitions - } else if (repetitions > 1) { - this.flush() - this.state = 'repetition' - this.count = repetitions - this.lastValue = value - } else { - this.state = 'literal' - this.literal = [this.lastValue] - this.lastValue = value - } - } else if (this.state === 'repetition') { - if (value === null) { - this.flush() - this.state = 'nulls' - this.count = repetitions - } else if (value === this.lastValue) { - this.count += repetitions - } else if (repetitions > 1) { - this.flush() - this.state = 'repetition' - this.count = repetitions - this.lastValue = value - } else { - this.flush() - this.state = 'loneValue' - this.lastValue = value - } - } else if (this.state === 'literal') { - if (value === null) { - this.literal.push(this.lastValue) - this.flush() - this.state = 'nulls' - this.count = repetitions - } else if (value === this.lastValue) { - this.flush() - this.state = 'repetition' - this.count = 1 + repetitions - } else if (repetitions > 1) { - this.literal.push(this.lastValue) - this.flush() - this.state = 'repetition' - this.count = repetitions - this.lastValue = value - } else { - this.literal.push(this.lastValue) - this.lastValue = value - } - } else if (this.state === 'nulls') { - if (value === null) { - this.count += repetitions - } else if (repetitions > 1) { - this.flush() - this.state = 'repetition' - this.count = repetitions - this.lastValue = value - } else { - this.flush() - this.state = 'loneValue' - this.lastValue = value + _objectUpdate(diff, before, after, local, changes) { + if (!diff.objectId) return + if (this.observers[diff.objectId]) { + for (let callback of this.observers[diff.objectId]) { + callback(diff, before, after, local, changes) } } - } - /** - * Copies values from the RLEDecoder `decoder` into this encoder. The `options` object may - * contain the following keys: - * - `count`: The number of values to copy. If not specified, copies all remaining values. - * - `sumValues`: If true, the function computes the sum of all numeric values as they are - * copied (null values are counted as zero), and returns that number. - * - `sumShift`: If set, values are shifted right by `sumShift` bits before adding to the sum. - * - * Returns an object of the form `{nonNullValues, sum}` where `nonNullValues` is the number of - * non-null values copied, and `sum` is the sum (only if the `sumValues` option is set). - */ - copyFrom(decoder, options = {}) { - const { count, sumValues, sumShift } = options - if (!(decoder instanceof RLEDecoder) || (decoder.type !== this.type)) { - throw new TypeError('incompatible type of decoder') - } - let remaining = (typeof count === 'number' ? count : Number.MAX_SAFE_INTEGER) - let nonNullValues = 0, sum = 0 - if (count && remaining > 0 && decoder.done) throw new RangeError(`cannot copy ${count} values`) - if (remaining === 0 || decoder.done) return sumValues ? {nonNullValues, sum} : {nonNullValues} - - // Copy a value so that we have a well-defined starting state. NB: when super.copyFrom() is - // called by the DeltaEncoder subclass, the following calls to readValue() and appendValue() - // refer to the overridden methods, while later readRecord(), readRawValue() and _appendValue() - // calls refer to the non-overridden RLEDecoder/RLEEncoder methods. - let firstValue = decoder.readValue() - if (firstValue === null) { - const numNulls = Math.min(decoder.count + 1, remaining) - remaining -= numNulls - decoder.count -= numNulls - 1 - this.appendValue(null, numNulls) - if (count && remaining > 0 && decoder.done) throw new RangeError(`cannot copy ${count} values`) - if (remaining === 0 || decoder.done) return sumValues ? {nonNullValues, sum} : {nonNullValues} - firstValue = decoder.readValue() - if (firstValue === null) throw new RangeError('null run must be followed by non-null value') - } - this.appendValue(firstValue) - remaining-- - nonNullValues++ - if (sumValues) sum += (sumShift ? (firstValue >>> sumShift) : firstValue) - if (count && remaining > 0 && decoder.done) throw new RangeError(`cannot copy ${count} values`) - if (remaining === 0 || decoder.done) return sumValues ? {nonNullValues, sum} : {nonNullValues} - - // Copy data at the record level without expanding repetitions - let firstRun = (decoder.count > 0) - while (remaining > 0 && !decoder.done) { - if (!firstRun) decoder.readRecord() - const numValues = Math.min(decoder.count, remaining) - decoder.count -= numValues + if (diff.type === 'map' && diff.props) { + for (const propName of Object.keys(diff.props)) { + for (const opId of Object.keys(diff.props[propName])) { + this._objectUpdate(diff.props[propName][opId], + before && before[CONFLICTS] && before[CONFLICTS][propName] && before[CONFLICTS][propName][opId], + after && after[CONFLICTS] && after[CONFLICTS][propName] && after[CONFLICTS][propName][opId], + local, changes) + } + } - if (decoder.state === 'literal') { - nonNullValues += numValues - for (let i = 0; i < numValues; i++) { - if (decoder.done) throw new RangeError('incomplete literal') - const value = decoder.readRawValue() - if (value === decoder.lastValue) throw new RangeError('Repetition of values is not allowed in literal') - decoder.lastValue = value - this._appendValue(value) - if (sumValues) sum += (sumShift ? (value >>> sumShift) : value) + } else if (diff.type === 'table' && diff.props) { + for (const rowId of Object.keys(diff.props)) { + for (const opId of Object.keys(diff.props[rowId])) { + this._objectUpdate(diff.props[rowId][opId], + before && before.byId(rowId), + after && after.byId(rowId), + local, changes) } - } else if (decoder.state === 'repetition') { - nonNullValues += numValues - if (sumValues) sum += numValues * (sumShift ? (decoder.lastValue >>> sumShift) : decoder.lastValue) - const value = decoder.lastValue - this._appendValue(value) - if (numValues > 1) { - this._appendValue(value) - if (this.state !== 'repetition') throw new RangeError(`Unexpected state ${this.state}`) - this.count += numValues - 2 + } + + } else if (diff.type === 'list' && diff.edits) { + let offset = 0 + for (const edit of diff.edits) { + if (edit.action === 'insert') { + offset -= 1 + this._objectUpdate(edit.value, undefined, + after && after[CONFLICTS] && after[CONFLICTS][edit.index] && after[CONFLICTS][edit.index][edit.elemId], + local, changes) + } else if (edit.action === 'multi-insert') { + offset -= edit.values.length + } else if (edit.action === 'update') { + this._objectUpdate(edit.value, + before && before[CONFLICTS] && before[CONFLICTS][edit.index + offset] && + before[CONFLICTS][edit.index + offset][edit.opId], + after && after[CONFLICTS] && after[CONFLICTS][edit.index] && after[CONFLICTS][edit.index][edit.opId], + local, changes) + } else if (edit.action === 'remove') { + offset += edit.count } - } else if (decoder.state === 'nulls') { - this._appendValue(null) - if (this.state !== 'nulls') throw new RangeError(`Unexpected state ${this.state}`) - this.count += numValues - 1 } - firstRun = false - remaining -= numValues + } else if (diff.type === 'text' && diff.edits) { + let offset = 0 + for (const edit of diff.edits) { + if (edit.action === 'insert') { + offset -= 1 + this._objectUpdate(edit.value, undefined, after && after.get(edit.index), local, changes) + } else if (edit.action === 'multi-insert') { + offset -= edit.values.length + } else if (edit.action === 'update') { + this._objectUpdate(edit.value, + before && before.get(edit.index + offset), + after && after.get(edit.index), + local, changes) + } else if (edit.action === 'remove') { + offset += edit.count + } + } } - if (count && remaining > 0 && decoder.done) throw new RangeError(`cannot copy ${count} values`) - return sumValues ? {nonNullValues, sum} : {nonNullValues} } /** - * Private method, do not call from outside the class. + * Call this to register a callback that will get called whenever a particular + * object in a document changes. The callback is passed five arguments: the + * part of the patch describing the update to that object, the old state of + * the object, the new state of the object, a boolean that is true if the + * change is the result of calling `Automerge.change()` locally, and the array + * of binary changes applied to the document. */ - flush() { - if (this.state === 'loneValue') { - this.appendInt32(-1) - this.appendRawValue(this.lastValue) - } else if (this.state === 'repetition') { - this.appendInt53(this.count) - this.appendRawValue(this.lastValue) - } else if (this.state === 'literal') { - this.appendInt53(-this.literal.length) - for (let v of this.literal) this.appendRawValue(v) - } else if (this.state === 'nulls') { - this.appendInt32(0) - this.appendUint53(this.count) - } - this.state = 'empty' + observe(object, callback) { + const objectId = object[OBJECT_ID] + if (!objectId) throw new TypeError('The observed object must be part of an Automerge document') + if (!this.observers[objectId]) this.observers[objectId] = [] + this.observers[objectId].push(callback) } +} - /** - * Private method, do not call from outside the class. - */ - appendRawValue(value) { - if (this.type === 'int') { - this.appendInt53(value) - } else if (this.type === 'uint') { - this.appendUint53(value) - } else if (this.type === 'utf8') { - this.appendPrefixedString(value) - } else { - throw new RangeError(`Unknown RLEEncoder datatype: ${this.type}`) - } - } +module.exports = { Observable } - /** - * Flushes any unwritten data to the buffer. Call this before reading from - * the buffer constructed by this Encoder. - */ - finish() { - if (this.state === 'literal') this.literal.push(this.lastValue) - // Don't write anything if the only values we have seen are nulls - if (this.state !== 'nulls' || this.offset > 0) this.flush() - } -} +},{"./constants":56}],62:[function(require,module,exports){ +const { OBJECT_ID, CHANGE, STATE } = require('./constants') +const { createArrayOfNulls } = require('../src/common') +const { Text } = require('./text') +const { Table } = require('./table') -/** - * Counterpart to RLEEncoder: reads values from an RLE-compressed sequence, - * returning nulls and repeated values as required. - */ -class RLEDecoder extends Decoder { - constructor(type, buffer) { - super(buffer) - this.type = type - this.lastValue = undefined - this.count = 0 - this.state = undefined +function parseListIndex(key) { + if (typeof key === 'string' && /^[0-9]+$/.test(key)) key = parseInt(key, 10) + if (typeof key !== 'number') { + throw new TypeError('A list index must be a number, but you passed ' + JSON.stringify(key)) } - - /** - * Returns false if there is still data to be read at the current decoding - * position, and true if we are at the end of the buffer. - */ - get done() { - return (this.count === 0) && (this.offset === this.buf.byteLength) + if (key < 0 || isNaN(key) || key === Infinity || key === -Infinity) { + throw new RangeError('A list index must be positive, but you passed ' + key) } + return key +} - /** - * Resets the cursor position, so that the next read goes back to the - * beginning of the buffer. - */ - reset() { - this.offset = 0 - this.lastValue = undefined - this.count = 0 - this.state = undefined - } +function listMethods(context, listId, path) { + const methods = { + deleteAt(index, numDelete) { + context.splice(path, parseListIndex(index), numDelete || 1, []) + return this + }, - /** - * Returns the next value (or null) in the sequence. - */ - readValue() { - if (this.done) return null - if (this.count === 0) this.readRecord() - this.count -= 1 - if (this.state === 'literal') { - const value = this.readRawValue() - if (value === this.lastValue) throw new RangeError('Repetition of values is not allowed in literal') - this.lastValue = value - return value - } else { - return this.lastValue - } - } + fill(value, start, end) { + let list = context.getObject(listId) + for (let index = parseListIndex(start || 0); index < parseListIndex(end || list.length); index++) { + context.setListIndex(path, index, value) + } + return this + }, - /** - * Discards the next `numSkip` values in the sequence. - */ - skipValues(numSkip) { - while (numSkip > 0 && !this.done) { - if (this.count === 0) { - this.count = this.readInt53() - if (this.count > 0) { - this.lastValue = (this.count <= numSkip) ? this.skipRawValues(1) : this.readRawValue() - this.state = 'repetition' - } else if (this.count < 0) { - this.count = -this.count - this.state = 'literal' - } else { // this.count == 0 - this.count = this.readUint53() - this.lastValue = null - this.state = 'nulls' + indexOf(o, start = 0) { + const id = o[OBJECT_ID] + if (id) { + const list = context.getObject(listId) + for (let index = start; index < list.length; index++) { + if (list[index][OBJECT_ID] === id) { + return index + } } + return -1 + } else { + return context.getObject(listId).indexOf(o, start) } + }, - const consume = Math.min(numSkip, this.count) - if (this.state === 'literal') this.skipRawValues(consume) - numSkip -= consume - this.count -= consume - } - } + insertAt(index, ...values) { + context.splice(path, parseListIndex(index), 0, values) + return this + }, - /** - * Private method, do not call from outside the class. - * Reads a repetition count from the buffer and sets up the state appropriately. - */ - readRecord() { - this.count = this.readInt53() - if (this.count > 1) { - const value = this.readRawValue() - if ((this.state === 'repetition' || this.state === 'literal') && this.lastValue === value) { - throw new RangeError('Successive repetitions with the same value are not allowed') + pop() { + let list = context.getObject(listId) + if (list.length == 0) return + const last = context.getObjectField(path, listId, list.length - 1) + context.splice(path, list.length - 1, 1, []) + return last + }, + + push(...values) { + let list = context.getObject(listId) + context.splice(path, list.length, 0, values) + // need to getObject() again because the list object above may be immutable + return context.getObject(listId).length + }, + + shift() { + let list = context.getObject(listId) + if (list.length == 0) return + const first = context.getObjectField(path, listId, 0) + context.splice(path, 0, 1, []) + return first + }, + + splice(start, deleteCount, ...values) { + let list = context.getObject(listId) + start = parseListIndex(start) + if (deleteCount === undefined || deleteCount > list.length - start) { + deleteCount = list.length - start } - this.state = 'repetition' - this.lastValue = value - } else if (this.count === 1) { - throw new RangeError('Repetition count of 1 is not allowed, use a literal instead') - } else if (this.count < 0) { - this.count = -this.count - if (this.state === 'literal') throw new RangeError('Successive literals are not allowed') - this.state = 'literal' - } else { // this.count == 0 - if (this.state === 'nulls') throw new RangeError('Successive null runs are not allowed') - this.count = this.readUint53() - if (this.count === 0) throw new RangeError('Zero-length null runs are not allowed') - this.lastValue = null - this.state = 'nulls' + const deleted = [] + for (let n = 0; n < deleteCount; n++) { + deleted.push(context.getObjectField(path, listId, start + n)) + } + context.splice(path, start, deleteCount, values) + return deleted + }, + + unshift(...values) { + context.splice(path, 0, 0, values) + return context.getObject(listId).length } } - /** - * Private method, do not call from outside the class. - * Reads one value of the datatype configured on construction. - */ - readRawValue() { - if (this.type === 'int') { - return this.readInt53() - } else if (this.type === 'uint') { - return this.readUint53() - } else if (this.type === 'utf8') { - return this.readPrefixedString() - } else { - throw new RangeError(`Unknown RLEDecoder datatype: ${this.type}`) - } + for (let iterator of ['entries', 'keys', 'values']) { + let list = context.getObject(listId) + methods[iterator] = () => list[iterator]() } - /** - * Private method, do not call from outside the class. - * Skips over `num` values of the datatype configured on construction. - */ - skipRawValues(num) { - if (this.type === 'utf8') { - for (let i = 0; i < num; i++) this.skip(this.readUint53()) - } else { - while (num > 0 && this.offset < this.buf.byteLength) { - if ((this.buf[this.offset] & 0x80) === 0) num-- - this.offset++ - } - if (num > 0) throw new RangeError('cannot skip beyond end of buffer') + // Read-only methods that can delegate to the JavaScript built-in implementations + for (let method of ['concat', 'every', 'filter', 'find', 'findIndex', 'forEach', 'includes', + 'join', 'lastIndexOf', 'map', 'reduce', 'reduceRight', + 'slice', 'some', 'toLocaleString', 'toString']) { + methods[method] = (...args) => { + const list = context.getObject(listId) + .map((item, index) => context.getObjectField(path, listId, index)) + return list[method](...args) } } + + return methods } -/** - * A variant of RLEEncoder: rather than storing the actual values passed to - * appendValue(), this version stores only the first value, and for all - * subsequent values it stores the difference to the previous value. This - * encoding is good when values tend to come in sequentially incrementing runs, - * because the delta between successive values is 1, and repeated values of 1 - * are easily compressed with run-length encoding. - * - * Null values are also allowed, as with RLEEncoder. - */ -class DeltaEncoder extends RLEEncoder { - constructor() { - super('int') - this.absoluteValue = 0 - } +const MapHandler = { + get (target, key) { + const { context, objectId, path } = target + if (key === OBJECT_ID) return objectId + if (key === CHANGE) return context + if (key === STATE) return {actorId: context.actorId} + return context.getObjectField(path, objectId, key) + }, - /** - * Appends a new integer value to the sequence. If `repetitions` is given, the value is repeated - * `repetitions` times. - */ - appendValue(value, repetitions = 1) { - if (repetitions <= 0) return - if (typeof value === 'number') { - super.appendValue(value - this.absoluteValue, 1) - this.absoluteValue = value - if (repetitions > 1) super.appendValue(0, repetitions - 1) - } else { - super.appendValue(value, repetitions) + set (target, key, value) { + const { context, path, readonly } = target + if (Array.isArray(readonly) && readonly.indexOf(key) >= 0) { + throw new RangeError(`Object property "${key}" cannot be modified`) } - } + context.setMapKey(path, key, value) + return true + }, - /** - * Copies values from the DeltaDecoder `decoder` into this encoder. The `options` object may - * contain the key `count`, indicating the number of values to copy. If not specified, copies - * all remaining values in the decoder. - */ - copyFrom(decoder, options = {}) { - if (options.sumValues) { - throw new RangeError('unsupported options for DeltaEncoder.copyFrom()') - } - if (!(decoder instanceof DeltaDecoder)) { - throw new TypeError('incompatible type of decoder') + deleteProperty (target, key) { + const { context, path, readonly } = target + if (Array.isArray(readonly) && readonly.indexOf(key) >= 0) { + throw new RangeError(`Object property "${key}" cannot be modified`) } + context.deleteMapKey(path, key) + return true + }, - let remaining = options.count - if (remaining > 0 && decoder.done) throw new RangeError(`cannot copy ${remaining} values`) - if (remaining === 0 || decoder.done) return - - // Copy any null values, and the first non-null value, so that appendValue() computes the - // difference between the encoder's last value and the decoder's first (absolute) value. - let value = decoder.readValue(), nulls = 0 - this.appendValue(value) - if (value === null) { - nulls = decoder.count + 1 - if (remaining !== undefined && remaining < nulls) nulls = remaining - decoder.count -= nulls - 1 - this.count += nulls - 1 - if (remaining > nulls && decoder.done) throw new RangeError(`cannot copy ${remaining} values`) - if (remaining === nulls || decoder.done) return + has (target, key) { + const { context, objectId } = target + return [OBJECT_ID, CHANGE].includes(key) || (key in context.getObject(objectId)) + }, - // The next value read is certain to be non-null because we're not at the end of the decoder, - // and a run of nulls must be followed by a run of non-nulls. - if (decoder.count === 0) this.appendValue(decoder.readValue()) + getOwnPropertyDescriptor (target, key) { + const { context, objectId } = target + const object = context.getObject(objectId) + if (key in object) { + return { + configurable: true, enumerable: true, + value: context.getObjectField(objectId, key) + } } + }, - // Once we have the first value, the subsequent relative values can be copied verbatim without - // any further processing. Note that the first value copied by super.copyFrom() is an absolute - // value, while subsequent values are relative. Thus, the sum of all of the (non-null) copied - // values must equal the absolute value of the final element copied. - if (remaining !== undefined) remaining -= nulls + 1 - const { nonNullValues, sum } = super.copyFrom(decoder, {count: remaining, sumValues: true}) - if (nonNullValues > 0) { - this.absoluteValue = sum - decoder.absoluteValue = sum - } + ownKeys (target) { + const { context, objectId } = target + return Object.keys(context.getObject(objectId)) } } -/** - * Counterpart to DeltaEncoder: reads values from a delta-compressed sequence of - * numbers (may include null values). - */ -class DeltaDecoder extends RLEDecoder { - constructor(buffer) { - super('int', buffer) - this.absoluteValue = 0 - } - - /** - * Resets the cursor position, so that the next read goes back to the - * beginning of the buffer. - */ - reset() { - this.offset = 0 - this.lastValue = undefined - this.count = 0 - this.state = undefined - this.absoluteValue = 0 - } +const ListHandler = { + get (target, key) { + const [context, objectId, path] = target + if (key === Symbol.iterator) return context.getObject(objectId)[Symbol.iterator] + if (key === OBJECT_ID) return objectId + if (key === CHANGE) return context + if (key === 'length') return context.getObject(objectId).length + if (typeof key === 'string' && /^[0-9]+$/.test(key)) { + return context.getObjectField(path, objectId, parseListIndex(key)) + } + return listMethods(context, objectId, path)[key] + }, - /** - * Returns the next integer (or null) value in the sequence. - */ - readValue() { - const value = super.readValue() - if (value === null) return null - this.absoluteValue += value - return this.absoluteValue - } + set (target, key, value) { + const [context, objectId, path] = target + if (key === 'length') { + if (typeof value !== 'number') { + throw new RangeError("Invalid array length") + } + const length = context.getObject(objectId).length + if (length > value) { + context.splice(path, value, length - value, []) + } else { + context.splice(path, length, 0, createArrayOfNulls(value - length)) + } + } else { + context.setListIndex(path, parseListIndex(key), value) + } + return true + }, - /** - * Discards the next `numSkip` values in the sequence. - */ - skipValues(numSkip) { - while (numSkip > 0 && !this.done) { - if (this.count === 0) this.readRecord() - const consume = Math.min(numSkip, this.count) - if (this.state === 'literal') { - for (let i = 0; i < consume; i++) { - this.lastValue = this.readRawValue() - this.absoluteValue += this.lastValue - } - } else if (this.state === 'repetition') { - this.absoluteValue += consume * this.lastValue + deleteProperty (target, key) { + const [context, /* objectId */, path] = target + context.splice(path, parseListIndex(key), 1, []) + return true + }, + + has (target, key) { + const [context, objectId, /* path */] = target + if (typeof key === 'string' && /^[0-9]+$/.test(key)) { + return parseListIndex(key) < context.getObject(objectId).length + } + return ['length', OBJECT_ID, CHANGE].includes(key) + }, + + getOwnPropertyDescriptor (target, key) { + const [context, objectId, /* path */] = target + const object = context.getObject(objectId) + + if (key === 'length') return {writable: true, value: object.length} + if (key === OBJECT_ID) return {configurable: false, enumerable: false, value: objectId} + + if (typeof key === 'string' && /^[0-9]+$/.test(key)) { + const index = parseListIndex(key) + if (index < object.length) return { + configurable: true, enumerable: true, + value: context.getObjectField(objectId, index) } - numSkip -= consume - this.count -= consume } + }, + + ownKeys (target) { + const [context, objectId, /* path */] = target + const object = context.getObject(objectId) + let keys = ['length'] + for (let key of Object.keys(object)) keys.push(key) + return keys } } +function mapProxy(context, objectId, path, readonly) { + return new Proxy({context, objectId, path, readonly}, MapHandler) +} + +function listProxy(context, objectId, path) { + return new Proxy([context, objectId, path], ListHandler) +} + /** - * Encodes a sequence of boolean values by mapping it to a sequence of integers: - * the number of false values, followed by the number of true values, followed - * by the number of false values, and so on. Each number is encoded as a LEB128 - * unsigned integer. This encoding is a bit like RLEEncoder, except that we - * only encode the repetition count but not the actual value, since the values - * just alternate between false and true (starting with false). + * Instantiates a proxy object for the given `objectId`. + * This function is added as a method to the context object by rootObjectProxy(). + * When it is called, `this` is the context object. + * `readonly` is a list of map property names that cannot be modified. */ -class BooleanEncoder extends Encoder { - constructor() { - super() - this.lastValue = false - this.count = 0 +function instantiateProxy(path, objectId, readonly) { + const object = this.getObject(objectId) + if (Array.isArray(object)) { + return listProxy(this, objectId, path) + } else if (object instanceof Text || object instanceof Table) { + return object.getWriteable(this, path) + } else { + return mapProxy(this, objectId, path, readonly) } +} - /** - * Appends a new value to the sequence. If `repetitions` is given, the value is repeated - * `repetitions` times. - */ - appendValue(value, repetitions = 1) { - if (value !== false && value !== true) { - throw new RangeError(`Unsupported value for BooleanEncoder: ${value}`) - } - if (repetitions <= 0) return - if (this.lastValue === value) { - this.count += repetitions +function rootObjectProxy(context) { + context.instantiateObject = instantiateProxy + return mapProxy(context, '_root', []) +} + +module.exports = { rootObjectProxy } + +},{"../src/common":82,"./constants":56,"./table":63,"./text":64}],63:[function(require,module,exports){ +const { OBJECT_ID, CONFLICTS } = require('./constants') +const { isObject, copyObject } = require('../src/common') + +function compareRows(properties, row1, row2) { + for (let prop of properties) { + if (row1[prop] === row2[prop]) continue + + if (typeof row1[prop] === 'number' && typeof row2[prop] === 'number') { + return row1[prop] - row2[prop] } else { - this.appendUint53(this.count) - this.lastValue = value - this.count = repetitions + const prop1 = '' + row1[prop], prop2 = '' + row2[prop] + if (prop1 === prop2) continue + if (prop1 < prop2) return -1; else return +1 } } + return 0 +} + +/** + * A relational-style unordered collection of records (rows). Each row is an + * object that maps column names to values. The set of rows is represented by + * a map from UUID to row object. + */ +class Table { /** - * Copies values from the BooleanDecoder `decoder` into this encoder. The `options` object may - * contain the key `count`, indicating the number of values to copy. If not specified, copies - * all remaining values in the decoder. + * This constructor is used by application code when creating a new Table + * object within a change callback. */ - copyFrom(decoder, options = {}) { - if (!(decoder instanceof BooleanDecoder)) { - throw new TypeError('incompatible type of decoder') - } - - const { count } = options - let remaining = (typeof count === 'number' ? count : Number.MAX_SAFE_INTEGER) - if (count && remaining > 0 && decoder.done) throw new RangeError(`cannot copy ${count} values`) - if (remaining === 0 || decoder.done) return - - // Copy one value to bring decoder and encoder state into sync, then finish that value's repetitions - this.appendValue(decoder.readValue()) - remaining-- - const firstCopy = Math.min(decoder.count, remaining) - this.count += firstCopy - decoder.count -= firstCopy - remaining -= firstCopy - - while (remaining > 0 && !decoder.done) { - decoder.count = decoder.readUint53() - if (decoder.count === 0) throw new RangeError('Zero-length runs are not allowed') - decoder.lastValue = !decoder.lastValue - this.appendUint53(this.count) + constructor() { + this.entries = Object.freeze({}) + this.opIds = Object.freeze({}) + Object.freeze(this) + } - const numCopied = Math.min(decoder.count, remaining) - this.count = numCopied - this.lastValue = decoder.lastValue - decoder.count -= numCopied - remaining -= numCopied - } + /** + * Looks up a row in the table by its unique ID. + */ + byId(id) { + return this.entries[id] + } - if (count && remaining > 0 && decoder.done) throw new RangeError(`cannot copy ${count} values`) + /** + * Returns an array containing the unique IDs of all rows in the table, in no + * particular order. + */ + get ids() { + return Object.keys(this.entries).filter(key => { + const entry = this.entries[key] + return isObject(entry) && entry.id === key + }) } /** - * Flushes any unwritten data to the buffer. Call this before reading from - * the buffer constructed by this Encoder. + * Returns the number of rows in the table. */ - finish() { - if (this.count > 0) { - this.appendUint53(this.count) - this.count = 0 - } + get count() { + return this.ids.length } -} -/** - * Counterpart to BooleanEncoder: reads boolean values from a runlength-encoded - * sequence. - */ -class BooleanDecoder extends Decoder { - constructor(buffer) { - super(buffer) - this.lastValue = true // is negated the first time we read a count - this.firstRun = true - this.count = 0 + /** + * Returns an array containing all of the rows in the table, in no particular + * order. + */ + get rows() { + return this.ids.map(id => this.byId(id)) } /** - * Returns false if there is still data to be read at the current decoding - * position, and true if we are at the end of the buffer. + * The standard JavaScript `filter()` method, which passes each row to the + * callback function and returns all rows for which the it returns true. */ - get done() { - return (this.count === 0) && (this.offset === this.buf.byteLength) + filter(callback, thisArg) { + return this.rows.filter(callback, thisArg) } /** - * Resets the cursor position, so that the next read goes back to the - * beginning of the buffer. + * The standard JavaScript `find()` method, which passes each row to the + * callback function and returns the first row for which it returns true. */ - reset() { - this.offset = 0 - this.lastValue = true - this.firstRun = true - this.count = 0 + find(callback, thisArg) { + return this.rows.find(callback, thisArg) } /** - * Returns the next value in the sequence. + * The standard JavaScript `map()` method, which passes each row to the + * callback function and returns a list of its return values. */ - readValue() { - if (this.done) return false - while (this.count === 0) { - this.count = this.readUint53() - this.lastValue = !this.lastValue - if (this.count === 0 && !this.firstRun) { - throw new RangeError('Zero-length runs are not allowed') - } - this.firstRun = false + map(callback, thisArg) { + return this.rows.map(callback, thisArg) + } + + /** + * Returns the list of rows, sorted by one of the following: + * - If a function argument is given, it compares rows as per + * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#Description + * - If a string argument is given, it is interpreted as a column name and + * rows are sorted according to that column. + * - If an array of strings is given, it is interpreted as a list of column + * names, and rows are sorted lexicographically by those columns. + * - If no argument is given, it sorts by row ID by default. + */ + sort(arg) { + if (typeof arg === 'function') { + return this.rows.sort(arg) + } else if (typeof arg === 'string') { + return this.rows.sort((row1, row2) => compareRows([arg], row1, row2)) + } else if (Array.isArray(arg)) { + return this.rows.sort((row1, row2) => compareRows(arg, row1, row2)) + } else if (arg === undefined) { + return this.rows.sort((row1, row2) => compareRows(['id'], row1, row2)) + } else { + throw new TypeError(`Unsupported sorting argument: ${arg}`) } - this.count -= 1 - return this.lastValue } /** - * Discards the next `numSkip` values in the sequence. + * When iterating over a table, you get all rows in the table, in no + * particular order. */ - skipValues(numSkip) { - while (numSkip > 0 && !this.done) { - if (this.count === 0) { - this.count = this.readUint53() - this.lastValue = !this.lastValue - if (this.count === 0) throw new RangeError('Zero-length runs are not allowed') - } - if (this.count < numSkip) { - numSkip -= this.count - this.count = 0 - } else { - this.count -= numSkip - numSkip = 0 + [Symbol.iterator] () { + let rows = this.rows, index = -1 + return { + next () { + index += 1 + if (index < rows.length) { + return {done: false, value: rows[index]} + } else { + return {done: true} + } } } } -} - -module.exports = { - stringToUtf8, utf8ToString, hexStringToBytes, bytesToHexString, - Encoder, Decoder, RLEEncoder, RLEDecoder, DeltaEncoder, DeltaDecoder, BooleanEncoder, BooleanDecoder -} -},{}],51:[function(require,module,exports){ -const { init, clone, free, applyChanges, applyLocalChange, save, load, loadChanges, getPatch, getHeads, getAllChanges, getChanges, getChangesAdded, getChangeByHash, getMissingDeps } = require("./backend") -const { receiveSyncMessage, generateSyncMessage, encodeSyncMessage, decodeSyncMessage, encodeSyncState, decodeSyncState, initSyncState } = require('./sync') + /** + * Returns a shallow clone of this object. This clone is used while applying + * a patch to the table, and `freeze()` is called on it when we have finished + * applying the patch. + */ + _clone() { + if (!this[OBJECT_ID]) { + throw new RangeError('clone() requires the objectId to be set') + } + return instantiateTable(this[OBJECT_ID], copyObject(this.entries), copyObject(this.opIds)) + } -module.exports = { - init, clone, free, applyChanges, applyLocalChange, save, load, loadChanges, getPatch, - getHeads, getAllChanges, getChanges, getChangesAdded, getChangeByHash, getMissingDeps, - receiveSyncMessage, generateSyncMessage, encodeSyncMessage, decodeSyncMessage, encodeSyncState, decodeSyncState, initSyncState -} + /** + * Sets the entry with key `id` to `value`. `opId` is the ID of the operation + * performing this assignment. This method is for internal use only; it is + * not part of the public API of Automerge.Table. + */ + _set(id, value, opId) { + if (Object.isFrozen(this.entries)) { + throw new Error('A table can only be modified in a change function') + } + if (isObject(value) && !Array.isArray(value)) { + Object.defineProperty(value, 'id', {value: id, enumerable: true}) + } + this.entries[id] = value + this.opIds[id] = opId + } -},{"./backend":48,"./sync":53}],52:[function(require,module,exports){ -const { parseOpId, copyObject } = require('../src/common') -const { COLUMN_TYPE, VALUE_TYPE, ACTIONS, OBJECT_TYPE, DOC_OPS_COLUMNS, CHANGE_COLUMNS, DOCUMENT_COLUMNS, - encoderByColumnId, decoderByColumnId, makeDecoders, decodeValue, - encodeChange, decodeChangeColumns, decodeChangeMeta, decodeChanges, decodeDocumentHeader, encodeDocumentHeader } = require('./columnar') + /** + * Removes the row with unique ID `id` from the table. + */ + remove(id) { + if (Object.isFrozen(this.entries)) { + throw new Error('A table can only be modified in a change function') + } + delete this.entries[id] + delete this.opIds[id] + } -const MAX_BLOCK_SIZE = 600 // operations -const BLOOM_BITS_PER_ENTRY = 10, BLOOM_NUM_PROBES = 7 // 1% false positive rate -const BLOOM_FILTER_SIZE = Math.floor(BLOOM_BITS_PER_ENTRY * MAX_BLOCK_SIZE / 8) // bytes + /** + * Makes this object immutable. This is called after a change has been made. + */ + _freeze() { + Object.freeze(this.entries) + Object.freeze(this.opIds) + Object.freeze(this) + } -const objActorIdx = 0, objCtrIdx = 1, keyActorIdx = 2, keyCtrIdx = 3, keyStrIdx = 4, - idActorIdx = 5, idCtrIdx = 6, insertIdx = 7, actionIdx = 8, valLenIdx = 9, valRawIdx = 10, - predNumIdx = 13, predActorIdx = 14, predCtrIdx = 15, succNumIdx = 13, succActorIdx = 14, succCtrIdx = 15 + /** + * Returns a writeable instance of this table. This instance is returned when + * the table is accessed within a change callback. `context` is the proxy + * context that keeps track of the mutations. + */ + getWriteable(context, path) { + if (!this[OBJECT_ID]) { + throw new RangeError('getWriteable() requires the objectId to be set') + } -const PRED_COLUMN_IDS = CHANGE_COLUMNS - .filter(column => ['predNum', 'predActor', 'predCtr'].includes(column.columnName)) - .map(column => column.columnId) + const instance = Object.create(WriteableTable.prototype) + instance[OBJECT_ID] = this[OBJECT_ID] + instance.context = context + instance.entries = this.entries + instance.opIds = this.opIds + instance.path = path + return instance + } -/** - * Updates `objectTree`, which is a tree of nested objects, so that afterwards - * `objectTree[path[0]][path[1]][...] === value`. Only the root object is mutated, whereas any - * nested objects are copied before updating. This means that once the root object has been - * shallow-copied, this function can be used to update it without mutating the previous version. - */ -function deepCopyUpdate(objectTree, path, value) { - if (path.length === 1) { - objectTree[path[0]] = value - } else { - let child = Object.assign({}, objectTree[path[0]]) - deepCopyUpdate(child, path.slice(1), value) - objectTree[path[0]] = child + /** + * Returns an object containing the table entries, indexed by objectID, + * for serializing an Automerge document to JSON. + */ + toJSON() { + const rows = {} + for (let id of this.ids) rows[id] = this.byId(id) + return rows } } /** - * Scans a block of document operations, encoded as columns `docCols`, to find the position at which - * an operation (or sequence of operations) `ops` should be applied. `actorIds` is the array that - * maps actor numbers to hexadecimal actor IDs. `resumeInsertion` is true if we're performing a list - * insertion and we already found the reference element in a previous block, but we reached the end - * of that previous block while scanning for the actual insertion position, and so we're continuing - * the scan in a subsequent block. - * - * Returns an object with keys: - * - `found`: false if we were scanning for a reference element in a list but couldn't find it; - * true otherwise. - * - `skipCount`: the number of operations, counted from the start of the block, after which the - * new operations should be inserted or applied. - * - `visibleCount`: if modifying a list object, the number of visible (i.e. non-deleted) list - * elements that precede the position where the new operations should be applied. + * An instance of this class is used when a table is accessed within a change + * callback. */ -function seekWithinBlock(ops, docCols, actorIds, resumeInsertion) { - for (let col of docCols) col.decoder.reset() - const { objActor, objCtr, keyActor, keyCtr, keyStr, idActor, idCtr, insert } = ops - const [objActorD, objCtrD, /* keyActorD */, /* keyCtrD */, keyStrD, idActorD, idCtrD, insertD, actionD, - /* valLenD */, /* valRawD */, /* chldActorD */, /* chldCtrD */, succNumD] = docCols.map(col => col.decoder) - let skipCount = 0, visibleCount = 0, elemVisible = false, nextObjActor = null, nextObjCtr = null - let nextIdActor = null, nextIdCtr = null, nextKeyStr = null, nextInsert = null, nextSuccNum = 0 - - // Seek to the beginning of the object being updated - if (objCtr !== null && !resumeInsertion) { - while (!objCtrD.done || !objActorD.done || !actionD.done) { - nextObjCtr = objCtrD.readValue() - nextObjActor = actorIds[objActorD.readValue()] - actionD.skipValues(1) - if (nextObjCtr === null || !nextObjActor || nextObjCtr < objCtr || - (nextObjCtr === objCtr && nextObjActor < objActor)) { - skipCount += 1 - } else { - break - } +class WriteableTable extends Table { + /** + * Returns a proxied version of the row with ID `id`. This row object can be + * modified within a change callback. + */ + byId(id) { + if (isObject(this.entries[id]) && this.entries[id].id === id) { + const objectId = this.entries[id][OBJECT_ID] + const path = this.path.concat([{key: id, objectId}]) + return this.context.instantiateObject(path, objectId, ['id']) } } - if ((nextObjCtr !== objCtr || nextObjActor !== objActor) && !resumeInsertion) { - return {found: true, skipCount, visibleCount} - } - // Seek to the appropriate key (if string key is used) - if (keyStr !== null) { - keyStrD.skipValues(skipCount) - while (!keyStrD.done) { - const objActorIndex = objActorD.readValue() - nextObjActor = objActorIndex === null ? null : actorIds[objActorIndex] - nextObjCtr = objCtrD.readValue() - nextKeyStr = keyStrD.readValue() - if (nextKeyStr !== null && nextKeyStr < keyStr && - nextObjCtr === objCtr && nextObjActor === objActor) { - skipCount += 1 - } else { - break - } - } - return {found: true, skipCount, visibleCount} + /** + * Adds a new row to the table. The row is given as a map from + * column name to value. Returns the objectId of the new row. + */ + add(row) { + return this.context.addTableRow(this.path, row) } - idCtrD.skipValues(skipCount) - idActorD.skipValues(skipCount) - insertD.skipValues(skipCount) - succNumD.skipValues(skipCount) - nextIdCtr = idCtrD.readValue() - nextIdActor = actorIds[idActorD.readValue()] - nextInsert = insertD.readValue() - nextSuccNum = succNumD.readValue() - - // If we are inserting into a list, an opId key is used, and we need to seek to a position *after* - // the referenced operation. Moreover, we need to skip over any existing operations with a greater - // opId than the new insertion, for CRDT convergence on concurrent insertions in the same place. - if (insert) { - // If insertion is not at the head, search for the reference element - if (!resumeInsertion && keyCtr !== null && keyCtr > 0 && keyActor !== null) { - skipCount += 1 - while (!idCtrD.done && !idActorD.done && (nextIdCtr !== keyCtr || nextIdActor !== keyActor)) { - if (nextInsert) elemVisible = false - if (nextSuccNum === 0 && !elemVisible) { - visibleCount += 1 - elemVisible = true - } - nextIdCtr = idCtrD.readValue() - nextIdActor = actorIds[idActorD.readValue()] - nextObjCtr = objCtrD.readValue() - nextObjActor = actorIds[objActorD.readValue()] - nextInsert = insertD.readValue() - nextSuccNum = succNumD.readValue() - if (nextObjCtr === objCtr && nextObjActor === objActor) skipCount += 1; else break - } - if (nextObjCtr !== objCtr || nextObjActor !== objActor || nextIdCtr !== keyCtr || - nextIdActor !== keyActor || !nextInsert) { - return {found: false, skipCount, visibleCount} - } - if (nextInsert) elemVisible = false - if (nextSuccNum === 0 && !elemVisible) { - visibleCount += 1 - elemVisible = true - } - - // Set up the next* variables to the operation following the reference element - if (idCtrD.done || idActorD.done) return {found: true, skipCount, visibleCount} - nextIdCtr = idCtrD.readValue() - nextIdActor = actorIds[idActorD.readValue()] - nextObjCtr = objCtrD.readValue() - nextObjActor = actorIds[objActorD.readValue()] - nextInsert = insertD.readValue() - nextSuccNum = succNumD.readValue() - } - - // Skip over any list elements with greater ID than the new one, and any non-insertions - while ((!nextInsert || nextIdCtr > idCtr || (nextIdCtr === idCtr && nextIdActor > idActor)) && - nextObjCtr === objCtr && nextObjActor === objActor) { - skipCount += 1 - if (nextInsert) elemVisible = false - if (nextSuccNum === 0 && !elemVisible) { - visibleCount += 1 - elemVisible = true - } - if (!idCtrD.done && !idActorD.done) { - nextIdCtr = idCtrD.readValue() - nextIdActor = actorIds[idActorD.readValue()] - nextObjCtr = objCtrD.readValue() - nextObjActor = actorIds[objActorD.readValue()] - nextInsert = insertD.readValue() - nextSuccNum = succNumD.readValue() - } else { - break - } - } - - } else if (keyCtr !== null && keyCtr > 0 && keyActor !== null) { - // If we are updating an existing list element, seek to just before the referenced ID - while ((!nextInsert || nextIdCtr !== keyCtr || nextIdActor !== keyActor) && - nextObjCtr === objCtr && nextObjActor === objActor) { - skipCount += 1 - if (nextInsert) elemVisible = false - if (nextSuccNum === 0 && !elemVisible) { - visibleCount += 1 - elemVisible = true - } - if (!idCtrD.done && !idActorD.done) { - nextIdCtr = idCtrD.readValue() - nextIdActor = actorIds[idActorD.readValue()] - nextObjCtr = objCtrD.readValue() - nextObjActor = actorIds[objActorD.readValue()] - nextInsert = insertD.readValue() - nextSuccNum = succNumD.readValue() - } else { - break - } - } - if (nextObjCtr !== objCtr || nextObjActor !== objActor || nextIdCtr !== keyCtr || - nextIdActor !== keyActor || !nextInsert) { - return {found: false, skipCount, visibleCount} + /** + * Removes the row with ID `id` from the table. Throws an exception if the row + * does not exist in the table. + */ + remove(id) { + if (isObject(this.entries[id]) && this.entries[id].id === id) { + this.context.deleteTableRow(this.path, id, this.opIds[id]) + } else { + throw new RangeError(`There is no row with ID ${id} in this table`) } } - return {found: true, skipCount, visibleCount} } /** - * Returns the number of list elements that should be added to a list index when skipping over the - * block with index `blockIndex` in the list object with ID `objectId`. + * This function is used to instantiate a Table object in the context of + * applying a patch (see apply_patch.js). */ -function visibleListElements(docState, blockIndex, objectId) { - const thisBlock = docState.blocks[blockIndex] - const nextBlock = docState.blocks[blockIndex + 1] - - let blockVisible = thisBlock.numVisible[objectId] - if (blockVisible !== undefined) { - // If a list element is split across the block boundary, don't double-count it - if (thisBlock.lastVisibleActor === nextBlock.firstVisibleActor && - thisBlock.lastVisibleActor !== undefined && - thisBlock.lastVisibleCtr === nextBlock.firstVisibleCtr && - thisBlock.lastVisibleCtr !== undefined) blockVisible -= 1 - return blockVisible - } else { - return 0 +function instantiateTable(objectId, entries, opIds) { + const instance = Object.create(Table.prototype) + if (!objectId) { + throw new RangeError('instantiateTable requires an objectId to be given') } + instance[OBJECT_ID] = objectId + instance[CONFLICTS] = Object.freeze({}) + instance.entries = entries || {} + instance.opIds = opIds || {} + return instance } -/** - * Scans the blocks of document operations to find the position where a new operation should be - * inserted. Returns an object with keys: - * - `blockIndex`: the index of the block into which we should insert the new operation - * - `skipCount`: the number of operations, counted from the start of the block, after which the - * new operations should be inserted or merged. - * - `visibleCount`: if modifying a list object, the number of visible (i.e. non-deleted) list - * elements that precede the position where the new operations should be applied. - */ -function seekToOp(docState, ops) { - const { objActor, objCtr, keyActor, keyCtr, keyStr } = ops - let blockIndex = 0, totalVisible = 0 +module.exports = { Table, instantiateTable } - // Skip any blocks that contain only objects with lower objectIds - if (objCtr !== null) { - while (blockIndex < docState.blocks.length - 1) { - const blockActor = docState.blocks[blockIndex].lastObjectActor === undefined ? undefined - : docState.actorIds[docState.blocks[blockIndex].lastObjectActor] - const blockCtr = docState.blocks[blockIndex].lastObjectCtr - if (blockCtr === undefined || blockCtr < objCtr || (blockCtr === objCtr && blockActor < objActor)) { - blockIndex++ - } else { - break - } - } - } +},{"../src/common":82,"./constants":56}],64:[function(require,module,exports){ +const { OBJECT_ID } = require('./constants') +const { isObject } = require('../src/common') - if (keyStr !== null) { - // String key is used. First skip any blocks that contain only lower keys - while (blockIndex < docState.blocks.length - 1) { - const blockLastKey = docState.blocks[blockIndex].lastKey[ops.objId] - if (blockLastKey !== undefined && blockLastKey < keyStr) blockIndex++; else break +class Text { + constructor (text) { + if (typeof text === 'string') { + const elems = [...text].map(value => ({value})) + return instantiateText(undefined, elems) // eslint-disable-line + } else if (Array.isArray(text)) { + const elems = text.map(value => ({value})) + return instantiateText(undefined, elems) // eslint-disable-line + } else if (text === undefined) { + return instantiateText(undefined, []) // eslint-disable-line + } else { + throw new TypeError(`Unsupported initial value for Text: ${text}`) } + } - // When we have a candidate block, decode it to find the exact insertion position - const {skipCount} = seekWithinBlock(ops, docState.blocks[blockIndex].columns, docState.actorIds, false) - return {blockIndex, skipCount, visibleCount: 0} + get length () { + return this.elems.length + } - } else { - // List operation - const insertAtHead = keyCtr === null || keyCtr === 0 || keyActor === null - const keyActorNum = keyActor === null ? null : docState.actorIds.indexOf(keyActor) - let resumeInsertion = false + get (index) { + const value = this.elems[index].value + if (this.context && isObject(value)) { + const objectId = value[OBJECT_ID] + const path = this.path.concat([{key: index, objectId}]) + return this.context.instantiateObject(path, objectId) + } else { + return value + } + } - while (true) { - // Search for the reference element, skipping any blocks whose Bloom filter does not contain - // the reference element. We only do this if not inserting at the head (in which case there is - // no reference element), or if we already found the reference element in an earlier block (in - // which case we have resumeInsertion === true). The latter case arises with concurrent - // insertions at the same position, and so we have to scan beyond the reference element to - // find the actual insertion position, and that further scan crosses a block boundary. - if (!insertAtHead && !resumeInsertion) { - while (blockIndex < docState.blocks.length - 1 && - !bloomFilterContains(docState.blocks[blockIndex].bloom, keyActorNum, keyCtr)) { - // If we reach the end of the list object without a Bloom filter hit, the reference element - // doesn't exist - if (docState.blocks[blockIndex].lastObjectCtr > objCtr) { - throw new RangeError(`Reference element not found: ${keyCtr}@${keyActor}`) - } + getElemId (index) { + return this.elems[index].elemId + } - // Add up number of visible list elements in any blocks we skip, for list index computation - totalVisible += visibleListElements(docState, blockIndex, ops.objId) - blockIndex++ + /** + * Iterates over the text elements character by character, including any + * inline objects. + */ + [Symbol.iterator] () { + let elems = this.elems, index = -1 + return { + next () { + index += 1 + if (index < elems.length) { + return {done: false, value: elems[index].value} + } else { + return {done: true} } } + } + } - // We have a candidate block. Decode it to see whether it really contains the reference element - const {found, skipCount, visibleCount} = seekWithinBlock(ops, - docState.blocks[blockIndex].columns, - docState.actorIds, - resumeInsertion) + /** + * Returns the content of the Text object as a simple string, ignoring any + * non-character elements. + */ + toString() { + // Concatting to a string is faster than creating an array and then + // .join()ing for small (<100KB) arrays. + // https://jsperf.com/join-vs-loop-w-type-test + let str = '' + for (const elem of this.elems) { + if (typeof elem.value === 'string') str += elem.value + } + return str + } - if (blockIndex === docState.blocks.length - 1) { - // Last block: if we haven't found the reference element by now, it's an error - if (found) { - return {blockIndex, skipCount, visibleCount: totalVisible + visibleCount} - } else { - throw new RangeError(`Reference element not found: ${keyCtr}@${keyActor}`) + /** + * Returns the content of the Text object as a sequence of strings, + * interleaved with non-character elements. + * + * For example, the value ['a', 'b', {x: 3}, 'c', 'd'] has spans: + * => ['ab', {x: 3}, 'cd'] + */ + toSpans() { + let spans = [] + let chars = '' + for (const elem of this.elems) { + if (typeof elem.value === 'string') { + chars += elem.value + } else { + if (chars.length > 0) { + spans.push(chars) + chars = '' } - - } else if (found && skipCount < docState.blocks[blockIndex].numOps) { - // The insertion position lies within the current block - return {blockIndex, skipCount, visibleCount: totalVisible + visibleCount} + spans.push(elem.value) } - - // Reference element not found and there are still blocks left ==> it was probably a false positive. - // Reference element found, but we skipped all the way to the end of the block ==> we need to - // continue scanning the next block to find the actual insertion position. - // Either way, go back round the loop again to skip blocks until the next Bloom filter hit. - resumeInsertion = found && ops.insert - totalVisible += visibleListElements(docState, blockIndex, ops.objId) - blockIndex++ } + if (chars.length > 0) { + spans.push(chars) + } + return spans } -} -/** - * Updates Bloom filter `bloom`, given as a Uint8Array, to contain the list element ID consisting of - * counter `elemIdCtr` and actor number `elemIdActor`. We don't actually bother computing a hash - * function, since those two integers serve perfectly fine as input. We turn the two integers into a - * sequence of probe indexes using the triple hashing algorithm from the following paper: - * - * Peter C. Dillinger and Panagiotis Manolios. Bloom Filters in Probabilistic Verification. - * 5th International Conference on Formal Methods in Computer-Aided Design (FMCAD), November 2004. - * http://www.ccis.northeastern.edu/home/pete/pub/bloom-filters-verification.pdf - */ -function bloomFilterAdd(bloom, elemIdActor, elemIdCtr) { - let modulo = 8 * bloom.byteLength, x = elemIdCtr % modulo, y = elemIdActor % modulo + /** + * Returns the content of the Text object as a simple string, so that the + * JSON serialization of an Automerge document represents text nicely. + */ + toJSON() { + return this.toString() + } - // Use one step of FNV-1a to compute a third value from the two inputs. - // Taken from http://www.isthe.com/chongo/tech/comp/fnv/index.html - // The prime is just over 2^24, so elemIdCtr can be up to about 2^29 = 500 million before the - // result of the multiplication exceeds 2^53. And even if it does exceed 2^53 and loses precision, - // that shouldn't be a problem as it should still be deterministic, and the Bloom filter - // computation only needs to be internally consistent within this library. - let z = ((elemIdCtr ^ elemIdActor) * 16777619 >>> 0) % modulo + /** + * Returns a writeable instance of this object. This instance is returned when + * the text object is accessed within a change callback. `context` is the + * proxy context that keeps track of the mutations. + */ + getWriteable(context, path) { + if (!this[OBJECT_ID]) { + throw new RangeError('getWriteable() requires the objectId to be set') + } - for (let i = 0; i < BLOOM_NUM_PROBES; i++) { - bloom[x >>> 3] |= 1 << (x & 7) - x = (x + y) % modulo - y = (y + z) % modulo + const instance = instantiateText(this[OBJECT_ID], this.elems) + instance.context = context + instance.path = path + return instance } -} -/** - * Returns true if the list element ID consisting of counter `elemIdCtr` and actor number - * `elemIdActor` is likely to be contained in the Bloom filter `bloom`. - */ -function bloomFilterContains(bloom, elemIdActor, elemIdCtr) { - let modulo = 8 * bloom.byteLength, x = elemIdCtr % modulo, y = elemIdActor % modulo - let z = ((elemIdCtr ^ elemIdActor) * 16777619 >>> 0) % modulo - - // See comments in the bloomFilterAdd function for an explanation - for (let i = 0; i < BLOOM_NUM_PROBES; i++) { - if ((bloom[x >>> 3] & (1 << (x & 7))) === 0) { - return false + /** + * Updates the list item at position `index` to a new value `value`. + */ + set (index, value) { + if (this.context) { + this.context.setListIndex(this.path, index, value) + } else if (!this[OBJECT_ID]) { + this.elems[index].value = value + } else { + throw new TypeError('Automerge.Text object cannot be modified outside of a change block') } - x = (x + y) % modulo - y = (y + z) % modulo + return this } - return true -} - -/** - * Reads the relevant columns of a block of operations and updates that block to contain the - * metadata we need to efficiently figure out where to insert new operations. - */ -function updateBlockMetadata(block, actorIds) { - block.bloom = new Uint8Array(BLOOM_FILTER_SIZE) - block.lastKey = {} - block.numVisible = {} - block.numOps = 0 - block.lastObjectActor = undefined - block.lastObjectCtr = undefined - block.firstVisibleActor = undefined - block.firstVisibleCtr = undefined - block.lastVisibleActor = undefined - block.lastVisibleCtr = undefined - - for (let col of block.columns) col.decoder.reset() - const [objActorD, objCtrD, keyActorD, keyCtrD, keyStrD, idActorD, idCtrD, insertD, /* actionD */, - /* valLenD */, /* valRawD */, /* chldActorD */, /* chldCtrD */, succNumD] = block.columns.map(col => col.decoder) - - while (!idCtrD.done) { - block.numOps += 1 - const objActor = objActorD.readValue(), objCtr = objCtrD.readValue() - const keyActor = keyActorD.readValue(), keyCtr = keyCtrD.readValue(), keyStr = keyStrD.readValue() - const idActor = idActorD.readValue(), idCtr = idCtrD.readValue() - const insert = insertD.readValue(), succNum = succNumD.readValue() - const objectId = objActor === null ? '_root' : `${objCtr}@${actorIds[objActor]}` - if (objActor !== null && objCtr !== null) { - block.lastObjectActor = objActor - block.lastObjectCtr = objCtr + /** + * Inserts new list items `values` starting at position `index`. + */ + insertAt(index, ...values) { + if (this.context) { + this.context.splice(this.path, index, 0, values) + } else if (!this[OBJECT_ID]) { + this.elems.splice(index, 0, ...values.map(value => ({value}))) + } else { + throw new TypeError('Automerge.Text object cannot be modified outside of a change block') } + return this + } - if (keyStr !== null) { - // Map key: for each object, record the highest key contained in the block - block.lastKey[objectId] = keyStr - } else if (insert || keyCtr !== null) { - // List element - if (block.numVisible[objectId] === undefined) block.numVisible[objectId] = 0 - const elemIdActor = insert ? idActor : keyActor - const elemIdCtr = insert ? idCtr : keyCtr - bloomFilterAdd(block.bloom, elemIdActor, elemIdCtr) - - // If the list element is visible, update the block metadata accordingly - if (succNum === 0) { - if (block.firstVisibleActor === undefined) block.firstVisibleActor = elemIdActor - if (block.firstVisibleCtr === undefined) block.firstVisibleCtr = elemIdCtr - if (block.lastVisibleActor !== elemIdActor || block.lastVisibleCtr !== elemIdCtr) { - block.numVisible[objectId] += 1 - } - block.lastVisibleActor = elemIdActor - block.lastVisibleCtr = elemIdCtr - } + /** + * Deletes `numDelete` list items starting at position `index`. + * if `numDelete` is not given, one item is deleted. + */ + deleteAt(index, numDelete = 1) { + if (this.context) { + this.context.splice(this.path, index, numDelete, []) + } else if (!this[OBJECT_ID]) { + this.elems.splice(index, numDelete) + } else { + throw new TypeError('Automerge.Text object cannot be modified outside of a change block') } + return this } } -/** - * Updates a block's metadata based on an operation being added to a block. - */ -function addBlockOperation(block, op, objectId, actorIds, isChangeOp) { - // Keep track of the largest objectId contained within a block - if (op[objActorIdx] !== null && op[objCtrIdx] !== null && - (block.lastObjectCtr === undefined || block.lastObjectCtr < op[objCtrIdx] || - (block.lastObjectCtr === op[objCtrIdx] && actorIds[block.lastObjectActor] < actorIds[op[objActorIdx]]))) { - block.lastObjectActor = op[objActorIdx] - block.lastObjectCtr = op[objCtrIdx] +// Read-only methods that can delegate to the JavaScript built-in array +for (let method of ['concat', 'every', 'filter', 'find', 'findIndex', 'forEach', 'includes', + 'indexOf', 'join', 'lastIndexOf', 'map', 'reduce', 'reduceRight', + 'slice', 'some', 'toLocaleString']) { + Text.prototype[method] = function (...args) { + const array = [...this] + return array[method](...args) } +} - if (op[keyStrIdx] !== null) { - // TODO this comparison should use UTF-8 encoding, not JavaScript's UTF-16 - if (block.lastKey[objectId] === undefined || block.lastKey[objectId] < op[keyStrIdx]) { - block.lastKey[objectId] = op[keyStrIdx] - } - } else { - // List element - const elemIdActor = op[insertIdx] ? op[idActorIdx] : op[keyActorIdx] - const elemIdCtr = op[insertIdx] ? op[idCtrIdx] : op[keyCtrIdx] - bloomFilterAdd(block.bloom, elemIdActor, elemIdCtr) - - if (op[succNumIdx] === 0 || isChangeOp) { - if (block.firstVisibleActor === undefined) block.firstVisibleActor = elemIdActor - if (block.firstVisibleCtr === undefined) block.firstVisibleCtr = elemIdCtr - block.lastVisibleActor = elemIdActor - block.lastVisibleCtr = elemIdCtr - } - } +function instantiateText(objectId, elems) { + const instance = Object.create(Text.prototype) + instance[OBJECT_ID] = objectId + instance.elems = elems + return instance } -/** - * Takes a block containing too many operations, and splits it into a sequence of adjacent blocks of - * roughly equal size. - */ -function splitBlock(block, actorIds) { - for (let col of block.columns) col.decoder.reset() +module.exports = { Text, instantiateText } - // Make each of the resulting blocks between 50% and 80% full (leaving a bit of space in each - // block so that it doesn't get split again right away the next time an operation is added). - // The upper bound cannot be lower than 75% since otherwise we would end up with a block less than - // 50% full when going from two to three blocks. - const numBlocks = Math.ceil(block.numOps / (0.8 * MAX_BLOCK_SIZE)) - let blocks = [], opsSoFar = 0 +},{"../src/common":82,"./constants":56}],65:[function(require,module,exports){ +// Top level file is just a mixin of submodules & constants +'use strict'; - for (let i = 1; i <= numBlocks; i++) { - const opsToCopy = Math.ceil(i * block.numOps / numBlocks) - opsSoFar - const encoders = block.columns.map(col => ({columnId: col.columnId, encoder: encoderByColumnId(col.columnId)})) - copyColumns(encoders, block.columns, opsToCopy) - const decoders = encoders.map(col => { - const decoder = decoderByColumnId(col.columnId, col.encoder.buffer) - return {columnId: col.columnId, decoder} - }) +const { Deflate, deflate, deflateRaw, gzip } = require('./lib/deflate'); - const newBlock = {columns: decoders} - updateBlockMetadata(newBlock, actorIds) - blocks.push(newBlock) - opsSoFar += opsToCopy - } +const { Inflate, inflate, inflateRaw, ungzip } = require('./lib/inflate'); - return blocks -} +const constants = require('./lib/zlib/constants'); -/** - * Takes an array of blocks and concatenates the corresponding columns across all of the blocks. - */ -function concatBlocks(blocks) { - const encoders = blocks[0].columns.map(col => ({columnId: col.columnId, encoder: encoderByColumnId(col.columnId)})) +module.exports.Deflate = Deflate; +module.exports.deflate = deflate; +module.exports.deflateRaw = deflateRaw; +module.exports.gzip = gzip; +module.exports.Inflate = Inflate; +module.exports.inflate = inflate; +module.exports.inflateRaw = inflateRaw; +module.exports.ungzip = ungzip; +module.exports.constants = constants; - for (let block of blocks) { - for (let col of block.columns) col.decoder.reset() - copyColumns(encoders, block.columns, block.numOps) - } - return encoders -} +},{"./lib/deflate":66,"./lib/inflate":67,"./lib/zlib/constants":71}],66:[function(require,module,exports){ +'use strict'; -/** - * Copies `count` rows from the set of input columns `inCols` to the set of output columns - * `outCols`. The input columns are given as an array of `{columnId, decoder}` objects, and the - * output columns are given as an array of `{columnId, encoder}` objects. Both are sorted in - * increasing order of columnId. If there is no matching input column for a given output column, it - * is filled in with `count` blank values (according to the column type). - */ -function copyColumns(outCols, inCols, count) { - if (count === 0) return - let inIndex = 0, lastGroup = -1, lastCardinality = 0, valueColumn = -1, valueBytes = 0 - for (let outCol of outCols) { - while (inIndex < inCols.length && inCols[inIndex].columnId < outCol.columnId) inIndex++ - let inCol = null - if (inIndex < inCols.length && inCols[inIndex].columnId === outCol.columnId && - inCols[inIndex].decoder.buf.byteLength > 0) { - inCol = inCols[inIndex].decoder - } - const colCount = (outCol.columnId >> 4 === lastGroup) ? lastCardinality : count - if (outCol.columnId % 8 === COLUMN_TYPE.GROUP_CARD) { - lastGroup = outCol.columnId >> 4 - if (inCol) { - lastCardinality = outCol.encoder.copyFrom(inCol, {count, sumValues: true}).sum - } else { - outCol.encoder.appendValue(0, count) - lastCardinality = 0 - } - } else if (outCol.columnId % 8 === COLUMN_TYPE.VALUE_LEN) { - if (inCol) { - if (inIndex + 1 === inCols.length || inCols[inIndex + 1].columnId !== outCol.columnId + 1) { - throw new RangeError('VALUE_LEN column without accompanying VALUE_RAW column') - } - valueColumn = outCol.columnId + 1 - valueBytes = outCol.encoder.copyFrom(inCol, {count: colCount, sumValues: true, sumShift: 4}).sum - } else { - outCol.encoder.appendValue(null, colCount) - valueColumn = outCol.columnId + 1 - valueBytes = 0 - } - } else if (outCol.columnId % 8 === COLUMN_TYPE.VALUE_RAW) { - if (outCol.columnId !== valueColumn) { - throw new RangeError('VALUE_RAW column without accompanying VALUE_LEN column') - } - if (valueBytes > 0) { - outCol.encoder.appendRawBytes(inCol.readRawBytes(valueBytes)) - } - } else { // ACTOR_ID, INT_RLE, INT_DELTA, BOOLEAN, or STRING_RLE - if (inCol) { - outCol.encoder.copyFrom(inCol, {count: colCount}) - } else { - const blankValue = (outCol.columnId % 8 === COLUMN_TYPE.BOOLEAN) ? false : null - outCol.encoder.appendValue(blankValue, colCount) - } - } - } -} +const zlib_deflate = require('./zlib/deflate'); +const utils = require('./utils/common'); +const strings = require('./utils/strings'); +const msg = require('./zlib/messages'); +const ZStream = require('./zlib/zstream'); + +const toString = Object.prototype.toString; + +/* Public constants ==========================================================*/ +/* ===========================================================================*/ + +const { + Z_NO_FLUSH, Z_SYNC_FLUSH, Z_FULL_FLUSH, Z_FINISH, + Z_OK, Z_STREAM_END, + Z_DEFAULT_COMPRESSION, + Z_DEFAULT_STRATEGY, + Z_DEFLATED +} = require('./zlib/constants'); + +/* ===========================================================================*/ + /** - * Parses one operation from a set of columns. The argument `columns` contains a list of objects - * with `columnId` and `decoder` properties. Returns an array in which the i'th element is the - * value read from the i'th column in `columns`. Does not interpret datatypes; the only - * interpretation of values is that if `actorTable` is given, a value `v` in a column of type - * ACTOR_ID is replaced with `actorTable[v]`. - */ -function readOperation(columns, actorTable) { - let operation = [], colValue, lastGroup = -1, lastCardinality = 0, valueColumn = -1, valueBytes = 0 - for (let col of columns) { - if (col.columnId % 8 === COLUMN_TYPE.VALUE_RAW) { - if (col.columnId !== valueColumn) throw new RangeError('unexpected VALUE_RAW column') - colValue = col.decoder.readRawBytes(valueBytes) - } else if (col.columnId % 8 === COLUMN_TYPE.GROUP_CARD) { - lastGroup = col.columnId >> 4 - lastCardinality = col.decoder.readValue() || 0 - colValue = lastCardinality - } else if (col.columnId >> 4 === lastGroup) { - colValue = [] - if (col.columnId % 8 === COLUMN_TYPE.VALUE_LEN) { - valueColumn = col.columnId + 1 - valueBytes = 0 - } - for (let i = 0; i < lastCardinality; i++) { - let value = col.decoder.readValue() - if (col.columnId % 8 === COLUMN_TYPE.ACTOR_ID && actorTable && typeof value === 'number') { - value = actorTable[value] - } - if (col.columnId % 8 === COLUMN_TYPE.VALUE_LEN) { - valueBytes += colValue >>> 4 - } - colValue.push(value) - } - } else { - colValue = col.decoder.readValue() - if (col.columnId % 8 === COLUMN_TYPE.ACTOR_ID && actorTable && typeof colValue === 'number') { - colValue = actorTable[colValue] - } - if (col.columnId % 8 === COLUMN_TYPE.VALUE_LEN) { - valueColumn = col.columnId + 1 - valueBytes = colValue >>> 4 - } - } + * class Deflate + * + * Generic JS-style wrapper for zlib calls. If you don't need + * streaming behaviour - use more simple functions: [[deflate]], + * [[deflateRaw]] and [[gzip]]. + **/ - operation.push(colValue) - } - return operation -} +/* internal + * Deflate.chunks -> Array + * + * Chunks of output data, if [[Deflate#onData]] not overridden. + **/ /** - * Appends `operation`, in the form returned by `readOperation()`, to the columns in `outCols`. The - * argument `inCols` provides metadata about the types of columns in `operation`; the value - * `operation[i]` comes from the column `inCols[i]`. - */ -function appendOperation(outCols, inCols, operation) { - let inIndex = 0, lastGroup = -1, lastCardinality = 0 - for (let outCol of outCols) { - while (inIndex < inCols.length && inCols[inIndex].columnId < outCol.columnId) inIndex++ + * Deflate.result -> Uint8Array + * + * Compressed result, generated by default [[Deflate#onData]] + * and [[Deflate#onEnd]] handlers. Filled after you push last chunk + * (call [[Deflate#push]] with `Z_FINISH` / `true` param). + **/ - if (inIndex < inCols.length && inCols[inIndex].columnId === outCol.columnId) { - const colValue = operation[inIndex] - if (outCol.columnId % 8 === COLUMN_TYPE.GROUP_CARD) { - lastGroup = outCol.columnId >> 4 - lastCardinality = colValue - outCol.encoder.appendValue(colValue) - } else if (outCol.columnId >> 4 === lastGroup) { - if (!Array.isArray(colValue) || colValue.length !== lastCardinality) { - throw new RangeError('bad group value') - } - for (let v of colValue) outCol.encoder.appendValue(v) - } else if (outCol.columnId % 8 === COLUMN_TYPE.VALUE_RAW) { - if (colValue) outCol.encoder.appendRawBytes(colValue) - } else { - outCol.encoder.appendValue(colValue) - } - } else if (outCol.columnId % 8 === COLUMN_TYPE.GROUP_CARD) { - lastGroup = outCol.columnId >> 4 - lastCardinality = 0 - outCol.encoder.appendValue(0) - } else if (outCol.columnId % 8 !== COLUMN_TYPE.VALUE_RAW) { - const count = (outCol.columnId >> 4 === lastGroup) ? lastCardinality : 1 - let blankValue = null - if (outCol.columnId % 8 === COLUMN_TYPE.BOOLEAN) blankValue = false - if (outCol.columnId % 8 === COLUMN_TYPE.VALUE_LEN) blankValue = 0 - outCol.encoder.appendValue(blankValue, count) - } - } -} +/** + * Deflate.err -> Number + * + * Error code after deflate finished. 0 (Z_OK) on success. + * You will not need it in real life, because deflate errors + * are possible only on wrong options or bad `onData` / `onEnd` + * custom handlers. + **/ /** - * Parses the next operation from block `blockIndex` of the document. Returns an object of the form - * `{docOp, blockIndex}` where `docOp` is an operation in the form returned by `readOperation()`, - * and `blockIndex` is the block number to use on the next call (it moves on to the next block when - * we reach the end of the current block). `docOp` is null if there are no more operations. - */ -function readNextDocOp(docState, blockIndex) { - let block = docState.blocks[blockIndex] - if (!block.columns[actionIdx].decoder.done) { - return {docOp: readOperation(block.columns), blockIndex} - } else if (blockIndex === docState.blocks.length - 1) { - return {docOp: null, blockIndex} - } else { - blockIndex += 1 - block = docState.blocks[blockIndex] - for (let col of block.columns) col.decoder.reset() - return {docOp: readOperation(block.columns), blockIndex} - } -} + * Deflate.msg -> String + * + * Error message, if [[Deflate.err]] != 0 + **/ + /** - * Parses the next operation from a sequence of changes. `changeState` serves as the state of this - * pseudo-iterator, and it is mutated to reflect the new operation. In particular, - * `changeState.nextOp` is set to the operation that was read, and `changeState.done` is set to true - * when we have finished reading the last operation in the last change. - */ -function readNextChangeOp(docState, changeState) { - // If we've finished reading one change, move to the next change that contains at least one op - while (changeState.changeIndex < changeState.changes.length - 1 && - (!changeState.columns || changeState.columns[actionIdx].decoder.done)) { - changeState.changeIndex += 1 - const change = changeState.changes[changeState.changeIndex] - changeState.columns = makeDecoders(change.columns, CHANGE_COLUMNS) - changeState.opCtr = change.startOp + * new Deflate(options) + * - options (Object): zlib deflate options. + * + * Creates new deflator instance with specified params. Throws exception + * on bad params. Supported options: + * + * - `level` + * - `windowBits` + * - `memLevel` + * - `strategy` + * - `dictionary` + * + * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced) + * for more information on these. + * + * Additional options, for internal needs: + * + * - `chunkSize` - size of generated data chunks (16K by default) + * - `raw` (Boolean) - do raw deflate + * - `gzip` (Boolean) - create gzip wrapper + * - `header` (Object) - custom header for gzip + * - `text` (Boolean) - true if compressed data believed to be text + * - `time` (Number) - modification time, unix timestamp + * - `os` (Number) - operation system code + * - `extra` (Array) - array of bytes with extra data (max 65536) + * - `name` (String) - file name (binary string) + * - `comment` (String) - comment (binary string) + * - `hcrc` (Boolean) - true if header crc should be added + * + * ##### Example: + * + * ```javascript + * const pako = require('pako') + * , chunk1 = new Uint8Array([1,2,3,4,5,6,7,8,9]) + * , chunk2 = new Uint8Array([10,11,12,13,14,15,16,17,18,19]); + * + * const deflate = new pako.Deflate({ level: 3}); + * + * deflate.push(chunk1, false); + * deflate.push(chunk2, true); // true -> last chunk + * + * if (deflate.err) { throw new Error(deflate.err); } + * + * console.log(deflate.result); + * ``` + **/ +function Deflate(options) { + this.options = utils.assign({ + level: Z_DEFAULT_COMPRESSION, + method: Z_DEFLATED, + chunkSize: 16384, + windowBits: 15, + memLevel: 8, + strategy: Z_DEFAULT_STRATEGY + }, options || {}); - // Update docState based on the information in the change - updateBlockColumns(docState, changeState.columns) - const {actorIds, actorTable} = getActorTable(docState.actorIds, change) - docState.actorIds = actorIds - changeState.actorTable = actorTable - changeState.actorIndex = docState.actorIds.indexOf(change.actorIds[0]) + let opt = this.options; + + if (opt.raw && (opt.windowBits > 0)) { + opt.windowBits = -opt.windowBits; } - // Reached the end of the last change? - if (changeState.columns[actionIdx].decoder.done) { - changeState.done = true - changeState.nextOp = null - return + else if (opt.gzip && (opt.windowBits > 0) && (opt.windowBits < 16)) { + opt.windowBits += 16; } - changeState.nextOp = readOperation(changeState.columns, changeState.actorTable) - changeState.nextOp[idActorIdx] = changeState.actorIndex - changeState.nextOp[idCtrIdx] = changeState.opCtr - changeState.changes[changeState.changeIndex].maxOp = changeState.opCtr - if (changeState.opCtr > docState.maxOp) docState.maxOp = changeState.opCtr - changeState.opCtr += 1 + this.err = 0; // error code, if happens (0 = Z_OK) + this.msg = ''; // error message + this.ended = false; // used to avoid multiple onEnd() calls + this.chunks = []; // chunks of compressed data - const op = changeState.nextOp - if ((op[objCtrIdx] === null && op[objActorIdx] !== null) || - (op[objCtrIdx] !== null && op[objActorIdx] === null)) { - throw new RangeError(`Mismatched object reference: (${op[objCtrIdx]}, ${op[objActorIdx]})`) + this.strm = new ZStream(); + this.strm.avail_out = 0; + + let status = zlib_deflate.deflateInit2( + this.strm, + opt.level, + opt.method, + opt.windowBits, + opt.memLevel, + opt.strategy + ); + + if (status !== Z_OK) { + throw new Error(msg[status]); } - if ((op[keyCtrIdx] === null && op[keyActorIdx] !== null) || - (op[keyCtrIdx] === 0 && op[keyActorIdx] !== null) || - (op[keyCtrIdx] > 0 && op[keyActorIdx] === null)) { - throw new RangeError(`Mismatched operation key: (${op[keyCtrIdx]}, ${op[keyActorIdx]})`) + + if (opt.header) { + zlib_deflate.deflateSetHeader(this.strm, opt.header); } -} -function emptyObjectPatch(objectId, type) { - if (type === 'list' || type === 'text') { - return {objectId, type, edits: []} - } else { - return {objectId, type, props: {}} + if (opt.dictionary) { + let dict; + // Convert data if needed + if (typeof opt.dictionary === 'string') { + // If we need to compress text, change encoding to utf8. + dict = strings.string2buf(opt.dictionary); + } else if (toString.call(opt.dictionary) === '[object ArrayBuffer]') { + dict = new Uint8Array(opt.dictionary); + } else { + dict = opt.dictionary; + } + + status = zlib_deflate.deflateSetDictionary(this.strm, dict); + + if (status !== Z_OK) { + throw new Error(msg[status]); + } + + this._dict_set = true; } } /** - * Returns true if the two given operation IDs have the same actor ID, and the counter of `id2` is - * exactly `delta` greater than the counter of `id1`. - */ -function opIdDelta(id1, id2, delta = 1) { - const parsed1 = parseOpId(id1), parsed2 = parseOpId(id2) - return parsed1.actorId === parsed2.actorId && parsed1.counter + delta === parsed2.counter -} + * Deflate#push(data[, flush_mode]) -> Boolean + * - data (Uint8Array|ArrayBuffer|String): input data. Strings will be + * converted to utf8 byte sequence. + * - flush_mode (Number|Boolean): 0..6 for corresponding Z_NO_FLUSH..Z_TREE modes. + * See constants. Skipped or `false` means Z_NO_FLUSH, `true` means Z_FINISH. + * + * Sends input data to deflate pipe, generating [[Deflate#onData]] calls with + * new compressed chunks. Returns `true` on success. The last data block must + * have `flush_mode` Z_FINISH (or `true`). That will flush internal pending + * buffers and call [[Deflate#onEnd]]. + * + * On fail call [[Deflate#onEnd]] with error code and return false. + * + * ##### Example + * + * ```javascript + * push(chunk, false); // push one of data chunks + * ... + * push(chunk, true); // push last chunk + * ``` + **/ +Deflate.prototype.push = function (data, flush_mode) { + const strm = this.strm; + const chunkSize = this.options.chunkSize; + let status, _flush_mode; -/** - * Appends a list edit operation (insert, update, remove) to an array of existing operations. If the - * last existing operation can be extended (as a multi-op), we do that. - */ -function appendEdit(existingEdits, nextEdit) { - if (existingEdits.length === 0) { - existingEdits.push(nextEdit) - return + if (this.ended) { return false; } + + if (flush_mode === ~~flush_mode) _flush_mode = flush_mode; + else _flush_mode = flush_mode === true ? Z_FINISH : Z_NO_FLUSH; + + // Convert data if needed + if (typeof data === 'string') { + // If we need to compress text, change encoding to utf8. + strm.input = strings.string2buf(data); + } else if (toString.call(data) === '[object ArrayBuffer]') { + strm.input = new Uint8Array(data); + } else { + strm.input = data; } - let lastEdit = existingEdits[existingEdits.length - 1] - if (lastEdit.action === 'insert' && nextEdit.action === 'insert' && - lastEdit.index === nextEdit.index - 1 && - lastEdit.value.type === 'value' && nextEdit.value.type === 'value' && - lastEdit.elemId === lastEdit.opId && nextEdit.elemId === nextEdit.opId && - opIdDelta(lastEdit.elemId, nextEdit.elemId, 1) && - lastEdit.value.datatype === nextEdit.value.datatype && - typeof lastEdit.value.value === typeof nextEdit.value.value) { - lastEdit.action = 'multi-insert' - if (nextEdit.value.datatype) lastEdit.datatype = nextEdit.value.datatype - lastEdit.values = [lastEdit.value.value, nextEdit.value.value] - delete lastEdit.value - delete lastEdit.opId + strm.next_in = 0; + strm.avail_in = strm.input.length; - } else if (lastEdit.action === 'multi-insert' && nextEdit.action === 'insert' && - lastEdit.index + lastEdit.values.length === nextEdit.index && - nextEdit.value.type === 'value' && nextEdit.elemId === nextEdit.opId && - opIdDelta(lastEdit.elemId, nextEdit.elemId, lastEdit.values.length) && - lastEdit.datatype === nextEdit.value.datatype && - typeof lastEdit.values[0] === typeof nextEdit.value.value) { - lastEdit.values.push(nextEdit.value.value) + for (;;) { + if (strm.avail_out === 0) { + strm.output = new Uint8Array(chunkSize); + strm.next_out = 0; + strm.avail_out = chunkSize; + } - } else if (lastEdit.action === 'remove' && nextEdit.action === 'remove' && - lastEdit.index === nextEdit.index) { - lastEdit.count += nextEdit.count + // Make sure avail_out > 6 to avoid repeating markers + if ((_flush_mode === Z_SYNC_FLUSH || _flush_mode === Z_FULL_FLUSH) && strm.avail_out <= 6) { + this.onData(strm.output.subarray(0, strm.next_out)); + strm.avail_out = 0; + continue; + } - } else { - existingEdits.push(nextEdit) - } -} + status = zlib_deflate.deflate(strm, _flush_mode); -/** - * `edits` is an array of (SingleInsertEdit | MultiInsertEdit | UpdateEdit | RemoveEdit) list edits - * for a patch. This function appends an UpdateEdit to this array. A conflict is represented by - * having several consecutive edits with the same index, and this can be realised by calling - * `appendUpdate` several times for the same list element. On the first such call, `firstUpdate` - * must be true. - * - * It is possible that coincidentally the previous edit (potentially arising from a different - * change) is for the same index. If this is the case, to avoid accidentally treating consecutive - * updates for the same index as a conflict, we remove the previous edit for the same index. This is - * safe because the previous edit is overwritten by the new edit being appended, and we know that - * it's for the same list elements because there are no intervening insertions/deletions that could - * have changed the indexes. - */ -function appendUpdate(edits, index, elemId, opId, value, firstUpdate) { - let insert = false - if (firstUpdate) { - // Pop all edits for the same index off the end of the edits array. This sequence may begin with - // either an insert or an update. If it's an insert, we remember that fact, and use it below. - while (!insert && edits.length > 0) { - const lastEdit = edits[edits.length - 1] - if ((lastEdit.action === 'insert' || lastEdit.action === 'update') && lastEdit.index === index) { - edits.pop() - insert = (lastEdit.action === 'insert') - } else if (lastEdit.action === 'multi-insert' && lastEdit.index + lastEdit.values.length - 1 === index) { - lastEdit.values.pop() - insert = true - } else { - break + // Ended => flush and finish + if (status === Z_STREAM_END) { + if (strm.next_out > 0) { + this.onData(strm.output.subarray(0, strm.next_out)); } + status = zlib_deflate.deflateEnd(this.strm); + this.onEnd(status); + this.ended = true; + return status === Z_OK; } - } - // If we popped an insert edit off the edits array, we need to turn the new update into an insert - // in order to ensure the list element still gets inserted (just with a new value). - if (insert) { - appendEdit(edits, {action: 'insert', index, elemId, opId, value}) - } else { - appendEdit(edits, {action: 'update', index, opId, value}) + // Flush if out buffer full + if (strm.avail_out === 0) { + this.onData(strm.output); + continue; + } + + // Flush if requested and has data + if (_flush_mode > 0 && strm.next_out > 0) { + this.onData(strm.output.subarray(0, strm.next_out)); + strm.avail_out = 0; + continue; + } + + if (strm.avail_in === 0) break; } -} + + return true; +}; + /** - * `edits` is an array of (SingleInsertEdit | MultiInsertEdit | UpdateEdit | RemoveEdit) list edits - * for a patch. We assume that there is a suffix of this array that consists of an insertion at - * position `index`, followed by zero or more UpdateEdits at the same index. This function rewrites - * that suffix to be all updates instead. This is needed because sometimes when generating a patch - * we think we are performing a list insertion, but then it later turns out that there was already - * an existing value at that list element, and so we actually need to do an update, not an insert. + * Deflate#onData(chunk) -> Void + * - chunk (Uint8Array): output data. * - * If the suffix is preceded by one or more updates at the same index, those earlier updates are - * removed by `appendUpdate()` to ensure we don't inadvertently treat them as part of the same - * conflict. - */ -function convertInsertToUpdate(edits, index, elemId) { - let updates = [] - while (edits.length > 0) { - let lastEdit = edits[edits.length - 1] - if (lastEdit.action === 'insert') { - if (lastEdit.index !== index) throw new RangeError('last edit has unexpected index') - updates.unshift(edits.pop()) - break - } else if (lastEdit.action === 'update') { - if (lastEdit.index !== index) throw new RangeError('last edit has unexpected index') - updates.unshift(edits.pop()) - } else { - // It's impossible to encounter a remove edit here because the state machine in - // updatePatchProperty() ensures that a property can have either an insert or a remove edit, - // but not both. It's impossible to encounter a multi-insert here because multi-inserts always - // have equal elemId and opId (i.e. they can only be used for the operation that first inserts - // an element, but not for any subsequent assignments to that list element); moreover, - // convertInsertToUpdate is only called if an insert action is followed by a non-overwritten - // document op. The fact that there is a non-overwritten document op after another op on the - // same list element implies that the original insertion op for that list element must be - // overwritten, and thus the original insertion op cannot have given rise to a multi-insert. - throw new RangeError('last edit has unexpected action') - } - } + * By default, stores data blocks in `chunks[]` property and glue + * those in `onEnd`. Override this handler, if you need another behaviour. + **/ +Deflate.prototype.onData = function (chunk) { + this.chunks.push(chunk); +}; - // Now take the edits we popped off and push them back onto the list again - let firstUpdate = true - for (let update of updates) { - appendUpdate(edits, index, elemId, update.opId, update.value, firstUpdate) - firstUpdate = false + +/** + * Deflate#onEnd(status) -> Void + * - status (Number): deflate status. 0 (Z_OK) on success, + * other if not. + * + * Called once after you tell deflate that the input stream is + * complete (Z_FINISH). By default - join collected chunks, + * free memory and fill `results` / `err` properties. + **/ +Deflate.prototype.onEnd = function (status) { + // On success - join + if (status === Z_OK) { + this.result = utils.flattenChunks(this.chunks); } -} + this.chunks = []; + this.err = status; + this.msg = this.strm.msg; +}; + /** - * Updates `patches` to reflect the operation `op` within the document with state `docState`. - * Can be called multiple times if there are multiple operations for the same property (e.g. due - * to a conflict). `propState` is an object that carries over state between such successive - * invocations for the same property. If the current object is a list, `listIndex` is the index - * into that list (counting only visible elements). If the operation `op` was already previously - * in the document, `oldSuccNum` is the value of `op[succNumIdx]` before the current change was - * applied (allowing us to determine whether this operation was overwritten or deleted in the - * current change). `oldSuccNum` must be undefined if the operation came from the current change. - * If we are creating an incremental patch as a result of applying one or more changes, `newBlock` - * is the block to which the operations are getting written; we will update the metadata on this - * block. `newBlock` should be null if we are creating a patch for the whole document. - */ -function updatePatchProperty(patches, newBlock, objectId, op, docState, propState, listIndex, oldSuccNum) { - const isWholeDoc = !newBlock - const type = op[actionIdx] < ACTIONS.length ? OBJECT_TYPE[ACTIONS[op[actionIdx]]] : null - const opId = `${op[idCtrIdx]}@${docState.actorIds[op[idActorIdx]]}` - const elemIdActor = op[insertIdx] ? op[idActorIdx] : op[keyActorIdx] - const elemIdCtr = op[insertIdx] ? op[idCtrIdx] : op[keyCtrIdx] - const elemId = op[keyStrIdx] ? op[keyStrIdx] : `${elemIdCtr}@${docState.actorIds[elemIdActor]}` + * deflate(data[, options]) -> Uint8Array + * - data (Uint8Array|ArrayBuffer|String): input data to compress. + * - options (Object): zlib deflate options. + * + * Compress `data` with deflate algorithm and `options`. + * + * Supported options are: + * + * - level + * - windowBits + * - memLevel + * - strategy + * - dictionary + * + * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced) + * for more information on these. + * + * Sugar (options): + * + * - `raw` (Boolean) - say that we work with raw stream, if you don't wish to specify + * negative windowBits implicitly. + * + * ##### Example: + * + * ```javascript + * const pako = require('pako') + * const data = new Uint8Array([1,2,3,4,5,6,7,8,9]); + * + * console.log(pako.deflate(data)); + * ``` + **/ +function deflate(input, options) { + const deflator = new Deflate(options); - // When the change contains a new make* operation (i.e. with an even-numbered action), record the - // new parent-child relationship in objectMeta. TODO: also handle link/move operations. - if (op[actionIdx] % 2 === 0 && !docState.objectMeta[opId]) { - docState.objectMeta[opId] = {parentObj: objectId, parentKey: elemId, opId, type, children: {}} - deepCopyUpdate(docState.objectMeta, [objectId, 'children', elemId, opId], {objectId: opId, type, props: {}}) - } + deflator.push(input, true); - // firstOp is true if the current operation is the first of a sequence of ops for the same key - const firstOp = !propState[elemId] - if (!propState[elemId]) propState[elemId] = {visibleOps: [], hasChild: false} + // That will never happens, if you don't cheat with options :) + if (deflator.err) { throw deflator.msg || msg[deflator.err]; } - // An operation is overwritten if it is a document operation that has at least one successor - const isOverwritten = (oldSuccNum !== undefined && op[succNumIdx] > 0) + return deflator.result; +} - // Record all visible values for the property, and whether it has any child object - if (!isOverwritten) { - propState[elemId].visibleOps.push(op) - propState[elemId].hasChild = propState[elemId].hasChild || (op[actionIdx] % 2) === 0 // even-numbered action == make* operation - } - // If one or more of the values of the property is a child object, we update objectMeta to store - // all of the visible values of the property (even the non-child-object values). Then, when we - // subsequently process an update within that child object, we can construct the patch to - // contain the conflicting values. - const prevChildren = docState.objectMeta[objectId].children[elemId] - if (propState[elemId].hasChild || (prevChildren && Object.keys(prevChildren).length > 0)) { - let values = {} - for (let visible of propState[elemId].visibleOps) { - const opId = `${visible[idCtrIdx]}@${docState.actorIds[visible[idActorIdx]]}` - if (ACTIONS[visible[actionIdx]] === 'set') { - values[opId] = Object.assign({type: 'value'}, decodeValue(visible[valLenIdx], visible[valRawIdx])) - } else if (visible[actionIdx] % 2 === 0) { - const objType = visible[actionIdx] < ACTIONS.length ? OBJECT_TYPE[ACTIONS[visible[actionIdx]]] : null - values[opId] = emptyObjectPatch(opId, objType) - } - } +/** + * deflateRaw(data[, options]) -> Uint8Array + * - data (Uint8Array|ArrayBuffer|String): input data to compress. + * - options (Object): zlib deflate options. + * + * The same as [[deflate]], but creates raw data, without wrapper + * (header and adler32 crc). + **/ +function deflateRaw(input, options) { + options = options || {}; + options.raw = true; + return deflate(input, options); +} - // Copy so that objectMeta is not modified if an exception is thrown while applying change - deepCopyUpdate(docState.objectMeta, [objectId, 'children', elemId], values) - } - let patchKey, patchValue +/** + * gzip(data[, options]) -> Uint8Array + * - data (Uint8Array|ArrayBuffer|String): input data to compress. + * - options (Object): zlib deflate options. + * + * The same as [[deflate]], but create gzip wrapper instead of + * deflate one. + **/ +function gzip(input, options) { + options = options || {}; + options.gzip = true; + return deflate(input, options); +} - // For counters, increment operations are succs to the set operation that created the counter, - // but in this case we want to add the values rather than overwriting them. - if (isOverwritten && ACTIONS[op[actionIdx]] === 'set' && (op[valLenIdx] & 0x0f) === VALUE_TYPE.COUNTER) { - // This is the initial set operation that creates a counter. Initialise the counter state - // to contain all successors of the set operation. Only if we later find that each of these - // successor operations is an increment, we make the counter visible in the patch. - if (!propState[elemId]) propState[elemId] = {visibleOps: [], hasChild: false} - if (!propState[elemId].counterStates) propState[elemId].counterStates = {} - let counterStates = propState[elemId].counterStates - let counterState = {opId, value: decodeValue(op[valLenIdx], op[valRawIdx]).value, succs: {}} - for (let i = 0; i < op[succNumIdx]; i++) { - const succOp = `${op[succCtrIdx][i]}@${docState.actorIds[op[succActorIdx][i]]}` - counterStates[succOp] = counterState - counterState.succs[succOp] = true - } +module.exports.Deflate = Deflate; +module.exports.deflate = deflate; +module.exports.deflateRaw = deflateRaw; +module.exports.gzip = gzip; +module.exports.constants = require('./zlib/constants'); - } else if (ACTIONS[op[actionIdx]] === 'inc') { - // Incrementing a previously created counter. - if (!propState[elemId] || !propState[elemId].counterStates || !propState[elemId].counterStates[opId]) { - throw new RangeError(`increment operation ${opId} for unknown counter`) - } - let counterState = propState[elemId].counterStates[opId] - counterState.value += decodeValue(op[valLenIdx], op[valRawIdx]).value - delete counterState.succs[opId] +},{"./utils/common":68,"./utils/strings":69,"./zlib/constants":71,"./zlib/deflate":73,"./zlib/messages":78,"./zlib/zstream":80}],67:[function(require,module,exports){ +'use strict'; - if (Object.keys(counterState.succs).length === 0) { - patchKey = counterState.opId - patchValue = {type: 'value', datatype: 'counter', value: counterState.value} - // TODO if the counter is in a list element, we need to add a 'remove' action when deleted - } - } else if (!isOverwritten) { - // Add the value to the patch if it is not overwritten (i.e. if it has no succs). - if (ACTIONS[op[actionIdx]] === 'set') { - patchKey = opId - patchValue = Object.assign({type: 'value'}, decodeValue(op[valLenIdx], op[valRawIdx])) - } else if (op[actionIdx] % 2 === 0) { // even-numbered action == make* operation - if (!patches[opId]) patches[opId] = emptyObjectPatch(opId, type) - patchKey = opId - patchValue = patches[opId] - } - } +const zlib_inflate = require('./zlib/inflate'); +const utils = require('./utils/common'); +const strings = require('./utils/strings'); +const msg = require('./zlib/messages'); +const ZStream = require('./zlib/zstream'); +const GZheader = require('./zlib/gzheader'); - if (!patches[objectId]) patches[objectId] = emptyObjectPatch(objectId, docState.objectMeta[objectId].type) - const patch = patches[objectId] +const toString = Object.prototype.toString; - // Updating a list or text object (with elemId key) - if (op[keyStrIdx] === null) { - // If we come across any document op that was previously non-overwritten/non-deleted, that - // means the current list element already had a value before this change was applied, and - // therefore the current element cannot be an insert. If we already registered an insert, we - // have to convert it into an update. - if (oldSuccNum === 0 && !isWholeDoc && propState[elemId].action === 'insert') { - propState[elemId].action = 'update' - convertInsertToUpdate(patch.edits, listIndex, elemId) - if (newBlock) newBlock.numVisible[objectId] -= 1 - } +/* Public constants ==========================================================*/ +/* ===========================================================================*/ - if (patchValue) { - // If the op has a non-overwritten value and it came from the change, it's an insert. - // (It's not necessarily the case that op[insertIdx] is true: if a list element is concurrently - // deleted and updated, the node that first processes the deletion and then the update will - // observe the update as a re-insertion of the deleted list element.) - if (!propState[elemId].action && (oldSuccNum === undefined || isWholeDoc)) { - propState[elemId].action = 'insert' - appendEdit(patch.edits, {action: 'insert', index: listIndex, elemId, opId: patchKey, value: patchValue}) - if (newBlock) { - if (newBlock.numVisible[objectId] === undefined) newBlock.numVisible[objectId] = 0 - newBlock.numVisible[objectId] += 1 - } +const { + Z_NO_FLUSH, Z_FINISH, + Z_OK, Z_STREAM_END, Z_NEED_DICT, Z_STREAM_ERROR, Z_DATA_ERROR, Z_MEM_ERROR +} = require('./zlib/constants'); - // If the property has a value and it's not an insert, then it must be an update. - // We might have previously registered it as a remove, in which case we convert it to update. - } else if (propState[elemId].action === 'remove') { - let lastEdit = patch.edits[patch.edits.length - 1] - if (lastEdit.action !== 'remove') throw new RangeError('last edit has unexpected type') - if (lastEdit.count > 1) lastEdit.count -= 1; else patch.edits.pop() - propState[elemId].action = 'update' - appendUpdate(patch.edits, listIndex, elemId, patchKey, patchValue, true) - if (newBlock) newBlock.numVisible[objectId] += 1 +/* ===========================================================================*/ - } else { - // A 'normal' update - appendUpdate(patch.edits, listIndex, elemId, patchKey, patchValue, !propState[elemId].action) - if (!propState[elemId].action) propState[elemId].action = 'update' - } - } else if (oldSuccNum === 0 && !propState[elemId].action) { - // If the property used to have a non-overwritten/non-deleted value, but no longer, it's a remove - propState[elemId].action = 'remove' - appendEdit(patch.edits, {action: 'remove', index: listIndex, count: 1}) - if (newBlock) newBlock.numVisible[objectId] -= 1 - } +/** + * class Inflate + * + * Generic JS-style wrapper for zlib calls. If you don't need + * streaming behaviour - use more simple functions: [[inflate]] + * and [[inflateRaw]]. + **/ - } else if (patchValue || !isWholeDoc) { - // Updating a map or table (with string key) - if (firstOp || !patch.props[op[keyStrIdx]]) patch.props[op[keyStrIdx]] = {} - if (patchValue) patch.props[op[keyStrIdx]][patchKey] = patchValue - } -} +/* internal + * inflate.chunks -> Array + * + * Chunks of output data, if [[Inflate#onData]] not overridden. + **/ /** - * Applies operations (from one or more changes) to the document by merging the sequence of change - * ops into the sequence of document ops. The two inputs are `changeState` and `docState` - * respectively. Assumes that the decoders of both sets of columns are at the position where we want - * to start merging. `patches` is mutated to reflect the effect of the change operations. `ops` is - * the operation sequence to apply (as decoded by `groupRelatedOps()`). `docState` is as - * documented in `applyOps()`. If the operations are updating a list or text object, `listIndex` - * is the number of visible elements that precede the position at which we start merging. - * `blockIndex` is the document block number from which we are currently reading. - */ -function mergeDocChangeOps(patches, newBlock, outCols, changeState, docState, listIndex, blockIndex) { - const firstOp = changeState.nextOp, insert = firstOp[insertIdx] - const objActor = firstOp[objActorIdx], objCtr = firstOp[objCtrIdx] - const objectId = objActor === null ? '_root' : `${objCtr}@${docState.actorIds[objActor]}` - const idActorIndex = changeState.actorIndex, idActor = docState.actorIds[idActorIndex] - let foundListElem = false, elemVisible = false, propState = {}, docOp - ;({ docOp, blockIndex } = readNextDocOp(docState, blockIndex)) - let docOpsConsumed = (docOp === null ? 0 : 1) - let docOpOldSuccNum = (docOp === null ? 0 : docOp[succNumIdx]) - let changeOp = null, changeOps = [], changeCols = [], predSeen = [], lastChangeKey = null - changeState.objectIds.add(objectId) + * Inflate.result -> Uint8Array|String + * + * Uncompressed result, generated by default [[Inflate#onData]] + * and [[Inflate#onEnd]] handlers. Filled after you push last chunk + * (call [[Inflate#push]] with `Z_FINISH` / `true` param). + **/ - // Merge the two inputs: the sequence of ops in the doc, and the sequence of ops in the change. - // At each iteration, we either output the doc's op (possibly updated based on the change's ops) - // or output an op from the change. - while (true) { - // The array `changeOps` contains operations from the change(s) we're applying. When the array - // is empty, we load changes from the change. Typically we load only a single operation at a - // time, with two exceptions: 1. all operations that update the same key or list element in the - // same object are put into changeOps at the same time (this is needed so that we can update the - // succ columns of the document ops correctly); 2. a run of consecutive insertions is also - // placed into changeOps in one go. - // - // When we have processed all the ops in changeOps we try to see whether there are further - // operations that we can also process while we're at it. Those operations must be for the same - // object, they must be for a key or list element that appears later in the document, they must - // either all be insertions or all be non-insertions, and if insertions, they must be - // consecutive. If these conditions are satisfied, that means the operations can be processed in - // the same pass. If we encounter an operation that does not meet these conditions, we leave - // changeOps empty, and this function returns after having processed any remaining document ops. - // - // Any operations that could not be processed in a single pass remain in changeState; applyOps - // will seek to the appropriate position and then call mergeDocChangeOps again. - if (changeOps.length === 0) { - foundListElem = false +/** + * Inflate.err -> Number + * + * Error code after inflate finished. 0 (Z_OK) on success. + * Should be checked if broken data possible. + **/ - let nextOp = changeState.nextOp - while (!changeState.done && nextOp[idActorIdx] === idActorIndex && nextOp[insertIdx] === insert && - nextOp[objActorIdx] === firstOp[objActorIdx] && nextOp[objCtrIdx] === firstOp[objCtrIdx]) { +/** + * Inflate.msg -> String + * + * Error message, if [[Inflate.err]] != 0 + **/ - // Check if the operation's pred references a previous operation in changeOps - const lastOp = (changeOps.length > 0) ? changeOps[changeOps.length - 1] : null - let isOverwrite = false - for (let i = 0; i < nextOp[predNumIdx]; i++) { - for (let prevOp of changeOps) { - if (nextOp[predActorIdx][i] === prevOp[idActorIdx] && nextOp[predCtrIdx][i] === prevOp[idCtrIdx]) { - isOverwrite = true - } - } - } - // If any of the following `if` statements is true, we add `nextOp` to `changeOps`. If they - // are all false, we break out of the loop and stop adding to `changeOps`. - if (nextOp === firstOp) { - // First change operation in a mergeDocChangeOps call is always used - } else if (insert && lastOp !== null && nextOp[keyStrIdx] === null && - nextOp[keyActorIdx] === lastOp[idActorIdx] && - nextOp[keyCtrIdx] === lastOp[idCtrIdx]) { - // Collect consecutive insertions - } else if (!insert && lastOp !== null && nextOp[keyStrIdx] !== null && - nextOp[keyStrIdx] === lastOp[keyStrIdx] && !isOverwrite) { - // Collect several updates to the same key - } else if (!insert && lastOp !== null && - nextOp[keyStrIdx] === null && lastOp[keyStrIdx] === null && - nextOp[keyActorIdx] === lastOp[keyActorIdx] && - nextOp[keyCtrIdx] === lastOp[keyCtrIdx] && !isOverwrite) { - // Collect several updates to the same list element - } else if (!insert && lastOp === null && nextOp[keyStrIdx] === null && - docOp && docOp[insertIdx] && docOp[keyStrIdx] === null && - docOp[idActorIdx] === nextOp[keyActorIdx] && - docOp[idCtrIdx] === nextOp[keyCtrIdx]) { - // When updating/deleting list elements, keep going if the next elemId in the change - // equals the next elemId in the doc (i.e. we're updating several consecutive elements) - } else if (!insert && lastOp === null && nextOp[keyStrIdx] !== null && - lastChangeKey !== null && lastChangeKey < nextOp[keyStrIdx]) { - // Allow a single mergeDocChangeOps call to process changes to several keys in the same - // object, provided that they appear in ascending order - } else break +/** + * new Inflate(options) + * - options (Object): zlib inflate options. + * + * Creates new inflator instance with specified params. Throws exception + * on bad params. Supported options: + * + * - `windowBits` + * - `dictionary` + * + * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced) + * for more information on these. + * + * Additional options, for internal needs: + * + * - `chunkSize` - size of generated data chunks (16K by default) + * - `raw` (Boolean) - do raw inflate + * - `to` (String) - if equal to 'string', then result will be converted + * from utf8 to utf16 (javascript) string. When string output requested, + * chunk length can differ from `chunkSize`, depending on content. + * + * By default, when no options set, autodetect deflate/gzip data format via + * wrapper header. + * + * ##### Example: + * + * ```javascript + * const pako = require('pako') + * const chunk1 = new Uint8Array([1,2,3,4,5,6,7,8,9]) + * const chunk2 = new Uint8Array([10,11,12,13,14,15,16,17,18,19]); + * + * const inflate = new pako.Inflate({ level: 3}); + * + * inflate.push(chunk1, false); + * inflate.push(chunk2, true); // true -> last chunk + * + * if (inflate.err) { throw new Error(inflate.err); } + * + * console.log(inflate.result); + * ``` + **/ +function Inflate(options) { + this.options = utils.assign({ + chunkSize: 1024 * 64, + windowBits: 15, + to: '' + }, options || {}); - lastChangeKey = (nextOp !== null) ? nextOp[keyStrIdx] : null - changeOps.push(changeState.nextOp) - changeCols.push(changeState.columns) - predSeen.push(new Array(changeState.nextOp[predNumIdx])) - readNextChangeOp(docState, changeState) - nextOp = changeState.nextOp - } + const opt = this.options; + + // Force window size for `raw` data, if not set directly, + // because we have no header for autodetect. + if (opt.raw && (opt.windowBits >= 0) && (opt.windowBits < 16)) { + opt.windowBits = -opt.windowBits; + if (opt.windowBits === 0) { opt.windowBits = -15; } + } + + // If `windowBits` not defined (and mode not raw) - set autodetect flag for gzip/deflate + if ((opt.windowBits >= 0) && (opt.windowBits < 16) && + !(options && options.windowBits)) { + opt.windowBits += 32; + } + + // Gzip header has no info about windows size, we can do autodetect only + // for deflate. So, if window size not set, force it to max when gzip possible + if ((opt.windowBits > 15) && (opt.windowBits < 48)) { + // bit 3 (16) -> gzipped data + // bit 4 (32) -> autodetect gzip/deflate + if ((opt.windowBits & 15) === 0) { + opt.windowBits |= 15; } + } - if (changeOps.length > 0) changeOp = changeOps[0] - const inCorrectObject = docOp && docOp[objActorIdx] === changeOp[objActorIdx] && docOp[objCtrIdx] === changeOp[objCtrIdx] - const keyMatches = docOp && docOp[keyStrIdx] !== null && docOp[keyStrIdx] === changeOp[keyStrIdx] - const listElemMatches = docOp && docOp[keyStrIdx] === null && changeOp[keyStrIdx] === null && - ((!docOp[insertIdx] && docOp[keyActorIdx] === changeOp[keyActorIdx] && docOp[keyCtrIdx] === changeOp[keyCtrIdx]) || - (docOp[insertIdx] && docOp[idActorIdx] === changeOp[keyActorIdx] && docOp[idCtrIdx] === changeOp[keyCtrIdx])) + this.err = 0; // error code, if happens (0 = Z_OK) + this.msg = ''; // error message + this.ended = false; // used to avoid multiple onEnd() calls + this.chunks = []; // chunks of compressed data - // We keep going until we run out of ops in the change, except that even when we run out, we - // keep going until we have processed all doc ops for the current key/list element. - if (changeOps.length === 0 && !(inCorrectObject && (keyMatches || listElemMatches))) break + this.strm = new ZStream(); + this.strm.avail_out = 0; - let takeDocOp = false, takeChangeOps = 0 + let status = zlib_inflate.inflateInit2( + this.strm, + opt.windowBits + ); - // The change operations come first if we are inserting list elements (seekToOp already - // determines the correct insertion position), if there is no document operation, if the next - // document operation is for a different object, or if the change op's string key is - // lexicographically first (TODO check ordering of keys beyond the basic multilingual plane). - if (insert || !inCorrectObject || - (docOp[keyStrIdx] === null && changeOp[keyStrIdx] !== null) || - (docOp[keyStrIdx] !== null && changeOp[keyStrIdx] !== null && changeOp[keyStrIdx] < docOp[keyStrIdx])) { - // Take the operations from the change - takeChangeOps = changeOps.length - if (!inCorrectObject && !foundListElem && changeOp[keyStrIdx] === null && !changeOp[insertIdx]) { - // This can happen if we first update one list element, then another one earlier in the - // list. That is not allowed: list element updates must occur in ascending order. - throw new RangeError("could not find list element with ID: " + - `${changeOp[keyCtrIdx]}@${docState.actorIds[changeOp[keyActorIdx]]}`) - } + if (status !== Z_OK) { + throw new Error(msg[status]); + } - } else if (keyMatches || listElemMatches || foundListElem) { - // The doc operation is for the same key or list element in the same object as the change - // ops, so we merge them. First, if any of the change ops' `pred` matches the opId of the - // document operation, we update the document operation's `succ` accordingly. - for (let opIndex = 0; opIndex < changeOps.length; opIndex++) { - const op = changeOps[opIndex] - for (let i = 0; i < op[predNumIdx]; i++) { - if (op[predActorIdx][i] === docOp[idActorIdx] && op[predCtrIdx][i] === docOp[idCtrIdx]) { - // Insert into the doc op's succ list such that the lists remains sorted - let j = 0 - while (j < docOp[succNumIdx] && (docOp[succCtrIdx][j] < op[idCtrIdx] || - docOp[succCtrIdx][j] === op[idCtrIdx] && docState.actorIds[docOp[succActorIdx][j]] < idActor)) j++ - docOp[succCtrIdx].splice(j, 0, op[idCtrIdx]) - docOp[succActorIdx].splice(j, 0, idActorIndex) - docOp[succNumIdx]++ - predSeen[opIndex][i] = true - break - } - } - } - - if (listElemMatches) foundListElem = true - - if (foundListElem && !listElemMatches) { - // If the previous docOp was for the correct list element, and the current docOp is for - // the wrong list element, then place the current changeOp before the docOp. - takeChangeOps = changeOps.length - - } else if (changeOps.length === 0 || docOp[idCtrIdx] < changeOp[idCtrIdx] || - (docOp[idCtrIdx] === changeOp[idCtrIdx] && docState.actorIds[docOp[idActorIdx]] < idActor)) { - // When we have several operations for the same object and the same key, we want to keep - // them sorted in ascending order by opId. Here we have docOp with a lower opId, so we - // output it first. - takeDocOp = true - updatePatchProperty(patches, newBlock, objectId, docOp, docState, propState, listIndex, docOpOldSuccNum) - - // A deletion op in the change is represented in the document only by its entries in the - // succ list of the operations it overwrites; it has no separate row in the set of ops. - for (let i = changeOps.length - 1; i >= 0; i--) { - let deleted = true - for (let j = 0; j < changeOps[i][predNumIdx]; j++) { - if (!predSeen[i][j]) deleted = false - } - if (ACTIONS[changeOps[i][actionIdx]] === 'del' && deleted) { - changeOps.splice(i, 1) - changeCols.splice(i, 1) - predSeen.splice(i, 1) - } - } - - } else if (docOp[idCtrIdx] === changeOp[idCtrIdx] && docState.actorIds[docOp[idActorIdx]] === idActor) { - throw new RangeError(`duplicate operation ID: ${changeOp[idCtrIdx]}@${idActor}`) - } else { - // The changeOp has the lower opId, so we output it first. - takeChangeOps = 1 - } - } else { - // The document operation comes first if its string key is lexicographically first, or if - // we're using opId keys and the keys don't match (i.e. we scan the document until we find a - // matching key). - takeDocOp = true - } + this.header = new GZheader(); - if (takeDocOp) { - appendOperation(outCols, docState.blocks[blockIndex].columns, docOp) - addBlockOperation(newBlock, docOp, objectId, docState.actorIds, false) + zlib_inflate.inflateGetHeader(this.strm, this.header); - if (docOp[insertIdx] && elemVisible) { - elemVisible = false - listIndex++ - } - if (docOp[succNumIdx] === 0) elemVisible = true - newBlock.numOps++ - ;({ docOp, blockIndex } = readNextDocOp(docState, blockIndex)) - if (docOp !== null) { - docOpsConsumed++ - docOpOldSuccNum = docOp[succNumIdx] - } + // Setup dictionary + if (opt.dictionary) { + // Convert data if needed + if (typeof opt.dictionary === 'string') { + opt.dictionary = strings.string2buf(opt.dictionary); + } else if (toString.call(opt.dictionary) === '[object ArrayBuffer]') { + opt.dictionary = new Uint8Array(opt.dictionary); } - - if (takeChangeOps > 0) { - for (let i = 0; i < takeChangeOps; i++) { - let op = changeOps[i] - // Check that we've seen all ops mentioned in `pred` (they must all have lower opIds than - // the change op's own opId, so we must have seen them already) - for (let j = 0; j < op[predNumIdx]; j++) { - if (!predSeen[i][j]) { - throw new RangeError(`no matching operation for pred: ${op[predCtrIdx][j]}@${docState.actorIds[op[predActorIdx][j]]}`) - } - } - updatePatchProperty(patches, newBlock, objectId, op, docState, propState, listIndex) - appendOperation(outCols, changeCols[i], op) - addBlockOperation(newBlock, op, objectId, docState.actorIds, true) - - if (op[insertIdx]) { - elemVisible = false - listIndex++ - } else { - elemVisible = true - } - } - - if (takeChangeOps === changeOps.length) { - changeOps.length = 0 - changeCols.length = 0 - predSeen.length = 0 - } else { - changeOps.splice(0, takeChangeOps) - changeCols.splice(0, takeChangeOps) - predSeen.splice(0, takeChangeOps) + if (opt.raw) { //In raw mode we need to set the dictionary early + status = zlib_inflate.inflateSetDictionary(this.strm, opt.dictionary); + if (status !== Z_OK) { + throw new Error(msg[status]); } - newBlock.numOps += takeChangeOps - } - } - - if (docOp) { - appendOperation(outCols, docState.blocks[blockIndex].columns, docOp) - newBlock.numOps++ - if (docOp[objActorIdx] === objActor && docOp[objCtrIdx] === objCtr) { - addBlockOperation(newBlock, docOp, objectId, docState.actorIds, false) } } - return {docOpsConsumed, blockIndex} } /** - * Applies operations from the change (or series of changes) in `changeState` to the document - * `docState`. Passing `changeState` to `readNextChangeOp` allows iterating over the change ops. - * `docState` is an object with keys: - * - `actorIds` is an array of actorIds (as hex strings) occurring in the document (values in - * the document's objActor/keyActor/idActor/... columns are indexes into this array). - * - `blocks` is an array of all the blocks of operations in the document. - * - `objectMeta` is a map from objectId to metadata about that object. + * Inflate#push(data[, flush_mode]) -> Boolean + * - data (Uint8Array|ArrayBuffer): input data + * - flush_mode (Number|Boolean): 0..6 for corresponding Z_NO_FLUSH..Z_TREE + * flush modes. See constants. Skipped or `false` means Z_NO_FLUSH, + * `true` means Z_FINISH. * - * `docState` is mutated to contain the updated document state. - * `patches` is a patch object that is mutated to reflect the operations applied by this function. - */ -function applyOps(patches, changeState, docState) { - const [objActorNum, objCtr, keyActorNum, keyCtr, keyStr, idActorNum, idCtr, insert] = changeState.nextOp - const objActor = objActorNum === null ? null : docState.actorIds[objActorNum] - const keyActor = keyActorNum === null ? null : docState.actorIds[keyActorNum] - const ops = { - objActor, objCtr, keyActor, keyCtr, keyStr, idActor: docState.actorIds[idActorNum], idCtr, insert, - objId: objActor === null ? '_root' : `${objCtr}@${objActor}` - } - - const {blockIndex, skipCount, visibleCount} = seekToOp(docState, ops) - const block = docState.blocks[blockIndex] - for (let col of block.columns) col.decoder.reset() - - const resetFirstVisible = (skipCount === 0) || (block.firstVisibleActor === undefined) || - (!insert && block.firstVisibleActor === keyActorNum && block.firstVisibleCtr === keyCtr) - const newBlock = { - columns: undefined, - bloom: new Uint8Array(block.bloom), - lastKey: copyObject(block.lastKey), - numVisible: copyObject(block.numVisible), - numOps: skipCount, - lastObjectActor: block.lastObjectActor, - lastObjectCtr: block.lastObjectCtr, - firstVisibleActor: resetFirstVisible ? undefined : block.firstVisibleActor, - firstVisibleCtr: resetFirstVisible ? undefined : block.firstVisibleCtr, - lastVisibleActor: undefined, - lastVisibleCtr: undefined - } - - // Copy the operations up to the insertion position (the first skipCount operations) - const outCols = block.columns.map(col => ({columnId: col.columnId, encoder: encoderByColumnId(col.columnId)})) - copyColumns(outCols, block.columns, skipCount) + * Sends input data to inflate pipe, generating [[Inflate#onData]] calls with + * new output chunks. Returns `true` on success. If end of stream detected, + * [[Inflate#onEnd]] will be called. + * + * `flush_mode` is not needed for normal operation, because end of stream + * detected automatically. You may try to use it for advanced things, but + * this functionality was not tested. + * + * On fail call [[Inflate#onEnd]] with error code and return false. + * + * ##### Example + * + * ```javascript + * push(chunk, false); // push one of data chunks + * ... + * push(chunk, true); // push last chunk + * ``` + **/ +Inflate.prototype.push = function (data, flush_mode) { + const strm = this.strm; + const chunkSize = this.options.chunkSize; + const dictionary = this.options.dictionary; + let status, _flush_mode, last_avail_out; - // Apply the operations from the change. This may cause blockIndex to move forwards if the - // property being updated straddles a block boundary. - const {blockIndex: lastBlockIndex, docOpsConsumed} = - mergeDocChangeOps(patches, newBlock, outCols, changeState, docState, visibleCount, blockIndex) + if (this.ended) return false; - // Copy the remaining operations after the insertion position - const lastBlock = docState.blocks[lastBlockIndex] - let copyAfterMerge = -skipCount - docOpsConsumed - for (let i = blockIndex; i <= lastBlockIndex; i++) copyAfterMerge += docState.blocks[i].numOps - copyColumns(outCols, lastBlock.columns, copyAfterMerge) - newBlock.numOps += copyAfterMerge + if (flush_mode === ~~flush_mode) _flush_mode = flush_mode; + else _flush_mode = flush_mode === true ? Z_FINISH : Z_NO_FLUSH; - for (let col of lastBlock.columns) { - if (!col.decoder.done) throw new RangeError(`excess ops in column ${col.columnId}`) + // Convert data if needed + if (toString.call(data) === '[object ArrayBuffer]') { + strm.input = new Uint8Array(data); + } else { + strm.input = data; } - newBlock.columns = outCols.map(col => { - const decoder = decoderByColumnId(col.columnId, col.encoder.buffer) - return {columnId: col.columnId, decoder} - }) + strm.next_in = 0; + strm.avail_in = strm.input.length; - if (blockIndex === lastBlockIndex && newBlock.numOps <= MAX_BLOCK_SIZE) { - // The result is just one output block - if (copyAfterMerge > 0 && block.lastVisibleActor !== undefined && block.lastVisibleCtr !== undefined) { - // It's possible that none of the ops after the merge point are visible, in which case the - // lastVisible may not be strictly correct, because it may refer to an operation before the - // merge point rather than a list element inserted by the current change. However, this doesn't - // matter, because the only purpose for which we need it is to check whether one block ends with - // the same visible element as the next block starts with (to avoid double-counting its index); - // if the last list element of a block is invisible, the exact value of lastVisible doesn't - // matter since it will be different from the next block's firstVisible in any case. - newBlock.lastVisibleActor = block.lastVisibleActor - newBlock.lastVisibleCtr = block.lastVisibleCtr + for (;;) { + if (strm.avail_out === 0) { + strm.output = new Uint8Array(chunkSize); + strm.next_out = 0; + strm.avail_out = chunkSize; } - docState.blocks[blockIndex] = newBlock - - } else { - // Oversized output block must be split into smaller blocks - const newBlocks = splitBlock(newBlock, docState.actorIds) - docState.blocks.splice(blockIndex, lastBlockIndex - blockIndex + 1, ...newBlocks) - } -} + status = zlib_inflate.inflate(strm, _flush_mode); -/** - * Updates the columns in a document's operation blocks to contain all the columns in a change - * (including any column types we don't recognise, which have been generated by a future version - * of Automerge). - */ -function updateBlockColumns(docState, changeCols) { - // Check that the columns of a change appear at the index at which we expect them to be - if (changeCols[objActorIdx ].columnId !== CHANGE_COLUMNS[objActorIdx ].columnId || CHANGE_COLUMNS[objActorIdx ].columnName !== 'objActor' || - changeCols[objCtrIdx ].columnId !== CHANGE_COLUMNS[objCtrIdx ].columnId || CHANGE_COLUMNS[objCtrIdx ].columnName !== 'objCtr' || - changeCols[keyActorIdx ].columnId !== CHANGE_COLUMNS[keyActorIdx ].columnId || CHANGE_COLUMNS[keyActorIdx ].columnName !== 'keyActor' || - changeCols[keyCtrIdx ].columnId !== CHANGE_COLUMNS[keyCtrIdx ].columnId || CHANGE_COLUMNS[keyCtrIdx ].columnName !== 'keyCtr' || - changeCols[keyStrIdx ].columnId !== CHANGE_COLUMNS[keyStrIdx ].columnId || CHANGE_COLUMNS[keyStrIdx ].columnName !== 'keyStr' || - changeCols[idActorIdx ].columnId !== CHANGE_COLUMNS[idActorIdx ].columnId || CHANGE_COLUMNS[idActorIdx ].columnName !== 'idActor' || - changeCols[idCtrIdx ].columnId !== CHANGE_COLUMNS[idCtrIdx ].columnId || CHANGE_COLUMNS[idCtrIdx ].columnName !== 'idCtr' || - changeCols[insertIdx ].columnId !== CHANGE_COLUMNS[insertIdx ].columnId || CHANGE_COLUMNS[insertIdx ].columnName !== 'insert' || - changeCols[actionIdx ].columnId !== CHANGE_COLUMNS[actionIdx ].columnId || CHANGE_COLUMNS[actionIdx ].columnName !== 'action' || - changeCols[valLenIdx ].columnId !== CHANGE_COLUMNS[valLenIdx ].columnId || CHANGE_COLUMNS[valLenIdx ].columnName !== 'valLen' || - changeCols[valRawIdx ].columnId !== CHANGE_COLUMNS[valRawIdx ].columnId || CHANGE_COLUMNS[valRawIdx ].columnName !== 'valRaw' || - changeCols[predNumIdx ].columnId !== CHANGE_COLUMNS[predNumIdx ].columnId || CHANGE_COLUMNS[predNumIdx ].columnName !== 'predNum' || - changeCols[predActorIdx].columnId !== CHANGE_COLUMNS[predActorIdx].columnId || CHANGE_COLUMNS[predActorIdx].columnName !== 'predActor' || - changeCols[predCtrIdx ].columnId !== CHANGE_COLUMNS[predCtrIdx ].columnId || CHANGE_COLUMNS[predCtrIdx ].columnName !== 'predCtr') { - throw new RangeError('unexpected columnId') - } + if (status === Z_NEED_DICT && dictionary) { + status = zlib_inflate.inflateSetDictionary(strm, dictionary); - // Check if there any columns in the change that are not in the document, apart from pred* - const docCols = docState.blocks[0].columns - if (!changeCols.every(changeCol => PRED_COLUMN_IDS.includes(changeCol.columnId) || - docCols.find(docCol => docCol.columnId === changeCol.columnId))) { - let allCols = docCols.map(docCol => ({columnId: docCol.columnId})) - for (let changeCol of changeCols) { - const { columnId } = changeCol - if (!PRED_COLUMN_IDS.includes(columnId) && !docCols.find(docCol => docCol.columnId === columnId)) { - allCols.push({columnId}) + if (status === Z_OK) { + status = zlib_inflate.inflate(strm, _flush_mode); + } else if (status === Z_DATA_ERROR) { + // Replace code with more verbose + status = Z_NEED_DICT; } } - allCols.sort((a, b) => a.columnId - b.columnId) - for (let blockIndex = 0; blockIndex < docState.blocks.length; blockIndex++) { - let block = copyObject(docState.blocks[blockIndex]) - block.columns = makeDecoders(block.columns.map(col => ({columnId: col.columnId, buffer: col.decoder.buf})), allCols) - docState.blocks[blockIndex] = block + // Skip snyc markers if more data follows and not raw mode + while (strm.avail_in > 0 && + status === Z_STREAM_END && + strm.state.wrap > 0 && + data[strm.next_in] !== 0) + { + zlib_inflate.inflateReset(strm); + status = zlib_inflate.inflate(strm, _flush_mode); } - } -} -/** - * Takes a decoded change header, including an array of actorIds. Returns an object of the form - * `{actorIds, actorTable}`, where `actorIds` is an updated array of actorIds appearing in the - * document (including the new change's actorId). `actorTable` is an array of integers where - * `actorTable[i]` contains the document's actor index for the actor that has index `i` in the - * change (`i == 0` is the author of the change). - */ -function getActorTable(actorIds, change) { - if (actorIds.indexOf(change.actorIds[0]) < 0) { - if (change.seq !== 1) { - throw new RangeError(`Seq ${change.seq} is the first change for actor ${change.actorIds[0]}`) - } - // Use concat, not push, so that the original array is not mutated - actorIds = actorIds.concat([change.actorIds[0]]) - } - const actorTable = [] // translate from change's actor index to doc's actor index - for (let actorId of change.actorIds) { - const index = actorIds.indexOf(actorId) - if (index < 0) { - throw new RangeError(`actorId ${actorId} is not known to document`) + switch (status) { + case Z_STREAM_ERROR: + case Z_DATA_ERROR: + case Z_NEED_DICT: + case Z_MEM_ERROR: + this.onEnd(status); + this.ended = true; + return false; } - actorTable.push(index) - } - return {actorIds, actorTable} -} -/** - * Finalises the patch for a change. `patches` is a map from objectIds to patch for that - * particular object, `objectIds` is the array of IDs of objects that are created or updated in the - * change, and `docState` is an object containing various bits of document state, including - * `objectMeta`, a map from objectIds to metadata about that object (such as its parent in the - * document tree). Mutates `patches` such that child objects are linked into their parent object, - * all the way to the root object. - */ -function setupPatches(patches, objectIds, docState) { - for (let objectId of objectIds) { - let meta = docState.objectMeta[objectId], childMeta = null, patchExists = false - while (true) { - const hasChildren = childMeta && Object.keys(meta.children[childMeta.parentKey]).length > 0 - if (!patches[objectId]) patches[objectId] = emptyObjectPatch(objectId, meta.type) + // Remember real `avail_out` value, because we may patch out buffer content + // to align utf8 strings boundaries. + last_avail_out = strm.avail_out; - if (childMeta && hasChildren) { - if (meta.type === 'list' || meta.type === 'text') { - // In list/text objects, parentKey is an elemID. First see if it already appears in an edit - for (let edit of patches[objectId].edits) { - if (edit.opId && meta.children[childMeta.parentKey][edit.opId]) { - patchExists = true - } - } + if (strm.next_out) { + if (strm.avail_out === 0 || status === Z_STREAM_END) { - // If we need to add an edit, we first have to translate the elemId into an index - if (!patchExists) { - const obj = parseOpId(objectId), elem = parseOpId(childMeta.parentKey) - const seekPos = { - objActor: obj.actorId, objCtr: obj.counter, - keyActor: elem.actorId, keyCtr: elem.counter, - keyStr: null, insert: false, - objId: objectId - } - const { visibleCount } = seekToOp(docState, seekPos) + if (this.options.to === 'string') { - for (let [opId, value] of Object.entries(meta.children[childMeta.parentKey])) { - let patchValue = value - if (value.objectId) { - if (!patches[value.objectId]) patches[value.objectId] = emptyObjectPatch(value.objectId, value.type) - patchValue = patches[value.objectId] - } - const edit = {action: 'update', index: visibleCount, opId, value: patchValue} - appendEdit(patches[objectId].edits, edit) - } - } + let next_out_utf8 = strings.utf8border(strm.output, strm.next_out); - } else { - // Non-list object: parentKey is the name of the property being updated (a string) - if (!patches[objectId].props[childMeta.parentKey]) { - patches[objectId].props[childMeta.parentKey] = {} - } - let values = patches[objectId].props[childMeta.parentKey] + let tail = strm.next_out - next_out_utf8; + let utf8str = strings.buf2string(strm.output, next_out_utf8); - for (let [opId, value] of Object.entries(meta.children[childMeta.parentKey])) { - if (values[opId]) { - patchExists = true - } else if (value.objectId) { - if (!patches[value.objectId]) patches[value.objectId] = emptyObjectPatch(value.objectId, value.type) - values[opId] = patches[value.objectId] - } else { - values[opId] = value - } - } + // move tail & realign counters + strm.next_out = tail; + strm.avail_out = chunkSize - tail; + if (tail) strm.output.set(strm.output.subarray(next_out_utf8, next_out_utf8 + tail), 0); + + this.onData(utf8str); + + } else { + this.onData(strm.output.length === strm.next_out ? strm.output : strm.output.subarray(0, strm.next_out)); } } + } - if (patchExists || !meta.parentObj || (childMeta && !hasChildren)) break - childMeta = meta - objectId = meta.parentObj - meta = docState.objectMeta[objectId] + // Must repeat iteration if out buffer is full + if (status === Z_OK && last_avail_out === 0) continue; + + // Finalize if end of stream reached. + if (status === Z_STREAM_END) { + status = zlib_inflate.inflateEnd(this.strm); + this.onEnd(status); + this.ended = true; + return true; } + + if (strm.avail_in === 0) break; } - return patches -} + + return true; +}; + /** - * Takes an array of decoded changes and applies them to a document. `docState` contains a bunch of - * fields describing the document state. This function mutates `docState` to contain the updated - * document state, and mutates `patches` to contain a patch to return to the frontend. Only the - * top-level `docState` object is mutated; all nested objects within it are treated as immutable. - * `objectIds` is mutated to contain the IDs of objects that are updated in any of the changes. + * Inflate#onData(chunk) -> Void + * - chunk (Uint8Array|String): output data. When string output requested, + * each chunk will be string. * - * Returns a two-element array `[applied, enqueued]`, where `applied` is an array of changes that - * have been applied to the document, and `enqueued` is an array of changes that have not yet been - * applied because they are missing a dependency. - */ -function applyChanges(patches, decodedChanges, docState, objectIds) { - let heads = new Set(docState.heads), changeHashes = new Set() - let clock = copyObject(docState.clock) - let applied = [], enqueued = [] - - for (let change of decodedChanges) { - // Skip any duplicate changes that we have already seen - if (docState.changeIndexByHash[change.hash] !== undefined || changeHashes.has(change.hash)) continue + * By default, stores data blocks in `chunks[]` property and glue + * those in `onEnd`. Override this handler, if you need another behaviour. + **/ +Inflate.prototype.onData = function (chunk) { + this.chunks.push(chunk); +}; - let causallyReady = true - for (let dep of change.deps) { - const depIndex = docState.changeIndexByHash[dep] - if ((depIndex === undefined || depIndex === -1) && !changeHashes.has(dep)) { - causallyReady = false - } - } - if (causallyReady) { - const expectedSeq = (clock[change.actor] || 0) + 1 - if (change.seq !== expectedSeq) { - throw new RangeError(`Expected seq ${expectedSeq}, got seq ${change.seq} from actor ${change.actor}`) - } - clock[change.actor] = change.seq - changeHashes.add(change.hash) - for (let dep of change.deps) heads.delete(dep) - heads.add(change.hash) - applied.push(change) +/** + * Inflate#onEnd(status) -> Void + * - status (Number): inflate status. 0 (Z_OK) on success, + * other if not. + * + * Called either after you tell inflate that the input stream is + * complete (Z_FINISH). By default - join collected chunks, + * free memory and fill `results` / `err` properties. + **/ +Inflate.prototype.onEnd = function (status) { + // On success - join + if (status === Z_OK) { + if (this.options.to === 'string') { + this.result = this.chunks.join(''); } else { - enqueued.push(change) + this.result = utils.flattenChunks(this.chunks); } } + this.chunks = []; + this.err = status; + this.msg = this.strm.msg; +}; - if (applied.length > 0) { - let changeState = {changes: applied, changeIndex: -1, objectIds} - readNextChangeOp(docState, changeState) - while (!changeState.done) applyOps(patches, changeState, docState) - - docState.heads = [...heads].sort() - docState.clock = clock - } - return [applied, enqueued] -} /** - * Scans the operations in a document and generates a patch that can be sent to the frontend to - * instantiate the current state of the document. `objectMeta` is mutated to contain information - * about the parent and children of each object in the document. - */ -function documentPatch(docState) { - for (let col of docState.blocks[0].columns) col.decoder.reset() - let propState = {}, docOp = null, blockIndex = 0 - let patches = {_root: {objectId: '_root', type: 'map', props: {}}} - let lastObjActor = null, lastObjCtr = null, objectId = '_root', elemVisible = false, listIndex = 0 - - while (true) { - ({ docOp, blockIndex } = readNextDocOp(docState, blockIndex)) - if (docOp === null) break - if (docOp[objActorIdx] !== lastObjActor || docOp[objCtrIdx] !== lastObjCtr) { - objectId = `${docOp[objCtrIdx]}@${docState.actorIds[docOp[objActorIdx]]}` - lastObjActor = docOp[objActorIdx] - lastObjCtr = docOp[objCtrIdx] - propState = {} - listIndex = 0 - elemVisible = false - } - - if (docOp[insertIdx] && elemVisible) { - elemVisible = false - listIndex++ - } - if (docOp[succNumIdx] === 0) elemVisible = true - if (docOp[idCtrIdx] > docState.maxOp) docState.maxOp = docOp[idCtrIdx] - for (let i = 0; i < docOp[succNumIdx]; i++) { - if (docOp[succCtrIdx][i] > docState.maxOp) docState.maxOp = docOp[succCtrIdx][i] - } - - updatePatchProperty(patches, null, objectId, docOp, docState, propState, listIndex, docOp[succNumIdx]) - } - return patches._root -} + * inflate(data[, options]) -> Uint8Array|String + * - data (Uint8Array|ArrayBuffer): input data to decompress. + * - options (Object): zlib inflate options. + * + * Decompress `data` with inflate/ungzip and `options`. Autodetect + * format via wrapper header by default. That's why we don't provide + * separate `ungzip` method. + * + * Supported options are: + * + * - windowBits + * + * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced) + * for more information. + * + * Sugar (options): + * + * - `raw` (Boolean) - say that we work with raw stream, if you don't wish to specify + * negative windowBits implicitly. + * - `to` (String) - if equal to 'string', then result will be converted + * from utf8 to utf16 (javascript) string. When string output requested, + * chunk length can differ from `chunkSize`, depending on content. + * + * + * ##### Example: + * + * ```javascript + * const pako = require('pako'); + * const input = pako.deflate(new Uint8Array([1,2,3,4,5,6,7,8,9])); + * let output; + * + * try { + * output = pako.inflate(input); + * } catch (err) { + * console.log(err); + * } + * ``` + **/ +function inflate(input, options) { + const inflator = new Inflate(options); -/** - * Takes an encoded document whose headers have been parsed using `decodeDocumentHeader()` and reads - * from it the list of changes. Returns the document's current vector clock, i.e. an object mapping - * each actor ID (as a hex string) to the number of changes seen from that actor. Also returns an - * array of the actorIds whose most recent change has no dependents (i.e. the actors that - * contributed the current heads of the document), and an array of encoders that has been - * initialised to contain the columns of the changes list. - */ -function readDocumentChanges(doc) { - const columns = makeDecoders(doc.changesColumns, DOCUMENT_COLUMNS) - const actorD = columns[0].decoder, seqD = columns[1].decoder - const depsNumD = columns[5].decoder, depsIndexD = columns[6].decoder - if (columns[0].columnId !== DOCUMENT_COLUMNS[0].columnId || DOCUMENT_COLUMNS[0].columnName !== 'actor' || - columns[1].columnId !== DOCUMENT_COLUMNS[1].columnId || DOCUMENT_COLUMNS[1].columnName !== 'seq' || - columns[5].columnId !== DOCUMENT_COLUMNS[5].columnId || DOCUMENT_COLUMNS[5].columnName !== 'depsNum' || - columns[6].columnId !== DOCUMENT_COLUMNS[6].columnId || DOCUMENT_COLUMNS[6].columnName !== 'depsIndex') { - throw new RangeError('unexpected columnId') - } + inflator.push(input); - let numChanges = 0, clock = {}, actorNums = [], headIndexes = new Set() - while (!actorD.done) { - const actorNum = actorD.readValue(), seq = seqD.readValue(), depsNum = depsNumD.readValue() - const actorId = doc.actorIds[actorNum] - if (seq !== 1 && seq !== clock[actorId] + 1) { - throw new RangeError(`Expected seq ${clock[actorId] + 1}, got ${seq} for actor ${actorId}`) - } - actorNums.push(actorNum) - clock[actorId] = seq - headIndexes.add(numChanges) - for (let j = 0; j < depsNum; j++) headIndexes.delete(depsIndexD.readValue()) - numChanges++ - } - const headActors = [...headIndexes].map(index => doc.actorIds[actorNums[index]]).sort() + // That will never happens, if you don't cheat with options :) + if (inflator.err) throw inflator.msg || msg[inflator.err]; - for (let col of columns) col.decoder.reset() - const encoders = columns.map(col => ({columnId: col.columnId, encoder: encoderByColumnId(col.columnId)})) - copyColumns(encoders, columns, numChanges) - return {clock, headActors, encoders, numChanges} + return inflator.result; } + /** - * Records the metadata about a change in the appropriate columns. - */ -function appendChange(columns, change, actorIds, changeIndexByHash) { - appendOperation(columns, DOCUMENT_COLUMNS, [ - actorIds.indexOf(change.actor), // actor - change.seq, // seq - change.maxOp, // maxOp - change.time, // time - change.message, // message - change.deps.length, // depsNum - change.deps.map(dep => changeIndexByHash[dep]), // depsIndex - change.extraBytes ? (change.extraBytes.byteLength << 4 | VALUE_TYPE.BYTES) : VALUE_TYPE.BYTES, // extraLen - change.extraBytes // extraRaw - ]) + * inflateRaw(data[, options]) -> Uint8Array|String + * - data (Uint8Array|ArrayBuffer): input data to decompress. + * - options (Object): zlib inflate options. + * + * The same as [[inflate]], but creates raw data, without wrapper + * (header and adler32 crc). + **/ +function inflateRaw(input, options) { + options = options || {}; + options.raw = true; + return inflate(input, options); } -class BackendDoc { - constructor(buffer) { - this.maxOp = 0 - this.haveHashGraph = false - this.changes = [] - this.changeIndexByHash = {} - this.dependenciesByHash = {} - this.dependentsByHash = {} - this.hashesByActor = {} - this.actorIds = [] - this.heads = [] - this.clock = {} - this.queue = [] - this.objectMeta = {_root: {parentObj: null, parentKey: null, opId: null, type: 'map', children: {}}} - - if (buffer) { - const doc = decodeDocumentHeader(buffer) - const {clock, headActors, encoders, numChanges} = readDocumentChanges(doc) - this.binaryDoc = buffer - this.changes = new Array(numChanges) - this.actorIds = doc.actorIds - this.heads = doc.heads - this.clock = clock - this.changesEncoders = encoders - this.extraBytes = doc.extraBytes - // If there is a single head, we can unambiguously point at the actorId and sequence number of - // the head hash without having to reconstruct the hash graph - if (doc.heads.length === 1 && headActors.length === 1) { - this.hashesByActor[headActors[0]] = [] - this.hashesByActor[headActors[0]][clock[headActors[0]] - 1] = doc.heads[0] - } +/** + * ungzip(data[, options]) -> Uint8Array|String + * - data (Uint8Array|ArrayBuffer): input data to decompress. + * - options (Object): zlib inflate options. + * + * Just shortcut to [[inflate]], because it autodetects format + * by header.content. Done for convenience. + **/ - // The encoded document gives each change an index, and expresses dependencies in terms of - // those indexes. Initialise the translation table from hash to index. - if (doc.heads.length === doc.headsIndexes.length) { - for (let i = 0; i < doc.heads.length; i++) { - this.changeIndexByHash[doc.heads[i]] = doc.headsIndexes[i] - } - } else if (doc.heads.length === 1) { - // If there is only one head, it must be the last change - this.changeIndexByHash[doc.heads[0]] = numChanges - 1 - } else { - // We know the heads hashes, but not their indexes - for (let head of doc.heads) this.changeIndexByHash[head] = -1 - } - this.blocks = [{columns: makeDecoders(doc.opsColumns, DOC_OPS_COLUMNS)}] - updateBlockMetadata(this.blocks[0], this.actorIds) - if (this.blocks[0].numOps > MAX_BLOCK_SIZE) { - this.blocks = splitBlock(this.blocks[0], this.actorIds) - } +module.exports.Inflate = Inflate; +module.exports.inflate = inflate; +module.exports.inflateRaw = inflateRaw; +module.exports.ungzip = inflate; +module.exports.constants = require('./zlib/constants'); - let docState = {blocks: this.blocks, actorIds: this.actorIds, objectMeta: this.objectMeta, maxOp: 0} - this.initPatch = documentPatch(docState) - this.maxOp = docState.maxOp +},{"./utils/common":68,"./utils/strings":69,"./zlib/constants":71,"./zlib/gzheader":74,"./zlib/inflate":76,"./zlib/messages":78,"./zlib/zstream":80}],68:[function(require,module,exports){ +'use strict'; - } else { - this.haveHashGraph = true - this.changesEncoders = DOCUMENT_COLUMNS.map(col => ({columnId: col.columnId, encoder: encoderByColumnId(col.columnId)})) - this.blocks = [{ - columns: makeDecoders([], DOC_OPS_COLUMNS), - bloom: new Uint8Array(BLOOM_FILTER_SIZE), - lastKey: {}, - numVisible: {}, - numOps: 0, - lastObjectActor: undefined, - lastObjectCtr: undefined, - firstVisibleActor: undefined, - firstVisibleCtr: undefined, - lastVisibleActor: undefined, - lastVisibleCtr: undefined - }] - } - } - /** - * Makes a copy of this BackendDoc that can be independently modified. - */ - clone() { - let copy = new BackendDoc() - copy.maxOp = this.maxOp - copy.haveHashGraph = this.haveHashGraph - copy.changes = this.changes.slice() - copy.changeIndexByHash = copyObject(this.changeIndexByHash) - copy.dependenciesByHash = copyObject(this.dependenciesByHash) - copy.dependentsByHash = Object.entries(this.dependentsByHash).reduce((acc, [k, v]) => { acc[k] = v.slice(); return acc }, {}) - copy.hashesByActor = Object.entries(this.hashesByActor).reduce((acc, [k, v]) => { acc[k] = v.slice(); return acc }, {}) - copy.actorIds = this.actorIds // immutable, no copying needed - copy.heads = this.heads // immutable, no copying needed - copy.clock = this.clock // immutable, no copying needed - copy.blocks = this.blocks // immutable, no copying needed - copy.objectMeta = this.objectMeta // immutable, no copying needed - copy.queue = this.queue // immutable, no copying needed - return copy - } +const _has = (obj, key) => { + return Object.prototype.hasOwnProperty.call(obj, key); +}; - /** - * Parses the changes given as Uint8Arrays in `changeBuffers`, and applies them to the current - * document. Returns a patch to apply to the frontend. If an exception is thrown, the document - * object is not modified. - */ - applyChanges(changeBuffers, isLocal = false) { - // decoded change has the form { actor, seq, startOp, time, message, deps, actorIds, hash, columns, buffer } - let decodedChanges = changeBuffers.map(buffer => { - const decoded = decodeChangeColumns(buffer) - decoded.buffer = buffer - return decoded - }) +module.exports.assign = function (obj /*from1, from2, from3, ...*/) { + const sources = Array.prototype.slice.call(arguments, 1); + while (sources.length) { + const source = sources.shift(); + if (!source) { continue; } - let patches = {_root: {objectId: '_root', type: 'map', props: {}}} - let docState = { - maxOp: this.maxOp, - changeIndexByHash: this.changeIndexByHash, - actorIds: this.actorIds, - heads: this.heads, - clock: this.clock, - blocks: this.blocks.slice(), - objectMeta: Object.assign({}, this.objectMeta) + if (typeof source !== 'object') { + throw new TypeError(source + 'must be non-object'); } - let queue = (this.queue.length === 0) ? decodedChanges : decodedChanges.concat(this.queue) - let allApplied = [], objectIds = new Set() - - while (true) { - const [applied, enqueued] = applyChanges(patches, queue, docState, objectIds) - queue = enqueued - if (applied.length > 0) allApplied = allApplied.concat(applied) - if (queue.length === 0) break - // If we are missing a dependency, and we haven't computed the hash graph yet, first compute - // the hashes to see if we actually have it already - if (applied.length === 0) { - if (!this.haveHashGraph) this.computeHashGraph(); else break + for (const p in source) { + if (_has(source, p)) { + obj[p] = source[p]; } } + } - setupPatches(patches, objectIds, docState) + return obj; +}; - // Update the document state only if `applyChanges` does not throw an exception - for (let change of allApplied) { - this.changes.push(change.buffer) - if (!this.hashesByActor[change.actor]) this.hashesByActor[change.actor] = [] - this.hashesByActor[change.actor][change.seq - 1] = change.hash - this.changeIndexByHash[change.hash] = this.changes.length - 1 - this.dependenciesByHash[change.hash] = change.deps - this.dependentsByHash[change.hash] = [] - for (let dep of change.deps) { - if (!this.dependentsByHash[dep]) this.dependentsByHash[dep] = [] - this.dependentsByHash[dep].push(change.hash) - } - appendChange(this.changesEncoders, change, docState.actorIds, this.changeIndexByHash) - } - this.maxOp = docState.maxOp - this.actorIds = docState.actorIds - this.heads = docState.heads - this.clock = docState.clock - this.blocks = docState.blocks - this.objectMeta = docState.objectMeta - this.queue = queue - this.binaryDoc = null - this.initPatch = null +// Join array of chunks to single array. +module.exports.flattenChunks = (chunks) => { + // calculate data length + let len = 0; - let patch = { - maxOp: this.maxOp, clock: this.clock, deps: this.heads, - pendingChanges: this.queue.length, diffs: patches._root - } - if (isLocal && decodedChanges.length === 1) { - patch.actor = decodedChanges[0].actor - patch.seq = decodedChanges[0].seq - } - return patch + for (let i = 0, l = chunks.length; i < l; i++) { + len += chunks[i].length; } - /** - * Reconstructs the full change history of a document, and initialises the variables that allow us - * to traverse the hash graph of changes and their dependencies. When a compressed document is - * loaded we defer the computation of this hash graph to make loading faster, but if the hash - * graph is later needed (e.g. for the sync protocol), this function fills it in. - */ - computeHashGraph() { - const binaryDoc = this.save() - this.haveHashGraph = true - this.changes = [] - this.changeIndexByHash = {} - this.dependenciesByHash = {} - this.dependentsByHash = {} - this.hashesByActor = {} - this.clock = {} + // join chunks + const result = new Uint8Array(len); - for (let change of decodeChanges([binaryDoc])) { - const binaryChange = encodeChange(change) // TODO: avoid decoding and re-encoding again - this.changes.push(binaryChange) - this.changeIndexByHash[change.hash] = this.changes.length - 1 - this.dependenciesByHash[change.hash] = change.deps - this.dependentsByHash[change.hash] = [] - for (let dep of change.deps) this.dependentsByHash[dep].push(change.hash) - if (change.seq === 1) this.hashesByActor[change.actor] = [] - this.hashesByActor[change.actor].push(change.hash) - const expectedSeq = (this.clock[change.actor] || 0) + 1 - if (change.seq !== expectedSeq) { - throw new RangeError(`Expected seq ${expectedSeq}, got seq ${change.seq} from actor ${change.actor}`) - } - this.clock[change.actor] = change.seq - } + for (let i = 0, pos = 0, l = chunks.length; i < l; i++) { + let chunk = chunks[i]; + result.set(chunk, pos); + pos += chunk.length; } - /** - * Returns all the changes that need to be sent to another replica. `haveDeps` is a list of change - * hashes (as hex strings) of the heads that the other replica has. The changes in `haveDeps` and - * any of their transitive dependencies will not be returned; any changes later than or concurrent - * to the hashes in `haveDeps` will be returned. If `haveDeps` is an empty array, all changes are - * returned. Throws an exception if any of the given hashes are not known to this replica. - */ - getChanges(haveDeps) { - if (!this.haveHashGraph) this.computeHashGraph() + return result; +}; - // If the other replica has nothing, return all changes in history order - if (haveDeps.length === 0) { - return this.changes.slice() - } +},{}],69:[function(require,module,exports){ +// String encode/decode helpers +'use strict'; - // Fast path for the common case where all new changes depend only on haveDeps - let stack = [], seenHashes = {}, toReturn = [] - for (let hash of haveDeps) { - seenHashes[hash] = true - const successors = this.dependentsByHash[hash] - if (!successors) throw new RangeError(`hash not found: ${hash}`) - stack.push(...successors) - } - // Depth-first traversal of the hash graph to find all changes that depend on `haveDeps` - while (stack.length > 0) { - const hash = stack.pop() - seenHashes[hash] = true - toReturn.push(hash) - if (!this.dependenciesByHash[hash].every(dep => seenHashes[dep])) { - // If a change depends on a hash we have not seen, abort the traversal and fall back to the - // slower algorithm. This will sometimes abort even if all new changes depend on `haveDeps`, - // because our depth-first traversal is not necessarily a topological sort of the graph. - break - } - stack.push(...this.dependentsByHash[hash]) - } +// Quick check if we can use fast array to bin string conversion +// +// - apply(Array) can fail on Android 2.2 +// - apply(Uint8Array) can fail on iOS 5.1 Safari +// +let STR_APPLY_UIA_OK = true; - // If the traversal above has encountered all the heads, and was not aborted early due to - // a missing dependency, then the set of changes it has found is complete, so we can return it - if (stack.length === 0 && this.heads.every(head => seenHashes[head])) { - return toReturn.map(hash => this.changes[this.changeIndexByHash[hash]]) - } +try { String.fromCharCode.apply(null, new Uint8Array(1)); } catch (__) { STR_APPLY_UIA_OK = false; } - // If we haven't encountered all of the heads, we have to search harder. This will happen if - // changes were added that are concurrent to `haveDeps` - stack = haveDeps.slice() - seenHashes = {} - while (stack.length > 0) { - const hash = stack.pop() - if (!seenHashes[hash]) { - const deps = this.dependenciesByHash[hash] - if (!deps) throw new RangeError(`hash not found: ${hash}`) - stack.push(...deps) - seenHashes[hash] = true - } - } - return this.changes.filter(change => !seenHashes[decodeChangeMeta(change, true).hash]) +// Table with utf8 lengths (calculated by first byte of sequence) +// Note, that 5 & 6-byte values and some 4-byte values can not be represented in JS, +// because max possible codepoint is 0x10ffff +const _utf8len = new Uint8Array(256); +for (let q = 0; q < 256; q++) { + _utf8len[q] = (q >= 252 ? 6 : q >= 248 ? 5 : q >= 240 ? 4 : q >= 224 ? 3 : q >= 192 ? 2 : 1); +} +_utf8len[254] = _utf8len[254] = 1; // Invalid sequence start + + +// convert string to array (typed, when possible) +module.exports.string2buf = (str) => { + if (typeof TextEncoder === 'function' && TextEncoder.prototype.encode) { + return new TextEncoder().encode(str); } - /** - * Returns all changes that are present in this BackendDoc, but not present in the `other` - * BackendDoc. - */ - getChangesAdded(other) { - if (!this.haveHashGraph) this.computeHashGraph() + let buf, c, c2, m_pos, i, str_len = str.length, buf_len = 0; - // Depth-first traversal from the heads through the dependency graph, - // until we reach a change that is already present in opSet1 - let stack = this.heads.slice(), seenHashes = {}, toReturn = [] - while (stack.length > 0) { - const hash = stack.pop() - if (!seenHashes[hash] && other.changeIndexByHash[hash] === undefined) { - seenHashes[hash] = true - toReturn.push(hash) - stack.push(...this.dependenciesByHash[hash]) + // count binary size + for (m_pos = 0; m_pos < str_len; m_pos++) { + c = str.charCodeAt(m_pos); + if ((c & 0xfc00) === 0xd800 && (m_pos + 1 < str_len)) { + c2 = str.charCodeAt(m_pos + 1); + if ((c2 & 0xfc00) === 0xdc00) { + c = 0x10000 + ((c - 0xd800) << 10) + (c2 - 0xdc00); + m_pos++; } } - - // Return those changes in the reverse of the order in which the depth-first search - // found them. This is not necessarily a topological sort, but should usually be close. - return toReturn.reverse().map(hash => this.changes[this.changeIndexByHash[hash]]) - } - - getChangeByHash(hash) { - if (!this.haveHashGraph) this.computeHashGraph() - return this.changes[this.changeIndexByHash[hash]] + buf_len += c < 0x80 ? 1 : c < 0x800 ? 2 : c < 0x10000 ? 3 : 4; } - /** - * Returns the hashes of any missing dependencies, i.e. where we have tried to apply a change that - * has a dependency on a change we have not seen. - * - * If the argument `heads` is given (an array of hexadecimal strings representing hashes as - * returned by `getHeads()`), this function also ensures that all of those hashes resolve to - * either a change that has been applied to the document, or that has been enqueued for later - * application once missing dependencies have arrived. Any missing heads hashes are included in - * the returned array. - */ - getMissingDeps(heads = []) { - if (!this.haveHashGraph) this.computeHashGraph() + // allocate buffer + buf = new Uint8Array(buf_len); - let allDeps = new Set(heads), inQueue = new Set() - for (let change of this.queue) { - inQueue.add(change.hash) - for (let dep of change.deps) allDeps.add(dep) + // convert + for (i = 0, m_pos = 0; i < buf_len; m_pos++) { + c = str.charCodeAt(m_pos); + if ((c & 0xfc00) === 0xd800 && (m_pos + 1 < str_len)) { + c2 = str.charCodeAt(m_pos + 1); + if ((c2 & 0xfc00) === 0xdc00) { + c = 0x10000 + ((c - 0xd800) << 10) + (c2 - 0xdc00); + m_pos++; + } } - - let missing = [] - for (let hash of allDeps) { - if (this.changeIndexByHash[hash] === undefined && !inQueue.has(hash)) missing.push(hash) + if (c < 0x80) { + /* one byte */ + buf[i++] = c; + } else if (c < 0x800) { + /* two bytes */ + buf[i++] = 0xC0 | (c >>> 6); + buf[i++] = 0x80 | (c & 0x3f); + } else if (c < 0x10000) { + /* three bytes */ + buf[i++] = 0xE0 | (c >>> 12); + buf[i++] = 0x80 | (c >>> 6 & 0x3f); + buf[i++] = 0x80 | (c & 0x3f); + } else { + /* four bytes */ + buf[i++] = 0xf0 | (c >>> 18); + buf[i++] = 0x80 | (c >>> 12 & 0x3f); + buf[i++] = 0x80 | (c >>> 6 & 0x3f); + buf[i++] = 0x80 | (c & 0x3f); } - return missing.sort() } - /** - * Serialises the current document state into a single byte array. - */ - save() { - if (this.binaryDoc) return this.binaryDoc + return buf; +}; - // Getting the byte array for the changes columns finalises their encoders, after which we can - // no longer append values to them. We therefore copy their data over to fresh encoders. - const newEncoders = this.changesEncoders.map(col => ({columnId: col.columnId, encoder: encoderByColumnId(col.columnId)})) - const decoders = this.changesEncoders.map(col => { - const decoder = decoderByColumnId(col.columnId, col.encoder.buffer) - return {columnId: col.columnId, decoder} - }) - copyColumns(newEncoders, decoders, this.changes.length) - - this.binaryDoc = encodeDocumentHeader({ - changesColumns: this.changesEncoders, - opsColumns: concatBlocks(this.blocks), - actorIds: this.actorIds, // TODO: sort actorIds (requires transforming all actorId columns in opsColumns) - heads: this.heads, - headsIndexes: this.heads.map(hash => this.changeIndexByHash[hash]), - extraBytes: this.extraBytes - }) - this.changesEncoders = newEncoders - return this.binaryDoc +// Helper +const buf2binstring = (buf, len) => { + // On Chrome, the arguments in a function call that are allowed is `65534`. + // If the length of the buffer is smaller than that, we can use this optimization, + // otherwise we will take a slower path. + if (len < 65534) { + if (buf.subarray && STR_APPLY_UIA_OK) { + return String.fromCharCode.apply(null, buf.length === len ? buf : buf.subarray(0, len)); + } } - /** - * Returns a patch from which we can initialise the current state of the backend. - */ - getPatch() { - const objectMeta = {_root: {parentObj: null, parentKey: null, opId: null, type: 'map', children: {}}} - const docState = {blocks: this.blocks, actorIds: this.actorIds, objectMeta, maxOp: 0} - const diffs = this.initPatch ? this.initPatch : documentPatch(docState) - return { - maxOp: this.maxOp, clock: this.clock, deps: this.heads, - pendingChanges: this.queue.length, diffs - } + let result = ''; + for (let i = 0; i < len; i++) { + result += String.fromCharCode(buf[i]); } -} + return result; +}; -module.exports = { MAX_BLOCK_SIZE, BackendDoc, bloomFilterContains } -},{"../src/common":87,"./columnar":49}],53:[function(require,module,exports){ -/** - * Implementation of the data synchronisation protocol that brings a local and a remote document - * into the same state. This is typically used when two nodes have been disconnected for some time, - * and need to exchange any changes that happened while they were disconnected. The two nodes that - * are syncing could be client and server, or server and client, or two peers with symmetric roles. - * - * The protocol is based on this paper: Martin Kleppmann and Heidi Howard. Byzantine Eventual - * Consistency and the Fundamental Limits of Peer-to-Peer Databases. https://arxiv.org/abs/2012.00472 - * - * The protocol assumes that every time a node successfully syncs with another node, it remembers - * the current heads (as returned by `Backend.getHeads()`) after the last sync with that node. The - * next time we try to sync with the same node, we start from the assumption that the other node's - * document version is no older than the outcome of the last sync, so we only need to exchange any - * changes that are more recent than the last sync. This assumption may not be true if the other - * node did not correctly persist its state (perhaps it crashed before writing the result of the - * last sync to disk), and we fall back to sending the entire document in this case. - */ +// convert array to string +module.exports.buf2string = (buf, max) => { + const len = max || buf.length; -const Backend = require('./backend') -const { hexStringToBytes, bytesToHexString, Encoder, Decoder } = require('./encoding') -const { decodeChangeMeta } = require('./columnar') -const { copyObject } = require('../src/common') + if (typeof TextDecoder === 'function' && TextDecoder.prototype.decode) { + return new TextDecoder().decode(buf.subarray(0, max)); + } -const HASH_SIZE = 32 // 256 bits = 32 bytes -const MESSAGE_TYPE_SYNC = 0x42 // first byte of a sync message, for identification -const PEER_STATE_TYPE = 0x43 // first byte of an encoded peer state, for identification + let i, out; -// These constants correspond to a 1% false positive rate. The values can be changed without -// breaking compatibility of the network protocol, since the parameters used for a particular -// Bloom filter are encoded in the wire format. -const BITS_PER_ENTRY = 10, NUM_PROBES = 7 + // Reserve max possible length (2 words per char) + // NB: by unknown reasons, Array is significantly faster for + // String.fromCharCode.apply than Uint16Array. + const utf16buf = new Array(len * 2); -/** - * A Bloom filter implementation that can be serialised to a byte array for transmission - * over a network. The entries that are added are assumed to already be SHA-256 hashes, - * so this implementation does not perform its own hashing. - */ -class BloomFilter { - constructor (arg) { - if (Array.isArray(arg)) { - // arg is an array of SHA256 hashes in hexadecimal encoding - this.numEntries = arg.length - this.numBitsPerEntry = BITS_PER_ENTRY - this.numProbes = NUM_PROBES - this.bits = new Uint8Array(Math.ceil(this.numEntries * this.numBitsPerEntry / 8)) - for (let hash of arg) this.addHash(hash) - } else if (arg instanceof Uint8Array) { - if (arg.byteLength === 0) { - this.numEntries = 0 - this.numBitsPerEntry = 0 - this.numProbes = 0 - this.bits = arg - } else { - const decoder = new Decoder(arg) - this.numEntries = decoder.readUint32() - this.numBitsPerEntry = decoder.readUint32() - this.numProbes = decoder.readUint32() - this.bits = decoder.readRawBytes(Math.ceil(this.numEntries * this.numBitsPerEntry / 8)) - } - } else { - throw new TypeError('invalid argument') - } - } + for (out = 0, i = 0; i < len;) { + let c = buf[i++]; + // quick process ascii + if (c < 0x80) { utf16buf[out++] = c; continue; } - /** - * Returns the Bloom filter state, encoded as a byte array. - */ - get bytes() { - if (this.numEntries === 0) return new Uint8Array(0) - const encoder = new Encoder() - encoder.appendUint32(this.numEntries) - encoder.appendUint32(this.numBitsPerEntry) - encoder.appendUint32(this.numProbes) - encoder.appendRawBytes(this.bits) - return encoder.buffer - } + let c_len = _utf8len[c]; + // skip 5 & 6 byte codes + if (c_len > 4) { utf16buf[out++] = 0xfffd; i += c_len - 1; continue; } - /** - * Given a SHA-256 hash (as hex string), returns an array of probe indexes indicating which bits - * in the Bloom filter need to be tested or set for this particular entry. We do this by - * interpreting the first 12 bytes of the hash as three little-endian 32-bit unsigned integers, - * and then using triple hashing to compute the probe indexes. The algorithm comes from: - * - * Peter C. Dillinger and Panagiotis Manolios. Bloom Filters in Probabilistic Verification. - * 5th International Conference on Formal Methods in Computer-Aided Design (FMCAD), November 2004. - * http://www.ccis.northeastern.edu/home/pete/pub/bloom-filters-verification.pdf - */ - getProbes(hash) { - const hashBytes = hexStringToBytes(hash), modulo = 8 * this.bits.byteLength - if (hashBytes.byteLength !== 32) throw new RangeError(`Not a 256-bit hash: ${hash}`) - // on the next three lines, the right shift means interpret value as unsigned - let x = ((hashBytes[0] | hashBytes[1] << 8 | hashBytes[2] << 16 | hashBytes[3] << 24) >>> 0) % modulo - let y = ((hashBytes[4] | hashBytes[5] << 8 | hashBytes[6] << 16 | hashBytes[7] << 24) >>> 0) % modulo - let z = ((hashBytes[8] | hashBytes[9] << 8 | hashBytes[10] << 16 | hashBytes[11] << 24) >>> 0) % modulo - const probes = [x] - for (let i = 1; i < this.numProbes; i++) { - x = (x + y) % modulo - y = (y + z) % modulo - probes.push(x) + // apply mask on first byte + c &= c_len === 2 ? 0x1f : c_len === 3 ? 0x0f : 0x07; + // join the rest + while (c_len > 1 && i < len) { + c = (c << 6) | (buf[i++] & 0x3f); + c_len--; } - return probes - } - /** - * Sets the Bloom filter bits corresponding to a given SHA-256 hash (given as hex string). - */ - addHash(hash) { - for (let probe of this.getProbes(hash)) { - this.bits[probe >>> 3] |= 1 << (probe & 7) - } - } + // terminated by end of string? + if (c_len > 1) { utf16buf[out++] = 0xfffd; continue; } - /** - * Tests whether a given SHA-256 hash (given as hex string) is contained in the Bloom filter. - */ - containsHash(hash) { - if (this.numEntries === 0) return false - for (let probe of this.getProbes(hash)) { - if ((this.bits[probe >>> 3] & (1 << (probe & 7))) === 0) { - return false - } + if (c < 0x10000) { + utf16buf[out++] = c; + } else { + c -= 0x10000; + utf16buf[out++] = 0xd800 | ((c >> 10) & 0x3ff); + utf16buf[out++] = 0xdc00 | (c & 0x3ff); } - return true - } -} - -/** - * Encodes a sorted array of SHA-256 hashes (as hexadecimal strings) into a byte array. - */ -function encodeHashes(encoder, hashes) { - if (!Array.isArray(hashes)) throw new TypeError('hashes must be an array') - encoder.appendUint32(hashes.length) - for (let i = 0; i < hashes.length; i++) { - if (i > 0 && hashes[i - 1] >= hashes[i]) throw new RangeError('hashes must be sorted') - const bytes = hexStringToBytes(hashes[i]) - if (bytes.byteLength !== HASH_SIZE) throw new TypeError('heads hashes must be 256 bits') - encoder.appendRawBytes(bytes) } -} -/** - * Decodes a byte array in the format returned by encodeHashes(), and returns its content as an - * array of hex strings. - */ -function decodeHashes(decoder) { - let length = decoder.readUint32(), hashes = [] - for (let i = 0; i < length; i++) { - hashes.push(bytesToHexString(decoder.readRawBytes(HASH_SIZE))) - } - return hashes -} + return buf2binstring(utf16buf, out); +}; -/** - * Takes a sync message of the form `{heads, need, have, changes}` and encodes it as a byte array for - * transmission. - */ -function encodeSyncMessage(message) { - const encoder = new Encoder() - encoder.appendByte(MESSAGE_TYPE_SYNC) - encodeHashes(encoder, message.heads) - encodeHashes(encoder, message.need) - encoder.appendUint32(message.have.length) - for (let have of message.have) { - encodeHashes(encoder, have.lastSync) - encoder.appendPrefixedBytes(have.bloom) - } - encoder.appendUint32(message.changes.length) - for (let change of message.changes) { - encoder.appendPrefixedBytes(change) - } - return encoder.buffer -} -/** - * Takes a binary-encoded sync message and decodes it into the form `{heads, need, have, changes}`. - */ -function decodeSyncMessage(bytes) { - const decoder = new Decoder(bytes) - const messageType = decoder.readByte() - if (messageType !== MESSAGE_TYPE_SYNC) { - throw new RangeError(`Unexpected message type: ${messageType}`) - } - const heads = decodeHashes(decoder) - const need = decodeHashes(decoder) - const haveCount = decoder.readUint32() - let message = {heads, need, have: [], changes: []} - for (let i = 0; i < haveCount; i++) { - const lastSync = decodeHashes(decoder) - const bloom = decoder.readPrefixedBytes(decoder) - message.have.push({lastSync, bloom}) - } - const changeCount = decoder.readUint32() - for (let i = 0; i < changeCount; i++) { - const change = decoder.readPrefixedBytes() - message.changes.push(change) - } - // Ignore any trailing bytes -- they can be used for extensions by future versions of the protocol - return message -} +// Calculate max possible position in utf8 buffer, +// that will not break sequence. If that's not possible +// - (very small limits) return max size as is. +// +// buf[] - utf8 bytes array +// max - length limit (mandatory); +module.exports.utf8border = (buf, max) => { -/** - * Takes a SyncState and encodes as a byte array those parts of the state that should persist across - * an application restart or disconnect and reconnect. The ephemeral parts of the state that should - * be cleared on reconnect are not encoded. - */ -function encodeSyncState(syncState) { - const encoder = new Encoder() - encoder.appendByte(PEER_STATE_TYPE) - encodeHashes(encoder, syncState.sharedHeads) - return encoder.buffer -} + max = max || buf.length; + if (max > buf.length) { max = buf.length; } -/** - * Takes a persisted peer state as encoded by `encodeSyncState` and decodes it into a SyncState - * object. The parts of the peer state that were not encoded are initialised with default values. - */ -function decodeSyncState(bytes) { - const decoder = new Decoder(bytes) - const recordType = decoder.readByte() - if (recordType !== PEER_STATE_TYPE) { - throw new RangeError(`Unexpected record type: ${recordType}`) - } - const sharedHeads = decodeHashes(decoder) - return Object.assign(initSyncState(), { sharedHeads }) -} + // go back from last position, until start of sequence found + let pos = max - 1; + while (pos >= 0 && (buf[pos] & 0xC0) === 0x80) { pos--; } -/** - * Constructs a Bloom filter containing all changes that are not one of the hashes in - * `lastSync` or its transitive dependencies. In other words, the filter contains those - * changes that have been applied since the version identified by `lastSync`. Returns - * an object of the form `{lastSync, bloom}` as required for the `have` field of a sync - * message. - */ -function makeBloomFilter(backend, lastSync) { - const newChanges = Backend.getChanges(backend, lastSync) - const hashes = newChanges.map(change => decodeChangeMeta(change, true).hash) - return {lastSync, bloom: new BloomFilter(hashes).bytes} -} + // Very small and broken sequence, + // return max, because we should return something anyway. + if (pos < 0) { return max; } -/** - * Call this function when a sync message is received from another node. The `message` argument - * needs to already have been decoded using `decodeSyncMessage()`. This function determines the - * changes that we need to send to the other node in response. Returns an array of changes (as - * byte arrays). - */ -function getChangesToSend(backend, have, need) { - if (have.length === 0) { - return need.map(hash => Backend.getChangeByHash(backend, hash)).filter(change => change !== undefined) - } + // If we came to start of buffer - that means buffer is too small, + // return max too. + if (pos === 0) { return max; } - let lastSyncHashes = {}, bloomFilters = [] - for (let h of have) { - for (let hash of h.lastSync) lastSyncHashes[hash] = true - bloomFilters.push(new BloomFilter(h.bloom)) - } + return (pos + _utf8len[buf[pos]] > max) ? pos : max; +}; - // Get all changes that were added since the last sync - const changes = Backend.getChanges(backend, Object.keys(lastSyncHashes)) - .map(change => decodeChangeMeta(change, true)) +},{}],70:[function(require,module,exports){ +'use strict'; - let changeHashes = {}, dependents = {}, hashesToSend = {} - for (let change of changes) { - changeHashes[change.hash] = true +// Note: adler32 takes 12% for level 0 and 2% for level 6. +// It isn't worth it to make additional optimizations as in original. +// Small size is preferable. - // For each change, make a list of changes that depend on it - for (let dep of change.deps) { - if (!dependents[dep]) dependents[dep] = [] - dependents[dep].push(change.hash) - } +// (C) 1995-2013 Jean-loup Gailly and Mark Adler +// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. - // Exclude any change hashes contained in one or more Bloom filters - if (bloomFilters.every(bloom => !bloom.containsHash(change.hash))) { - hashesToSend[change.hash] = true - } - } +const adler32 = (adler, buf, len, pos) => { + let s1 = (adler & 0xffff) |0, + s2 = ((adler >>> 16) & 0xffff) |0, + n = 0; - // Include any changes that depend on a Bloom-negative change - let stack = Object.keys(hashesToSend) - while (stack.length > 0) { - const hash = stack.pop() - if (dependents[hash]) { - for (let dep of dependents[hash]) { - if (!hashesToSend[dep]) { - hashesToSend[dep] = true - stack.push(dep) - } - } - } - } + while (len !== 0) { + // Set limit ~ twice less than 5552, to keep + // s2 in 31-bits, because we force signed ints. + // in other case %= will fail. + n = len > 2000 ? 2000 : len; + len -= n; - // Include any explicitly requested changes - let changesToSend = [] - for (let hash of need) { - hashesToSend[hash] = true - if (!changeHashes[hash]) { // Change is not among those returned by getMissingChanges()? - const change = Backend.getChangeByHash(backend, hash) - if (change) changesToSend.push(change) - } - } + do { + s1 = (s1 + buf[pos++]) |0; + s2 = (s2 + s1) |0; + } while (--n); - // Return changes in the order they were returned by getMissingChanges() - for (let change of changes) { - if (hashesToSend[change.hash]) changesToSend.push(change.change) + s1 %= 65521; + s2 %= 65521; } - return changesToSend -} -function initSyncState() { - return { - sharedHeads: [], - lastSentHeads: [], - theirHeads: null, - theirNeed: null, - theirHave: null, - sentHashes: {}, - } -} + return (s1 | (s2 << 16)) |0; +}; -function compareArrays(a, b) { - return (a.length === b.length) && a.every((v, i) => v === b[i]) -} -/** - * Given a backend and what we believe to be the state of our peer, generate a message which tells - * them about we have and includes any changes we believe they need - */ -function generateSyncMessage(backend, syncState) { - if (!backend) { - throw new Error("generateSyncMessage called with no Automerge document") - } - if (!syncState) { - throw new Error("generateSyncMessage requires a syncState, which can be created with initSyncState()") - } +module.exports = adler32; - let { sharedHeads, lastSentHeads, theirHeads, theirNeed, theirHave, sentHashes } = syncState - const ourHeads = Backend.getHeads(backend) +},{}],71:[function(require,module,exports){ +'use strict'; - // Hashes to explicitly request from the remote peer: any missing dependencies of unapplied - // changes, and any of the remote peer's heads that we don't know about - const ourNeed = Backend.getMissingDeps(backend, theirHeads || []) +// (C) 1995-2013 Jean-loup Gailly and Mark Adler +// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. - // There are two reasons why ourNeed may be nonempty: 1. we might be missing dependencies due to - // Bloom filter false positives; 2. we might be missing heads that the other peer mentioned - // because they (intentionally) only sent us a subset of changes. In case 1, we leave the `have` - // field of the message empty because we just want to fill in the missing dependencies for now. - // In case 2, or if ourNeed is empty, we send a Bloom filter to request any unsent changes. - let ourHave = [] - if (!theirHeads || ourNeed.every(hash => theirHeads.includes(hash))) { - ourHave = [makeBloomFilter(backend, sharedHeads)] - } +module.exports = { - // Fall back to a full re-sync if the sender's last sync state includes hashes - // that we don't know. This could happen if we crashed after the last sync and - // failed to persist changes that the other node already sent us. - if (theirHave && theirHave.length > 0) { - const lastSync = theirHave[0].lastSync - if (!lastSync.every(hash => Backend.getChangeByHash(backend, hash))) { - // we need to queue them to send us a fresh sync message, the one they sent is uninteligible so we don't know what they need - const resetMsg = {heads: ourHeads, need: [], have: [{ lastSync: [], bloom: new Uint8Array(0) }], changes: []} - return [syncState, encodeSyncMessage(resetMsg)] - } - } + /* Allowed flush values; see deflate() and inflate() below for details */ + Z_NO_FLUSH: 0, + Z_PARTIAL_FLUSH: 1, + Z_SYNC_FLUSH: 2, + Z_FULL_FLUSH: 3, + Z_FINISH: 4, + Z_BLOCK: 5, + Z_TREES: 6, - // XXX: we should limit ourselves to only sending a subset of all the messages, probably limited by a total message size - // these changes should ideally be RLE encoded but we haven't implemented that yet. - let changesToSend = Array.isArray(theirHave) && Array.isArray(theirNeed) ? getChangesToSend(backend, theirHave, theirNeed) : [] + /* Return codes for the compression/decompression functions. Negative values + * are errors, positive values are used for special but normal events. + */ + Z_OK: 0, + Z_STREAM_END: 1, + Z_NEED_DICT: 2, + Z_ERRNO: -1, + Z_STREAM_ERROR: -2, + Z_DATA_ERROR: -3, + Z_MEM_ERROR: -4, + Z_BUF_ERROR: -5, + //Z_VERSION_ERROR: -6, - // If the heads are equal, we're in sync and don't need to do anything further - const headsUnchanged = Array.isArray(lastSentHeads) && compareArrays(ourHeads, lastSentHeads) - const headsEqual = Array.isArray(theirHeads) && compareArrays(ourHeads, theirHeads) - if (headsUnchanged && headsEqual && changesToSend.length === 0) { - // no need to send a sync message if we know we're synced! - return [syncState, null] - } - - // TODO: this recomputes the SHA-256 hash of each change; we should restructure this to avoid the - // unnecessary recomputation - changesToSend = changesToSend.filter(change => !sentHashes[decodeChangeMeta(change, true).hash]) + /* compression levels */ + Z_NO_COMPRESSION: 0, + Z_BEST_SPEED: 1, + Z_BEST_COMPRESSION: 9, + Z_DEFAULT_COMPRESSION: -1, - // Regular response to a sync message: send any changes that the other node - // doesn't have. We leave the "have" field empty because the previous message - // generated by `syncStart` already indicated what changes we have. - const syncMessage = {heads: ourHeads, have: ourHave, need: ourNeed, changes: changesToSend} - if (changesToSend.length > 0) { - sentHashes = copyObject(sentHashes) - for (const change of changesToSend) { - sentHashes[decodeChangeMeta(change, true).hash] = true - } - } - syncState = Object.assign({}, syncState, {lastSentHeads: ourHeads, sentHashes}) - return [syncState, encodeSyncMessage(syncMessage)] -} + Z_FILTERED: 1, + Z_HUFFMAN_ONLY: 2, + Z_RLE: 3, + Z_FIXED: 4, + Z_DEFAULT_STRATEGY: 0, -/** - * Computes the heads that we share with a peer after we have just received some changes from that - * peer and applied them. This may not be sufficient to bring our heads in sync with the other - * peer's heads, since they may have only sent us a subset of their outstanding changes. - * - * `myOldHeads` are the local heads before the most recent changes were applied, `myNewHeads` are - * the local heads after those changes were applied, and `ourOldSharedHeads` is the previous set of - * shared heads. Applying the changes will have replaced some heads with others, but some heads may - * have remained unchanged (because they are for branches on which no changes have been added). Any - * such unchanged heads remain in the sharedHeads. Any sharedHeads that were replaced by applying - * changes are also replaced as sharedHeads. This is safe because if we received some changes from - * another peer, that means that peer had those changes, and therefore we now both know about them. - */ -function advanceHeads(myOldHeads, myNewHeads, ourOldSharedHeads) { - const newHeads = myNewHeads.filter((head) => !myOldHeads.includes(head)) - const commonHeads = ourOldSharedHeads.filter((head) => myNewHeads.includes(head)) - const advancedHeads = [...new Set([...newHeads, ...commonHeads])].sort() - return advancedHeads -} + /* Possible values of the data_type field (though see inflate()) */ + Z_BINARY: 0, + Z_TEXT: 1, + //Z_ASCII: 1, // = Z_TEXT (deprecated) + Z_UNKNOWN: 2, + /* The deflate compression method */ + Z_DEFLATED: 8 + //Z_NULL: null // Use -1 or null inline, depending on var type +}; -/** - * Given a backend, a message message and the state of our peer, apply any changes, update what - * we believe about the peer, and (if there were applied changes) produce a patch for the frontend - */ -function receiveSyncMessage(backend, oldSyncState, binaryMessage) { - if (!backend) { - throw new Error("generateSyncMessage called with no Automerge document") - } - if (!oldSyncState) { - throw new Error("generateSyncMessage requires a syncState, which can be created with initSyncState()") - } +},{}],72:[function(require,module,exports){ +'use strict'; - let { sharedHeads, lastSentHeads, sentHashes } = oldSyncState, patch = null - const message = decodeSyncMessage(binaryMessage) - const beforeHeads = Backend.getHeads(backend) +// Note: we can't get significant speed boost here. +// So write code to minimize size - no pregenerated tables +// and array tools dependencies. - // If we received changes, we try to apply them to the document. There may still be missing - // dependencies due to Bloom filter false positives, in which case the backend will enqueue the - // changes without applying them. The set of changes may also be incomplete if the sender decided - // to break a large set of changes into chunks. - if (message.changes.length > 0) { - [backend, patch] = Backend.applyChanges(backend, message.changes) - sharedHeads = advanceHeads(beforeHeads, Backend.getHeads(backend), sharedHeads) - } +// (C) 1995-2013 Jean-loup Gailly and Mark Adler +// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. - // If heads are equal, indicate we don't need to send a response message - if (message.changes.length === 0 && compareArrays(message.heads, beforeHeads)) { - lastSentHeads = message.heads - } +// Use ordinary array, since untyped makes no boost here +const makeTable = () => { + let c, table = []; - // If all of the remote heads are known to us, that means either our heads are equal, or we are - // ahead of the remote peer. In this case, take the remote heads to be our shared heads. - const knownHeads = message.heads.filter(head => Backend.getChangeByHash(backend, head)) - if (knownHeads.length === message.heads.length) { - sharedHeads = message.heads - // If the remote peer has lost all its data, reset our state to perform a full resync - if (message.heads.length === 0) { - lastSentHeads = [] - sentHashes = [] + for (var n = 0; n < 256; n++) { + c = n; + for (var k = 0; k < 8; k++) { + c = ((c & 1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1)); } - } else { - // If some remote heads are unknown to us, we add all the remote heads we know to - // sharedHeads, but don't remove anything from sharedHeads. This might cause sharedHeads to - // contain some redundant hashes (where one hash is actually a transitive dependency of - // another), but this will be cleared up as soon as we know all the remote heads. - sharedHeads = [...new Set(knownHeads.concat(sharedHeads))].sort() + table[n] = c; } - const syncState = { - sharedHeads, // what we have in common to generate an efficient bloom filter - lastSentHeads, - theirHave: message.have, // the information we need to calculate the changes they need - theirHeads: message.heads, - theirNeed: message.need, - sentHashes - } - return [backend, syncState, patch] -} + return table; +}; -module.exports = { - receiveSyncMessage, generateSyncMessage, - encodeSyncMessage, decodeSyncMessage, - initSyncState, encodeSyncState, decodeSyncState, - BloomFilter // BloomFilter is a private API, exported only for testing purposes -} +// Create table on load. Just 255 signed longs. Not a problem. +const crcTable = new Uint32Array(makeTable()); -},{"../src/common":87,"./backend":48,"./columnar":49,"./encoding":50}],54:[function(require,module,exports){ -function backendState(backend) { - if (backend.frozen) { - throw new Error( - 'Attempting to use an outdated Automerge document that has already been updated. ' + - 'Please use the latest document state, or call Automerge.clone() if you really ' + - 'need to use this old document state.' - ) - } - return backend.state -} -module.exports = { - backendState -} +const crc32 = (crc, buf, len, pos) => { + const t = crcTable; + const end = pos + len; -},{}],55:[function(require,module,exports){ -const { isObject, copyObject, parseOpId } = require('../src/common') -const { OBJECT_ID, CONFLICTS, ELEM_IDS } = require('./constants') -const { instantiateText } = require('./text') -const { instantiateTable } = require('./table') -const { Counter } = require('./counter') + crc ^= -1; -/** - * Reconstructs the value from the patch object `patch`. - */ -function getValue(patch, object, updated) { - if (patch.objectId) { - // If the objectId of the existing object does not match the objectId in the patch, - // that means the patch is replacing the object with a new one made from scratch - if (object && object[OBJECT_ID] !== patch.objectId) { - object = undefined - } - return interpretPatch(patch, object, updated) - } else if (patch.datatype === 'timestamp') { - // Timestamp: value is milliseconds since 1970 epoch - return new Date(patch.value) - } else if (patch.datatype === 'counter') { - return new Counter(patch.value) - } else { - // Primitive value (int, uint, float64, string, boolean, or null) - return patch.value + for (let i = pos; i < end; i++) { + crc = (crc >>> 8) ^ t[(crc ^ buf[i]) & 0xFF]; } -} -/** - * Compares two strings, interpreted as Lamport timestamps of the form - * 'counter@actorId'. Returns 1 if ts1 is greater, or -1 if ts2 is greater. - */ -function lamportCompare(ts1, ts2) { - const regex = /^(\d+)@(.*)$/ - const time1 = regex.test(ts1) ? parseOpId(ts1) : {counter: 0, actorId: ts1} - const time2 = regex.test(ts2) ? parseOpId(ts2) : {counter: 0, actorId: ts2} - if (time1.counter < time2.counter) return -1 - if (time1.counter > time2.counter) return 1 - if (time1.actorId < time2.actorId) return -1 - if (time1.actorId > time2.actorId) return 1 - return 0 -} + return (crc ^ (-1)); // >>> 0; +}; -/** - * `props` is an object of the form: - * `{key1: {opId1: {...}, opId2: {...}}, key2: {opId3: {...}}}` - * where the outer object is a mapping from property names to inner objects, - * and the inner objects are a mapping from operation ID to sub-patch. - * This function interprets that structure and updates the objects `object` and - * `conflicts` to reflect it. For each key, the greatest opId (by Lamport TS - * order) is chosen as the default resolution; that op's value is assigned - * to `object[key]`. Moreover, all the opIds and values are packed into a - * conflicts object of the form `{opId1: value1, opId2: value2}` and assigned - * to `conflicts[key]`. If there is no conflict, the conflicts object contains - * just a single opId-value mapping. - */ -function applyProperties(props, object, conflicts, updated) { - if (!props) return - for (let key of Object.keys(props)) { - const values = {}, opIds = Object.keys(props[key]).sort(lamportCompare).reverse() - for (let opId of opIds) { - const subpatch = props[key][opId] - if (conflicts[key] && conflicts[key][opId]) { - values[opId] = getValue(subpatch, conflicts[key][opId], updated) - } else { - values[opId] = getValue(subpatch, undefined, updated) - } - } +module.exports = crc32; - if (opIds.length === 0) { - delete object[key] - delete conflicts[key] - } else { - object[key] = values[opIds[0]] - conflicts[key] = values - } - } -} +},{}],73:[function(require,module,exports){ +'use strict'; -/** - * Creates a writable copy of an immutable map object. If `originalObject` - * is undefined, creates an empty object with ID `objectId`. - */ -function cloneMapObject(originalObject, objectId) { - const object = copyObject(originalObject) - const conflicts = copyObject(originalObject ? originalObject[CONFLICTS] : undefined) - Object.defineProperty(object, OBJECT_ID, {value: objectId}) - Object.defineProperty(object, CONFLICTS, {value: conflicts}) - return object -} +// (C) 1995-2013 Jean-loup Gailly and Mark Adler +// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. -/** - * Updates the map object `obj` according to the modifications described in - * `patch`, or creates a new object if `obj` is undefined. Mutates `updated` - * to map the objectId to the new object, and returns the new object. - */ -function updateMapObject(patch, obj, updated) { - const objectId = patch.objectId - if (!updated[objectId]) { - updated[objectId] = cloneMapObject(obj, objectId) - } +const { _tr_init, _tr_stored_block, _tr_flush_block, _tr_tally, _tr_align } = require('./trees'); +const adler32 = require('./adler32'); +const crc32 = require('./crc32'); +const msg = require('./messages'); - const object = updated[objectId] - applyProperties(patch.props, object, object[CONFLICTS], updated) - return object -} +/* Public constants ==========================================================*/ +/* ===========================================================================*/ -/** - * Updates the table object `obj` according to the modifications described in - * `patch`, or creates a new object if `obj` is undefined. Mutates `updated` - * to map the objectId to the new object, and returns the new object. - */ -function updateTableObject(patch, obj, updated) { - const objectId = patch.objectId - if (!updated[objectId]) { - updated[objectId] = obj ? obj._clone() : instantiateTable(objectId) - } +const { + Z_NO_FLUSH, Z_PARTIAL_FLUSH, Z_FULL_FLUSH, Z_FINISH, Z_BLOCK, + Z_OK, Z_STREAM_END, Z_STREAM_ERROR, Z_DATA_ERROR, Z_BUF_ERROR, + Z_DEFAULT_COMPRESSION, + Z_FILTERED, Z_HUFFMAN_ONLY, Z_RLE, Z_FIXED, Z_DEFAULT_STRATEGY, + Z_UNKNOWN, + Z_DEFLATED +} = require('./constants'); - const object = updated[objectId] +/*============================================================================*/ - for (let key of Object.keys(patch.props || {})) { - const opIds = Object.keys(patch.props[key]) - if (opIds.length === 0) { - object.remove(key) - } else if (opIds.length === 1) { - const subpatch = patch.props[key][opIds[0]] - object._set(key, getValue(subpatch, object.byId(key), updated), opIds[0]) - } else { - throw new RangeError('Conflicts are not supported on properties of a table') - } - } - return object -} +const MAX_MEM_LEVEL = 9; +/* Maximum value for memLevel in deflateInit2 */ +const MAX_WBITS = 15; +/* 32K LZ77 window */ +const DEF_MEM_LEVEL = 8; -/** - * Creates a writable copy of an immutable list object. If `originalList` is - * undefined, creates an empty list with ID `objectId`. - */ -function cloneListObject(originalList, objectId) { - const list = originalList ? originalList.slice() : [] // slice() makes a shallow clone - const conflicts = (originalList && originalList[CONFLICTS]) ? originalList[CONFLICTS].slice() : [] - const elemIds = (originalList && originalList[ELEM_IDS]) ? originalList[ELEM_IDS].slice() : [] - Object.defineProperty(list, OBJECT_ID, {value: objectId}) - Object.defineProperty(list, CONFLICTS, {value: conflicts}) - Object.defineProperty(list, ELEM_IDS, {value: elemIds}) - return list -} -/** - * Updates the list object `obj` according to the modifications described in - * `patch`, or creates a new object if `obj` is undefined. Mutates `updated` - * to map the objectId to the new object, and returns the new object. - */ -function updateListObject(patch, obj, updated) { - const objectId = patch.objectId - if (!updated[objectId]) { - updated[objectId] = cloneListObject(obj, objectId) - } +const LENGTH_CODES = 29; +/* number of length codes, not counting the special END_BLOCK code */ +const LITERALS = 256; +/* number of literal bytes 0..255 */ +const L_CODES = LITERALS + 1 + LENGTH_CODES; +/* number of Literal or Length codes, including the END_BLOCK code */ +const D_CODES = 30; +/* number of distance codes */ +const BL_CODES = 19; +/* number of codes used to transfer the bit lengths */ +const HEAP_SIZE = 2 * L_CODES + 1; +/* maximum heap size */ +const MAX_BITS = 15; +/* All codes must not exceed MAX_BITS bits */ - const list = updated[objectId], conflicts = list[CONFLICTS], elemIds = list[ELEM_IDS] - for (let i = 0; i < patch.edits.length; i++) { - const edit = patch.edits[i] +const MIN_MATCH = 3; +const MAX_MATCH = 258; +const MIN_LOOKAHEAD = (MAX_MATCH + MIN_MATCH + 1); - if (edit.action === 'insert' || edit.action === 'update') { - const oldValue = conflicts[edit.index] && conflicts[edit.index][edit.opId] - let lastValue = getValue(edit.value, oldValue, updated) - let values = {[edit.opId]: lastValue} +const PRESET_DICT = 0x20; - // Successive updates for the same index are an indication of a conflict on that list element. - // Edits are sorted in increasing order by Lamport timestamp, so the last value (with the - // greatest timestamp) is the default resolution of the conflict. - while (i < patch.edits.length - 1 && patch.edits[i + 1].index === edit.index && - patch.edits[i + 1].action === 'update') { - i++ - const conflict = patch.edits[i] - const oldValue2 = conflicts[conflict.index] && conflicts[conflict.index][conflict.opId] - lastValue = getValue(conflict.value, oldValue2, updated) - values[conflict.opId] = lastValue - } +const INIT_STATE = 42; /* zlib header -> BUSY_STATE */ +//#ifdef GZIP +const GZIP_STATE = 57; /* gzip header -> BUSY_STATE | EXTRA_STATE */ +//#endif +const EXTRA_STATE = 69; /* gzip extra block -> NAME_STATE */ +const NAME_STATE = 73; /* gzip file name -> COMMENT_STATE */ +const COMMENT_STATE = 91; /* gzip comment -> HCRC_STATE */ +const HCRC_STATE = 103; /* gzip header CRC -> BUSY_STATE */ +const BUSY_STATE = 113; /* deflate -> FINISH_STATE */ +const FINISH_STATE = 666; /* stream complete */ - if (edit.action === 'insert') { - list.splice(edit.index, 0, lastValue) - conflicts.splice(edit.index, 0, values) - elemIds.splice(edit.index, 0, edit.elemId) - } else { - list[edit.index] = lastValue - conflicts[edit.index] = values - } +const BS_NEED_MORE = 1; /* block not completed, need more input or more output */ +const BS_BLOCK_DONE = 2; /* block flush performed */ +const BS_FINISH_STARTED = 3; /* finish started, need only more output at next deflate */ +const BS_FINISH_DONE = 4; /* finish done, accept no more input or output */ - } else if (edit.action === 'multi-insert') { - const startElemId = parseOpId(edit.elemId), newElems = [], newValues = [], newConflicts = [] - const datatype = edit.datatype - edit.values.forEach((value, index) => { - const elemId = `${startElemId.counter + index}@${startElemId.actorId}` - value = getValue({ value, datatype }, undefined, updated) - newValues.push(value) - newConflicts.push({[elemId]: {value, datatype, type: 'value'}}) - newElems.push(elemId) - }) - list.splice(edit.index, 0, ...newValues) - conflicts.splice(edit.index, 0, ...newConflicts) - elemIds.splice(edit.index, 0, ...newElems) +const OS_CODE = 0x03; // Unix :) . Don't detect, use this default. - } else if (edit.action === 'remove') { - list.splice(edit.index, edit.count) - conflicts.splice(edit.index, edit.count) - elemIds.splice(edit.index, edit.count) - } - } - return list -} +const err = (strm, errorCode) => { + strm.msg = msg[errorCode]; + return errorCode; +}; -/** - * Updates the text object `obj` according to the modifications described in - * `patch`, or creates a new object if `obj` is undefined. Mutates `updated` - * to map the objectId to the new object, and returns the new object. - */ -function updateTextObject(patch, obj, updated) { - const objectId = patch.objectId - let elems - if (updated[objectId]) { - elems = updated[objectId].elems - } else if (obj) { - elems = obj.elems.slice() - } else { - elems = [] - } +const rank = (f) => { + return ((f) * 2) - ((f) > 4 ? 9 : 0); +}; - for (const edit of patch.edits) { - if (edit.action === 'insert') { - const value = getValue(edit.value, undefined, updated) - const elem = {elemId: edit.elemId, pred: [edit.opId], value} - elems.splice(edit.index, 0, elem) +const zero = (buf) => { + let len = buf.length; while (--len >= 0) { buf[len] = 0; } +}; - } else if (edit.action === 'multi-insert') { - const startElemId = parseOpId(edit.elemId) - const datatype = edit.datatype - const newElems = edit.values.map((value, index) => { - value = getValue({ datatype, value }, undefined, updated) - const elemId = `${startElemId.counter + index}@${startElemId.actorId}` - return {elemId, pred: [elemId], value} - }) - elems.splice(edit.index, 0, ...newElems) +/* =========================================================================== + * Slide the hash table when sliding the window down (could be avoided with 32 + * bit values at the expense of memory usage). We slide even when level == 0 to + * keep the hash table consistent if we switch back to level > 0 later. + */ +const slide_hash = (s) => { + let n, m; + let p; + let wsize = s.w_size; - } else if (edit.action === 'update') { - const elemId = elems[edit.index].elemId - const value = getValue(edit.value, elems[edit.index].value, updated) - elems[edit.index] = {elemId, pred: [edit.opId], value} + n = s.hash_size; + p = n; + do { + m = s.head[--p]; + s.head[p] = (m >= wsize ? m - wsize : 0); + } while (--n); + n = wsize; +//#ifndef FASTEST + p = n; + do { + m = s.prev[--p]; + s.prev[p] = (m >= wsize ? m - wsize : 0); + /* If n is not on any hash chain, prev[n] is garbage but + * its value will never be used. + */ + } while (--n); +//#endif +}; - } else if (edit.action === 'remove') { - elems.splice(edit.index, edit.count) - } - } +/* eslint-disable new-cap */ +let HASH_ZLIB = (s, prev, data) => ((prev << s.hash_shift) ^ data) & s.hash_mask; +// This hash causes less collisions, https://github.com/nodeca/pako/issues/135 +// But breaks binary compatibility +//let HASH_FAST = (s, prev, data) => ((prev << 8) + (prev >> 8) + (data << 4)) & s.hash_mask; +let HASH = HASH_ZLIB; - updated[objectId] = instantiateText(objectId, elems) - return updated[objectId] -} -/** - * Applies the patch object `patch` to the read-only document object `obj`. - * Clones a writable copy of `obj` and places it in `updated` (indexed by - * objectId), if that has not already been done. Returns the updated object. +/* ========================================================================= + * Flush as much pending output as possible. All deflate() output, except for + * some deflate_stored() output, goes through this function so some + * applications may wish to modify it to avoid allocating a large + * strm->next_out buffer and copying into it. (See also read_buf()). */ -function interpretPatch(patch, obj, updated) { - // Return original object if it already exists and isn't being modified - if (isObject(obj) && (!patch.props || Object.keys(patch.props).length === 0) && - (!patch.edits || patch.edits.length === 0) && !updated[patch.objectId]) { - return obj +const flush_pending = (strm) => { + const s = strm.state; + + //_tr_flush_bits(s); + let len = s.pending; + if (len > strm.avail_out) { + len = strm.avail_out; } + if (len === 0) { return; } - if (patch.type === 'map') { - return updateMapObject(patch, obj, updated) - } else if (patch.type === 'table') { - return updateTableObject(patch, obj, updated) - } else if (patch.type === 'list') { - return updateListObject(patch, obj, updated) - } else if (patch.type === 'text') { - return updateTextObject(patch, obj, updated) - } else { - throw new TypeError(`Unknown object type: ${patch.type}`) - } -} - -/** - * Creates a writable copy of the immutable document root object `root`. - */ -function cloneRootObject(root) { - if (root[OBJECT_ID] !== '_root') { - throw new RangeError(`Not the root object: ${root[OBJECT_ID]}`) + strm.output.set(s.pending_buf.subarray(s.pending_out, s.pending_out + len), strm.next_out); + strm.next_out += len; + s.pending_out += len; + strm.total_out += len; + strm.avail_out -= len; + s.pending -= len; + if (s.pending === 0) { + s.pending_out = 0; } - return cloneMapObject(root, '_root') -} - -module.exports = { - interpretPatch, cloneRootObject -} +}; -},{"../src/common":87,"./constants":56,"./counter":58,"./table":63,"./text":64}],56:[function(require,module,exports){ -// Properties of the document root object -const OPTIONS = Symbol('_options') // object containing options passed to init() -const CACHE = Symbol('_cache') // map from objectId to immutable object -const STATE = Symbol('_state') // object containing metadata about current state (e.g. sequence numbers) -// Properties of all Automerge objects -const OBJECT_ID = Symbol('_objectId') // the object ID of the current object (string) -const CONFLICTS = Symbol('_conflicts') // map or list (depending on object type) of conflicts -const CHANGE = Symbol('_change') // the context object on proxy objects used in change callback -const ELEM_IDS = Symbol('_elemIds') // list containing the element ID of each list element +const flush_block_only = (s, last) => { + _tr_flush_block(s, (s.block_start >= 0 ? s.block_start : -1), s.strstart - s.block_start, last); + s.block_start = s.strstart; + flush_pending(s.strm); +}; -module.exports = { - OPTIONS, CACHE, STATE, OBJECT_ID, CONFLICTS, CHANGE, ELEM_IDS -} -},{}],57:[function(require,module,exports){ -const { CACHE, OBJECT_ID, CONFLICTS, ELEM_IDS, STATE } = require('./constants') -const { interpretPatch } = require('./apply_patch') -const { Text } = require('./text') -const { Table } = require('./table') -const { Counter, getWriteableCounter } = require('./counter') -const { Int, Uint, Float64 } = require('./numbers') -const { isObject, parseOpId, createArrayOfNulls } = require('../src/common') -const uuid = require('../src/uuid') +const put_byte = (s, b) => { + s.pending_buf[s.pending++] = b; +}; -/** - * An instance of this class is passed to `rootObjectProxy()`. The methods are - * called by proxy object mutation functions to query the current object state - * and to apply the requested changes. +/* ========================================================================= + * Put a short in the pending buffer. The 16-bit value is put in MSB order. + * IN assertion: the stream state is correct and there is enough room in + * pending_buf. */ -class Context { - constructor (doc, actorId, applyPatch) { - this.actorId = actorId - this.nextOpNum = doc[STATE].maxOp + 1 - this.cache = doc[CACHE] - this.updated = {} - this.ops = [] - this.applyPatch = applyPatch ? applyPatch : interpretPatch - } +const putShortMSB = (s, b) => { - /** - * Adds an operation object to the list of changes made in the current context. - */ - addOp(operation) { - this.ops.push(operation) + // put_byte(s, (Byte)(b >> 8)); +// put_byte(s, (Byte)(b & 0xff)); + s.pending_buf[s.pending++] = (b >>> 8) & 0xff; + s.pending_buf[s.pending++] = b & 0xff; +}; - if (operation.action === 'set' && operation.values) { - this.nextOpNum += operation.values.length - } else if (operation.action === 'del' && operation.multiOp) { - this.nextOpNum += operation.multiOp - } else { - this.nextOpNum += 1 - } - } - /** - * Returns the operation ID of the next operation to be added to the context. - */ - nextOpId() { - return `${this.nextOpNum}@${this.actorId}` - } +/* =========================================================================== + * Read a new buffer from the current input stream, update the adler32 + * and total number of bytes read. All deflate() input goes through + * this function so some applications may wish to modify it to avoid + * allocating a large strm->input buffer and copying from it. + * (See also flush_pending()). + */ +const read_buf = (strm, buf, start, size) => { - /** - * Takes a value and returns an object describing the value (in the format used by patches). - */ - getValueDescription(value) { - if (!['object', 'boolean', 'number', 'string'].includes(typeof value)) { - throw new TypeError(`Unsupported type of value: ${typeof value}`) - } + let len = strm.avail_in; - if (isObject(value)) { - if (value instanceof Date) { - // Date object, represented as milliseconds since epoch - return {type: 'value', value: value.getTime(), datatype: 'timestamp'} + if (len > size) { len = size; } + if (len === 0) { return 0; } - } else if (value instanceof Int) { - return {type: 'value', value: value.value, datatype: 'int'} - } else if (value instanceof Uint) { - return {type: 'value', value: value.value, datatype: 'uint'} - } else if (value instanceof Float64) { - return {type: 'value', value: value.value, datatype: 'float64'} - } else if (value instanceof Counter) { - // Counter object - return {type: 'value', value: value.value, datatype: 'counter'} + strm.avail_in -= len; - } else { - // Nested object (map, list, text, or table) - const objectId = value[OBJECT_ID], type = this.getObjectType(objectId) - if (!objectId) { - throw new RangeError(`Object ${JSON.stringify(value)} has no objectId`) - } - if (type === 'list' || type === 'text') { - return {objectId, type, edits: []} - } else { - return {objectId, type, props: {}} - } - } - } else if (typeof value === 'number') { - if (Number.isInteger(value) && value <= Number.MAX_SAFE_INTEGER && value >= Number.MIN_SAFE_INTEGER) { - return {type: 'value', value, datatype: 'int'} - } else { - return {type: 'value', value, datatype: 'float64'} - } - } else { - // Primitive value (string, boolean, or null) - return {type: 'value', value} - } + // zmemcpy(buf, strm->next_in, len); + buf.set(strm.input.subarray(strm.next_in, strm.next_in + len), start); + if (strm.state.wrap === 1) { + strm.adler = adler32(strm.adler, buf, len, start); } - /** - * Builds the values structure describing a single property in a patch. Finds all the values of - * property `key` of `object` (there might be multiple values in the case of a conflict), and - * returns an object that maps operation IDs to descriptions of values. - */ - getValuesDescriptions(path, object, key) { - if (object instanceof Table) { - // Table objects don't have conflicts, since rows are identified by their unique objectId - const value = object.byId(key) - return value ? {[key]: this.getValueDescription(value)} : {} - } else if (object instanceof Text) { - // Text objects don't support conflicts - const value = object.get(key) - const elemId = object.getElemId(key) - return value ? {[elemId]: this.getValueDescription(value)} : {} - } else { - // Map or list objects - const conflicts = object[CONFLICTS][key], values = {} - if (!conflicts) { - throw new RangeError(`No children at key ${key} of path ${JSON.stringify(path)}`) - } - for (let opId of Object.keys(conflicts)) { - values[opId] = this.getValueDescription(conflicts[opId]) - } - return values - } + else if (strm.state.wrap === 2) { + strm.adler = crc32(strm.adler, buf, len, start); } - /** - * Returns the value at property `key` of object `object`. In the case of a conflict, returns - * the value whose assignment operation has the ID `opId`. - */ - getPropertyValue(object, key, opId) { - if (object instanceof Table) { - return object.byId(key) - } else if (object instanceof Text) { - return object.get(key) - } else { - return object[CONFLICTS][key][opId] - } - } + strm.next_in += len; + strm.total_in += len; - /** - * Recurses along `path` into the patch object `patch`, creating nodes along the way as needed - * by mutating the patch object. Returns the subpatch at the given path. - */ - getSubpatch(patch, path) { - if (path.length == 0) return patch - let subpatch = patch, object = this.getObject('_root') + return len; +}; - for (let pathElem of path) { - let values = this.getValuesDescriptions(path, object, pathElem.key) - if (subpatch.props) { - if (!subpatch.props[pathElem.key]) { - subpatch.props[pathElem.key] = values - } - } else if (subpatch.edits) { - for (const opId of Object.keys(values)) { - subpatch.edits.push({action: 'update', index: pathElem.key, opId, value: values[opId]}) - } - } - let nextOpId = null - for (let opId of Object.keys(values)) { - if (values[opId].objectId === pathElem.objectId) { - nextOpId = opId - } - } - if (!nextOpId) { - throw new RangeError(`Cannot find path object with objectId ${pathElem.objectId}`) - } +/* =========================================================================== + * Set match_start to the longest match starting at the given string and + * return its length. Matches shorter or equal to prev_length are discarded, + * in which case the result is equal to prev_length and match_start is + * garbage. + * IN assertions: cur_match is the head of the hash chain for the current + * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1 + * OUT assertion: the match length is not greater than s->lookahead. + */ +const longest_match = (s, cur_match) => { - subpatch = values[nextOpId] - object = this.getPropertyValue(object, pathElem.key, nextOpId) - } + let chain_length = s.max_chain_length; /* max hash chain length */ + let scan = s.strstart; /* current string */ + let match; /* matched string */ + let len; /* length of current match */ + let best_len = s.prev_length; /* best match length so far */ + let nice_match = s.nice_match; /* stop if match long enough */ + const limit = (s.strstart > (s.w_size - MIN_LOOKAHEAD)) ? + s.strstart - (s.w_size - MIN_LOOKAHEAD) : 0/*NIL*/; - return subpatch - } + const _win = s.window; // shortcut - /** - * Returns an object (not proxied) from the cache or updated set, as appropriate. + const wmask = s.w_mask; + const prev = s.prev; + + /* Stop when cur_match becomes <= limit. To simplify the code, + * we prevent matches with the string of window index 0. */ - getObject(objectId) { - const object = this.updated[objectId] || this.cache[objectId] - if (!object) throw new RangeError(`Target object does not exist: ${objectId}`) - return object - } - /** - * Returns a string that is either 'map', 'table', 'list', or 'text', indicating - * the type of the object with ID `objectId`. + const strend = s.strstart + MAX_MATCH; + let scan_end1 = _win[scan + best_len - 1]; + let scan_end = _win[scan + best_len]; + + /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + * It is easy to get rid of this optimization if necessary. */ - getObjectType(objectId) { - if (objectId === '_root') return 'map' - const object = this.getObject(objectId) - if (object instanceof Text) return 'text' - if (object instanceof Table) return 'table' - if (Array.isArray(object)) return 'list' - return 'map' - } + // Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); - /** - * Returns the value associated with the property named `key` on the object - * at path `path`. If the value is an object, returns a proxy for it. + /* Do not waste too much time if we already have a good match: */ + if (s.prev_length >= s.good_match) { + chain_length >>= 2; + } + /* Do not look for matches beyond the end of the input. This is necessary + * to make deflate deterministic. */ - getObjectField(path, objectId, key) { - if (!['string', 'number'].includes(typeof key)) return - const object = this.getObject(objectId) + if (nice_match > s.lookahead) { nice_match = s.lookahead; } - if (object[key] instanceof Counter) { - return getWriteableCounter(object[key].value, this, path, objectId, key) + // Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); - } else if (isObject(object[key])) { - const childId = object[key][OBJECT_ID] - const subpath = path.concat([{key, objectId: childId}]) - // The instantiateObject function is added to the context object by rootObjectProxy() - return this.instantiateObject(subpath, childId) + do { + // Assert(cur_match < s->strstart, "no future"); + match = cur_match; - } else { - return object[key] - } - } + /* Skip to next match if the match length cannot increase + * or if the match length is less than 2. Note that the checks below + * for insufficient lookahead only occur occasionally for performance + * reasons. Therefore uninitialized memory will be accessed, and + * conditional jumps will be made that depend on those values. + * However the length of the match is limited to the lookahead, so + * the output of deflate is not affected by the uninitialized values. + */ - /** - * Recursively creates Automerge versions of all the objects and nested objects in `value`, - * constructing a patch and operations that describe the object tree. The new object is - * assigned to the property `key` in the object with ID `obj`. If the object is a list or - * text, `key` must be set to the list index being updated, and `elemId` must be set to the - * elemId of the element being updated. If `insert` is true, we insert a new list element - * (or text character) at index `key`, and `elemId` must be the elemId of the immediate - * predecessor element (or the string '_head' if inserting at index 0). If the assignment - * overwrites a previous value at this key/element, `pred` must be set to the array of the - * prior operations we are overwriting (empty array if there is no existing value). - */ - createNestedObjects(obj, key, value, insert, pred, elemId) { - if (value[OBJECT_ID]) { - throw new RangeError('Cannot create a reference to an existing document object') + if (_win[match + best_len] !== scan_end || + _win[match + best_len - 1] !== scan_end1 || + _win[match] !== _win[scan] || + _win[++match] !== _win[scan + 1]) { + continue; } - const objectId = this.nextOpId() - if (value instanceof Text) { - // Create a new Text object - this.addOp(elemId ? {action: 'makeText', obj, elemId, insert, pred} - : {action: 'makeText', obj, key, insert, pred}) - const subpatch = {objectId, type: 'text', edits: []} - this.insertListItems(subpatch, 0, [...value], true) - return subpatch + /* The check at best_len-1 can be removed because it will be made + * again later. (This heuristic is not always a win.) + * It is not necessary to compare scan[2] and match[2] since they + * are always equal when the other bytes match, given that + * the hash keys are equal and that HASH_BITS >= 8. + */ + scan += 2; + match++; + // Assert(*scan == *match, "match[2]?"); - } else if (value instanceof Table) { - // Create a new Table object - if (value.count > 0) { - throw new RangeError('Assigning a non-empty Table object is not supported') - } - this.addOp(elemId ? {action: 'makeTable', obj, elemId, insert, pred} - : {action: 'makeTable', obj, key, insert, pred}) - return {objectId, type: 'table', props: {}} + /* We check for insufficient lookahead only every 8th comparison; + * the 256th check will be made at strstart+258. + */ + do { + /*jshint noempty:false*/ + } while (_win[++scan] === _win[++match] && _win[++scan] === _win[++match] && + _win[++scan] === _win[++match] && _win[++scan] === _win[++match] && + _win[++scan] === _win[++match] && _win[++scan] === _win[++match] && + _win[++scan] === _win[++match] && _win[++scan] === _win[++match] && + scan < strend); - } else if (Array.isArray(value)) { - // Create a new list object - this.addOp(elemId ? {action: 'makeList', obj, elemId, insert, pred} - : {action: 'makeList', obj, key, insert, pred}) - const subpatch = {objectId, type: 'list', edits: []} - this.insertListItems(subpatch, 0, value, true) - return subpatch + // Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); - } else { - // Create a new map object - this.addOp(elemId ? {action: 'makeMap', obj, elemId, insert, pred} - : {action: 'makeMap', obj, key, insert, pred}) - let props = {} - for (let nested of Object.keys(value).sort()) { - const opId = this.nextOpId() - const valuePatch = this.setValue(objectId, nested, value[nested], false, []) - props[nested] = {[opId]: valuePatch} + len = MAX_MATCH - (strend - scan); + scan = strend - MAX_MATCH; + + if (len > best_len) { + s.match_start = cur_match; + best_len = len; + if (len >= nice_match) { + break; } - return {objectId, type: 'map', props} + scan_end1 = _win[scan + best_len - 1]; + scan_end = _win[scan + best_len]; } + } while ((cur_match = prev[cur_match & wmask]) > limit && --chain_length !== 0); + + if (best_len <= s.lookahead) { + return best_len; } + return s.lookahead; +}; - /** - * Records an assignment to a particular key in a map, or a particular index in a list. - * `objectId` is the ID of the object being modified, `key` is the property name or list - * index being updated, and `value` is the new value being assigned. If `insert` is true, - * a new list element is inserted at index `key`, and `value` is assigned to that new list - * element. `pred` is an array of opIds for previous values of the property being assigned, - * which are overwritten by this operation. If the object being modified is a list or text, - * `elemId` is the element ID of the list element being updated (if insert=false), or the - * element ID of the list element immediately preceding the insertion (if insert=true). - * - * Returns a patch describing the new value. The return value is of the form - * `{objectId, type, props}` if `value` is an object, or `{value, datatype}` if it is a - * primitive value. For string, number, boolean, or null the datatype is omitted. - */ - setValue(objectId, key, value, insert, pred, elemId) { - if (!objectId) { - throw new RangeError('setValue needs an objectId') - } - if (key === '') { - throw new RangeError('The key of a map entry must not be an empty string') - } - if (isObject(value) && !(value instanceof Date) && !(value instanceof Counter) && !(value instanceof Int) && !(value instanceof Uint) && !(value instanceof Float64)) { - // Nested object (map, list, text, or table) - return this.createNestedObjects(objectId, key, value, insert, pred, elemId) - } else { - // Date or counter object, or primitive value (number, string, boolean, or null) - const description = this.getValueDescription(value) - const op = {action: 'set', obj: objectId, insert, value: description.value, pred} - if (elemId) op.elemId = elemId; else op.key = key - if (description.datatype) op.datatype = description.datatype - this.addOp(op) - return description - } - } +/* =========================================================================== + * Fill the window when the lookahead becomes insufficient. + * Updates strstart and lookahead. + * + * IN assertion: lookahead < MIN_LOOKAHEAD + * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD + * At least one byte has been read, or avail_in == 0; reads are + * performed for at least two bytes (required for the zip translate_eol + * option -- not supported here). + */ +const fill_window = (s) => { - /** - * Constructs a new patch, calls `callback` with the subpatch at the location `path`, - * and then immediately applies the patch to the document. - */ - applyAtPath(path, callback) { - let diff = {objectId: '_root', type: 'map', props: {}} - callback(this.getSubpatch(diff, path)) - this.applyPatch(diff, this.cache._root, this.updated) - } + const _w_size = s.w_size; + let n, more, str; - /** - * Updates the map object at path `path`, setting the property with name - * `key` to `value`. - */ - setMapKey(path, key, value) { - if (typeof key !== 'string') { - throw new RangeError(`The key of a map entry must be a string, not ${typeof key}`) - } + //Assert(s->lookahead < MIN_LOOKAHEAD, "already enough lookahead"); - const objectId = path.length === 0 ? '_root' : path[path.length - 1].objectId - const object = this.getObject(objectId) - if (object[key] instanceof Counter) { - throw new RangeError('Cannot overwrite a Counter object; use .increment() or .decrement() to change its value.') - } + do { + more = s.window_size - s.lookahead - s.strstart; - // If the assigned field value is the same as the existing value, and - // the assignment does not resolve a conflict, do nothing - if (object[key] !== value || Object.keys(object[CONFLICTS][key] || {}).length > 1 || value === undefined) { - this.applyAtPath(path, subpatch => { - const pred = getPred(object, key) - const opId = this.nextOpId() - const valuePatch = this.setValue(objectId, key, value, false, pred) - subpatch.props[key] = {[opId]: valuePatch} - }) - } - } + // JS ints have 32 bit, block below not needed + /* Deal with !@#$% 64K limit: */ + //if (sizeof(int) <= 2) { + // if (more == 0 && s->strstart == 0 && s->lookahead == 0) { + // more = wsize; + // + // } else if (more == (unsigned)(-1)) { + // /* Very unlikely, but possible on 16 bit machine if + // * strstart == 0 && lookahead == 1 (input done a byte at time) + // */ + // more--; + // } + //} - /** - * Updates the map object at path `path`, deleting the property `key`. - */ - deleteMapKey(path, key) { - const objectId = path.length === 0 ? '_root' : path[path.length - 1].objectId - const object = this.getObject(objectId) - if (object[key] !== undefined) { - const pred = getPred(object, key) - this.addOp({action: 'del', obj: objectId, key, insert: false, pred}) - this.applyAtPath(path, subpatch => { - subpatch.props[key] = {} - }) - } - } + /* If the window is almost full and there is insufficient lookahead, + * move the upper half to the lower one to make room in the upper half. + */ + if (s.strstart >= _w_size + (_w_size - MIN_LOOKAHEAD)) { - /** - * Inserts a sequence of new list elements `values` into a list, starting at position `index`. - * `newObject` is true if we are creating a new list object, and false if we are updating an - * existing one. `subpatch` is the patch for the list object being modified. Mutates - * `subpatch` to reflect the sequence of values. - */ - insertListItems(subpatch, index, values, newObject) { - const list = newObject ? [] : this.getObject(subpatch.objectId) - if (index < 0 || index > list.length) { - throw new RangeError(`List index ${index} is out of bounds for list of length ${list.length}`) + s.window.set(s.window.subarray(_w_size, _w_size + _w_size - more), 0); + s.match_start -= _w_size; + s.strstart -= _w_size; + /* we now have strstart >= MAX_DIST */ + s.block_start -= _w_size; + if (s.insert > s.strstart) { + s.insert = s.strstart; + } + slide_hash(s); + more += _w_size; + } + if (s.strm.avail_in === 0) { + break; } - if (values.length === 0) return - let elemId = getElemId(list, index, true) - const allPrimitive = values.every(v => typeof v === 'string' || typeof v === 'number' || - typeof v === 'boolean' || v === null || - (isObject(v) && (v instanceof Date || v instanceof Counter || v instanceof Int || - v instanceof Uint || v instanceof Float64))) - const allValueDescriptions = allPrimitive ? values.map(v => this.getValueDescription(v)) : [] - const allDatatypesSame = allValueDescriptions.every(t => t.datatype === allValueDescriptions[0].datatype) + /* If there was no sliding: + * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && + * more == window_size - lookahead - strstart + * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) + * => more >= window_size - 2*WSIZE + 2 + * In the BIG_MEM or MMAP case (not yet supported), + * window_size == input_size + MIN_LOOKAHEAD && + * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. + * Otherwise, window_size == 2*WSIZE so more >= 2. + * If there was sliding, more >= WSIZE. So in all cases, more >= 2. + */ + //Assert(more >= 2, "more < 2"); + n = read_buf(s.strm, s.window, s.strstart + s.lookahead, more); + s.lookahead += n; - if (allPrimitive && allDatatypesSame && values.length > 1) { - const nextElemId = this.nextOpId() - const datatype = allValueDescriptions[0].datatype - const values = allValueDescriptions.map(v => v.value) - const op = {action: 'set', obj: subpatch.objectId, elemId, insert: true, values, pred: []} - const edit = {action: 'multi-insert', elemId: nextElemId, index, values} - if (datatype) { - op.datatype = datatype - edit.datatype = datatype - } - this.addOp(op) - subpatch.edits.push(edit) - } else { - for (let offset = 0; offset < values.length; offset++) { - let nextElemId = this.nextOpId() - const valuePatch = this.setValue(subpatch.objectId, index + offset, values[offset], true, [], elemId) - elemId = nextElemId - subpatch.edits.push({action: 'insert', index: index + offset, elemId, opId: elemId, value: valuePatch}) + /* Initialize the hash value now that we have some input: */ + if (s.lookahead + s.insert >= MIN_MATCH) { + str = s.strstart - s.insert; + s.ins_h = s.window[str]; + + /* UPDATE_HASH(s, s->ins_h, s->window[str + 1]); */ + s.ins_h = HASH(s, s.ins_h, s.window[str + 1]); +//#if MIN_MATCH != 3 +// Call update_hash() MIN_MATCH-3 more times +//#endif + while (s.insert) { + /* UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); */ + s.ins_h = HASH(s, s.ins_h, s.window[str + MIN_MATCH - 1]); + + s.prev[str & s.w_mask] = s.head[s.ins_h]; + s.head[s.ins_h] = str; + str++; + s.insert--; + if (s.lookahead + s.insert < MIN_MATCH) { + break; + } } } - } + /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, + * but this is not important since only literal bytes will be emitted. + */ - /** - * Updates the list object at path `path`, replacing the current value at - * position `index` with the new value `value`. + } while (s.lookahead < MIN_LOOKAHEAD && s.strm.avail_in !== 0); + + /* If the WIN_INIT bytes after the end of the current data have never been + * written, then zero those bytes in order to avoid memory check reports of + * the use of uninitialized (or uninitialised as Julian writes) bytes by + * the longest match routines. Update the high water mark for the next + * time through here. WIN_INIT is set to MAX_MATCH since the longest match + * routines allow scanning to strstart + MAX_MATCH, ignoring lookahead. */ - setListIndex(path, index, value) { - const objectId = path.length === 0 ? '_root' : path[path.length - 1].objectId - const list = this.getObject(objectId) +// if (s.high_water < s.window_size) { +// const curr = s.strstart + s.lookahead; +// let init = 0; +// +// if (s.high_water < curr) { +// /* Previous high water mark below current data -- zero WIN_INIT +// * bytes or up to end of window, whichever is less. +// */ +// init = s.window_size - curr; +// if (init > WIN_INIT) +// init = WIN_INIT; +// zmemzero(s->window + curr, (unsigned)init); +// s->high_water = curr + init; +// } +// else if (s->high_water < (ulg)curr + WIN_INIT) { +// /* High water mark at or above current data, but below current data +// * plus WIN_INIT -- zero out to current data plus WIN_INIT, or up +// * to end of window, whichever is less. +// */ +// init = (ulg)curr + WIN_INIT - s->high_water; +// if (init > s->window_size - s->high_water) +// init = s->window_size - s->high_water; +// zmemzero(s->window + s->high_water, (unsigned)init); +// s->high_water += init; +// } +// } +// +// Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD, +// "not enough room for search"); +}; - // Assignment past the end of the list => insert nulls followed by new value - if (index >= list.length) { - const insertions = createArrayOfNulls(index - list.length) - insertions.push(value) - return this.splice(path, list.length, 0, insertions) +/* =========================================================================== + * Copy without compression as much as possible from the input stream, return + * the current block state. + * + * In case deflateParams() is used to later switch to a non-zero compression + * level, s->matches (otherwise unused when storing) keeps track of the number + * of hash table slides to perform. If s->matches is 1, then one hash table + * slide will be done when switching. If s->matches is 2, the maximum value + * allowed here, then the hash table will be cleared, since two or more slides + * is the same as a clear. + * + * deflate_stored() is written to minimize the number of times an input byte is + * copied. It is most efficient with large input and output buffers, which + * maximizes the opportunites to have a single copy from next_in to next_out. + */ +const deflate_stored = (s, flush) => { + + /* Smallest worthy block size when not flushing or finishing. By default + * this is 32K. This can be as small as 507 bytes for memLevel == 1. For + * large input and output buffers, the stored block size will be larger. + */ + let min_block = s.pending_buf_size - 5 > s.w_size ? s.w_size : s.pending_buf_size - 5; + + /* Copy as many min_block or larger stored blocks directly to next_out as + * possible. If flushing, copy the remaining available input to next_out as + * stored blocks, if there is enough space. + */ + let len, left, have, last = 0; + let used = s.strm.avail_in; + do { + /* Set len to the maximum size block that we can copy directly with the + * available input data and output space. Set left to how much of that + * would be copied from what's left in the window. + */ + len = 65535/* MAX_STORED */; /* maximum deflate stored block length */ + have = (s.bi_valid + 42) >> 3; /* number of header bytes */ + if (s.strm.avail_out < have) { /* need room for header */ + break; } - if (list[index] instanceof Counter) { - throw new RangeError('Cannot overwrite a Counter object; use .increment() or .decrement() to change its value.') + /* maximum stored block length that will fit in avail_out: */ + have = s.strm.avail_out - have; + left = s.strstart - s.block_start; /* bytes left in window */ + if (len > left + s.strm.avail_in) { + len = left + s.strm.avail_in; /* limit len to the input */ } - - // If the assigned list element value is the same as the existing value, and - // the assignment does not resolve a conflict, do nothing - if (list[index] !== value || Object.keys(list[CONFLICTS][index] || {}).length > 1 || value === undefined) { - this.applyAtPath(path, subpatch => { - const pred = getPred(list, index) - const opId = this.nextOpId() - const valuePatch = this.setValue(objectId, index, value, false, pred, getElemId(list, index)) - subpatch.edits.push({action: 'update', index, opId, value: valuePatch}) - }) + if (len > have) { + len = have; /* limit len to the output */ } - } - /** - * Updates the list object at path `path`, deleting `deletions` list elements starting from - * list index `start`, and inserting the list of new elements `insertions` at that position. - */ - splice(path, start, deletions, insertions) { - const objectId = path.length === 0 ? '_root' : path[path.length - 1].objectId - let list = this.getObject(objectId) - if (start < 0 || deletions < 0 || start > list.length - deletions) { - throw new RangeError(`${deletions} deletions starting at index ${start} are out of bounds for list of length ${list.length}`) + /* If the stored block would be less than min_block in length, or if + * unable to copy all of the available input when flushing, then try + * copying to the window and the pending buffer instead. Also don't + * write an empty block when flushing -- deflate() does that. + */ + if (len < min_block && ((len === 0 && flush !== Z_FINISH) || + flush === Z_NO_FLUSH || + len !== left + s.strm.avail_in)) { + break; } - if (deletions === 0 && insertions.length === 0) return - let patch = {diffs: {objectId: '_root', type: 'map', props: {}}} - let subpatch = this.getSubpatch(patch.diffs, path) + /* Make a dummy stored block in pending to get the header bytes, + * including any pending bits. This also updates the debugging counts. + */ + last = flush === Z_FINISH && len === left + s.strm.avail_in ? 1 : 0; + _tr_stored_block(s, 0, 0, last); - if (deletions > 0) { - let op, lastElemParsed, lastPredParsed - for (let i = 0; i < deletions; i++) { - if (this.getObjectField(path, objectId, start + i) instanceof Counter) { - // This may seem bizarre, but it's really fiddly to implement deletion of counters from - // lists, and I doubt anyone ever needs to do this, so I'm just going to throw an - // exception for now. The reason is: a counter is created by a set operation with counter - // datatype, and subsequent increment ops are successors to the set operation. Normally, a - // set operation with successor indicates a value that has been overwritten, so a set - // operation with successors is normally invisible. Counters are an exception, because the - // increment operations don't make the set operation invisible. When a counter appears in - // a map, this is not too bad: if all successors are increments, then the counter remains - // visible; if one or more successors are deletions, it goes away. However, when deleting - // a list element, we have the additional challenge that we need to distinguish between a - // list element that is being deleted by the current change (in which case we need to put - // a 'remove' action in the patch's edits for that list) and a list element that was - // already deleted previously (in which case the patch should not reflect the deletion). - // This can be done, but as I said, it's fiddly. If someone wants to pick this up in the - // future, hopefully the above description will be enough to get you started. Good luck! - throw new TypeError('Unsupported operation: deleting a counter from a list') - } + /* Replace the lengths in the dummy stored block with len. */ + s.pending_buf[s.pending - 4] = len; + s.pending_buf[s.pending - 3] = len >> 8; + s.pending_buf[s.pending - 2] = ~len; + s.pending_buf[s.pending - 1] = ~len >> 8; - // Any sequences of deletions with consecutive elemId and pred values get combined into a - // single multiOp; any others become individual deletion operations. This optimisation only - // kicks in if the user deletes a sequence of elements at once (in a single call to splice); - // it might be nice to also detect such runs of deletions in the case where the user deletes - // a sequence of list elements one by one. - const thisElem = getElemId(list, start + i), thisElemParsed = parseOpId(thisElem) - const thisPred = getPred(list, start + i) - const thisPredParsed = (thisPred.length === 1) ? parseOpId(thisPred[0]) : undefined + /* Write the stored block header bytes. */ + flush_pending(s.strm); - if (op && lastElemParsed && lastPredParsed && thisPredParsed && - lastElemParsed.actorId === thisElemParsed.actorId && lastElemParsed.counter + 1 === thisElemParsed.counter && - lastPredParsed.actorId === thisPredParsed.actorId && lastPredParsed.counter + 1 === thisPredParsed.counter) { - op.multiOp = (op.multiOp || 1) + 1 - } else { - if (op) this.addOp(op) - op = {action: 'del', obj: objectId, elemId: thisElem, insert: false, pred: thisPred} - } - lastElemParsed = thisElemParsed - lastPredParsed = thisPredParsed +//#ifdef ZLIB_DEBUG +// /* Update debugging counts for the data about to be copied. */ +// s->compressed_len += len << 3; +// s->bits_sent += len << 3; +//#endif + + /* Copy uncompressed bytes from the window to next_out. */ + if (left) { + if (left > len) { + left = len; } - this.addOp(op) - subpatch.edits.push({action: 'remove', index: start, count: deletions}) + //zmemcpy(s->strm->next_out, s->window + s->block_start, left); + s.strm.output.set(s.window.subarray(s.block_start, s.block_start + left), s.strm.next_out); + s.strm.next_out += left; + s.strm.avail_out -= left; + s.strm.total_out += left; + s.block_start += left; + len -= left; } - if (insertions.length > 0) { - this.insertListItems(subpatch, start, insertions, false) + /* Copy uncompressed bytes directly from next_in to next_out, updating + * the check value. + */ + if (len) { + read_buf(s.strm, s.strm.output, s.strm.next_out, len); + s.strm.next_out += len; + s.strm.avail_out -= len; + s.strm.total_out += len; } - this.applyPatch(patch.diffs, this.cache._root, this.updated) - } + } while (last === 0); - /** - * Updates the table object at path `path`, adding a new entry `row`. - * Returns the objectId of the new row. + /* Update the sliding window with the last s->w_size bytes of the copied + * data, or append all of the copied data to the existing window if less + * than s->w_size bytes were copied. Also update the number of bytes to + * insert in the hash tables, in the event that deflateParams() switches to + * a non-zero compression level. */ - addTableRow(path, row) { - if (!isObject(row) || Array.isArray(row)) { - throw new TypeError('A table row must be an object') - } - if (row[OBJECT_ID]) { - throw new TypeError('Cannot reuse an existing object as table row') + used -= s.strm.avail_in; /* number of input bytes directly copied */ + if (used) { + /* If any input was used, then no unused input remains in the window, + * therefore s->block_start == s->strstart. + */ + if (used >= s.w_size) { /* supplant the previous history */ + s.matches = 2; /* clear hash */ + //zmemcpy(s->window, s->strm->next_in - s->w_size, s->w_size); + s.window.set(s.strm.input.subarray(s.strm.next_in - s.w_size, s.strm.next_in), 0); + s.strstart = s.w_size; + s.insert = s.strstart; } - if (row.id) { - throw new TypeError('A table row must not have an "id" property; it is generated automatically') + else { + if (s.window_size - s.strstart <= used) { + /* Slide the window down. */ + s.strstart -= s.w_size; + //zmemcpy(s->window, s->window + s->w_size, s->strstart); + s.window.set(s.window.subarray(s.w_size, s.w_size + s.strstart), 0); + if (s.matches < 2) { + s.matches++; /* add a pending slide_hash() */ + } + if (s.insert > s.strstart) { + s.insert = s.strstart; + } + } + //zmemcpy(s->window + s->strstart, s->strm->next_in - used, used); + s.window.set(s.strm.input.subarray(s.strm.next_in - used, s.strm.next_in), s.strstart); + s.strstart += used; + s.insert += used > s.w_size - s.insert ? s.w_size - s.insert : used; } + s.block_start = s.strstart; + } + if (s.high_water < s.strstart) { + s.high_water = s.strstart; + } - const id = uuid() - const valuePatch = this.setValue(path[path.length - 1].objectId, id, row, false, []) - this.applyAtPath(path, subpatch => { - subpatch.props[id] = {[valuePatch.objectId]: valuePatch} - }) - return id + /* If the last block was written to next_out, then done. */ + if (last) { + return BS_FINISH_DONE; } - /** - * Updates the table object at path `path`, deleting the row with ID `rowId`. - * `pred` is the opId of the operation that originally created the row. - */ - deleteTableRow(path, rowId, pred) { - const objectId = path[path.length - 1].objectId, table = this.getObject(objectId) + /* If flushing and all input has been consumed, then done. */ + if (flush !== Z_NO_FLUSH && flush !== Z_FINISH && + s.strm.avail_in === 0 && s.strstart === s.block_start) { + return BS_BLOCK_DONE; + } - if (table.byId(rowId)) { - this.addOp({action: 'del', obj: objectId, key: rowId, insert: false, pred: [pred]}) - this.applyAtPath(path, subpatch => { - subpatch.props[rowId] = {} - }) + /* Fill the window with any remaining input. */ + have = s.window_size - s.strstart; + if (s.strm.avail_in > have && s.block_start >= s.w_size) { + /* Slide the window down. */ + s.block_start -= s.w_size; + s.strstart -= s.w_size; + //zmemcpy(s->window, s->window + s->w_size, s->strstart); + s.window.set(s.window.subarray(s.w_size, s.w_size + s.strstart), 0); + if (s.matches < 2) { + s.matches++; /* add a pending slide_hash() */ } + have += s.w_size; /* more space now */ + if (s.insert > s.strstart) { + s.insert = s.strstart; + } + } + if (have > s.strm.avail_in) { + have = s.strm.avail_in; + } + if (have) { + read_buf(s.strm, s.window, s.strstart, have); + s.strstart += have; + s.insert += have > s.w_size - s.insert ? s.w_size - s.insert : have; + } + if (s.high_water < s.strstart) { + s.high_water = s.strstart; } - /** - * Adds the integer `delta` to the value of the counter located at property - * `key` in the object at path `path`. + /* There was not enough avail_out to write a complete worthy or flushed + * stored block to next_out. Write a stored block to pending instead, if we + * have enough input for a worthy block, or if flushing and there is enough + * room for the remaining input as a stored block in the pending buffer. */ - increment(path, key, delta) { - const objectId = path.length === 0 ? '_root' : path[path.length - 1].objectId - const object = this.getObject(objectId) - if (!(object[key] instanceof Counter)) { - throw new TypeError('Only counter values can be incremented') - } + have = (s.bi_valid + 42) >> 3; /* number of header bytes */ + /* maximum stored block length that will fit in pending: */ + have = s.pending_buf_size - have > 65535/* MAX_STORED */ ? 65535/* MAX_STORED */ : s.pending_buf_size - have; + min_block = have > s.w_size ? s.w_size : have; + left = s.strstart - s.block_start; + if (left >= min_block || + ((left || flush === Z_FINISH) && flush !== Z_NO_FLUSH && + s.strm.avail_in === 0 && left <= have)) { + len = left > have ? have : left; + last = flush === Z_FINISH && s.strm.avail_in === 0 && + len === left ? 1 : 0; + _tr_stored_block(s, s.block_start, len, last); + s.block_start += len; + flush_pending(s.strm); + } + + /* We've done all we can with the available input and output. */ + return last ? BS_FINISH_STARTED : BS_NEED_MORE; +}; - // TODO what if there is a conflicting value on the same key as the counter? - const type = this.getObjectType(objectId) - const value = object[key].value + delta - const opId = this.nextOpId() - const pred = getPred(object, key) - if (type === 'list' || type === 'text') { - const elemId = getElemId(object, key, false) - this.addOp({action: 'inc', obj: objectId, elemId, value: delta, insert: false, pred}) - } else { - this.addOp({action: 'inc', obj: objectId, key, value: delta, insert: false, pred}) - } +/* =========================================================================== + * Compress as much as possible from the input stream, return the current + * block state. + * This function does not perform lazy evaluation of matches and inserts + * new strings in the dictionary only for unmatched strings or for short + * matches. It is used only for the fast compression options. + */ +const deflate_fast = (s, flush) => { - this.applyAtPath(path, subpatch => { - if (type === 'list' || type === 'text') { - subpatch.edits.push({action: 'update', index: key, opId, value: {value, datatype: 'counter'}}) - } else { - subpatch.props[key] = {[opId]: {value, datatype: 'counter'}} + let hash_head; /* head of the hash chain */ + let bflush; /* set if current block must be flushed */ + + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + if (s.lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s.lookahead < MIN_LOOKAHEAD && flush === Z_NO_FLUSH) { + return BS_NEED_MORE; } - }) - } -} + if (s.lookahead === 0) { + break; /* flush the current block */ + } + } -function getPred(object, key) { - if (object instanceof Table) { - return [object.opIds[key]] - } else if (object instanceof Text) { - return object.elems[key].pred - } else if (object[CONFLICTS]) { - return object[CONFLICTS][key] ? Object.keys(object[CONFLICTS][key]) : [] - } else { - return [] - } -} + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + hash_head = 0/*NIL*/; + if (s.lookahead >= MIN_MATCH) { + /*** INSERT_STRING(s, s.strstart, hash_head); ***/ + s.ins_h = HASH(s, s.ins_h, s.window[s.strstart + MIN_MATCH - 1]); + hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h]; + s.head[s.ins_h] = s.strstart; + /***/ + } -function getElemId(list, index, insert = false) { - if (insert) { - if (index === 0) return '_head' - index -= 1 - } - if (list[ELEM_IDS]) return list[ELEM_IDS][index] - if (list.getElemId) return list.getElemId(index) - throw new RangeError(`Cannot find elemId at list index ${index}`) -} + /* Find the longest match, discarding those <= prev_length. + * At this point we have always match_length < MIN_MATCH + */ + if (hash_head !== 0/*NIL*/ && ((s.strstart - hash_head) <= (s.w_size - MIN_LOOKAHEAD))) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ + s.match_length = longest_match(s, hash_head); + /* longest_match() sets match_start */ + } + if (s.match_length >= MIN_MATCH) { + // check_match(s, s.strstart, s.match_start, s.match_length); // for debug only -module.exports = { - Context -} + /*** _tr_tally_dist(s, s.strstart - s.match_start, + s.match_length - MIN_MATCH, bflush); ***/ + bflush = _tr_tally(s, s.strstart - s.match_start, s.match_length - MIN_MATCH); -},{"../src/common":87,"../src/uuid":88,"./apply_patch":55,"./constants":56,"./counter":58,"./numbers":60,"./table":63,"./text":64}],58:[function(require,module,exports){ -/** - * The most basic CRDT: an integer value that can be changed only by - * incrementing and decrementing. Since addition of integers is commutative, - * the value trivially converges. - */ -class Counter { - constructor(value) { - this.value = value || 0 - Object.freeze(this) - } + s.lookahead -= s.match_length; - /** - * A peculiar JavaScript language feature from its early days: if the object - * `x` has a `valueOf()` method that returns a number, you can use numerical - * operators on the object `x` directly, such as `x + 1` or `x < 4`. - * This method is also called when coercing a value to a string by - * concatenating it with another string, as in `x + ''`. - * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/valueOf - */ - valueOf() { - return this.value - } + /* Insert new strings in the hash table only if the match length + * is not too large. This saves time but degrades compression. + */ + if (s.match_length <= s.max_lazy_match/*max_insert_length*/ && s.lookahead >= MIN_MATCH) { + s.match_length--; /* string at strstart already in table */ + do { + s.strstart++; + /*** INSERT_STRING(s, s.strstart, hash_head); ***/ + s.ins_h = HASH(s, s.ins_h, s.window[s.strstart + MIN_MATCH - 1]); + hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h]; + s.head[s.ins_h] = s.strstart; + /***/ + /* strstart never exceeds WSIZE-MAX_MATCH, so there are + * always MIN_MATCH bytes ahead. + */ + } while (--s.match_length !== 0); + s.strstart++; + } else + { + s.strstart += s.match_length; + s.match_length = 0; + s.ins_h = s.window[s.strstart]; + /* UPDATE_HASH(s, s.ins_h, s.window[s.strstart+1]); */ + s.ins_h = HASH(s, s.ins_h, s.window[s.strstart + 1]); - /** - * Returns the counter value as a decimal string. If `x` is a counter object, - * this method is called e.g. when you do `['value: ', x].join('')` or when - * you use string interpolation: `value: ${x}`. - */ - toString() { - return this.valueOf().toString() - } +//#if MIN_MATCH != 3 +// Call UPDATE_HASH() MIN_MATCH-3 more times +//#endif + /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not + * matter since it will be recomputed at next deflate call. + */ + } + } else { + /* No match, output a literal byte */ + //Tracevv((stderr,"%c", s.window[s.strstart])); + /*** _tr_tally_lit(s, s.window[s.strstart], bflush); ***/ + bflush = _tr_tally(s, 0, s.window[s.strstart]); - /** - * Returns the counter value, so that a JSON serialization of an Automerge - * document represents the counter simply as an integer. - */ - toJSON() { - return this.value + s.lookahead--; + s.strstart++; + } + if (bflush) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + } } -} + s.insert = ((s.strstart < (MIN_MATCH - 1)) ? s.strstart : MIN_MATCH - 1); + if (flush === Z_FINISH) { + /*** FLUSH_BLOCK(s, 1); ***/ + flush_block_only(s, true); + if (s.strm.avail_out === 0) { + return BS_FINISH_STARTED; + } + /***/ + return BS_FINISH_DONE; + } + if (s.sym_next) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + } + return BS_BLOCK_DONE; +}; -/** - * An instance of this class is used when a counter is accessed within a change - * callback. +/* =========================================================================== + * Same as above, but achieves better compression. We use a lazy + * evaluation for matches: a match is finally adopted only if there is + * no better match at the next window position. */ -class WriteableCounter extends Counter { - /** - * Increases the value of the counter by `delta`. If `delta` is not given, - * increases the value of the counter by 1. - */ - increment(delta) { - delta = typeof delta === 'number' ? delta : 1 - this.context.increment(this.path, this.key, delta) - this.value += delta - return this.value - } +const deflate_slow = (s, flush) => { - /** - * Decreases the value of the counter by `delta`. If `delta` is not given, - * decreases the value of the counter by 1. - */ - decrement(delta) { - return this.increment(typeof delta === 'number' ? -delta : -1) - } -} + let hash_head; /* head of hash chain */ + let bflush; /* set if current block must be flushed */ -/** - * Returns an instance of `WriteableCounter` for use in a change callback. - * `context` is the proxy context that keeps track of the mutations. - * `objectId` is the ID of the object containing the counter, and `key` is - * the property name (key in map, or index in list) where the counter is - * located. -*/ -function getWriteableCounter(value, context, path, objectId, key) { - const instance = Object.create(WriteableCounter.prototype) - instance.value = value - instance.context = context - instance.path = path - instance.objectId = objectId - instance.key = key - return instance -} - -module.exports = { Counter, getWriteableCounter } - -},{}],59:[function(require,module,exports){ -const { OPTIONS, CACHE, STATE, OBJECT_ID, CONFLICTS, CHANGE, ELEM_IDS } = require('./constants') -const { isObject, copyObject } = require('../src/common') -const uuid = require('../src/uuid') -const { interpretPatch, cloneRootObject } = require('./apply_patch') -const { rootObjectProxy } = require('./proxies') -const { Context } = require('./context') -const { Text } = require('./text') -const { Table } = require('./table') -const { Counter } = require('./counter') -const { Float64, Int, Uint } = require('./numbers') -const { Observable } = require('./observable') - -/** - * Actor IDs must consist only of hexadecimal digits so that they can be encoded - * compactly in binary form. - */ -function checkActorId(actorId) { - if (typeof actorId !== 'string') { - throw new TypeError(`Unsupported type of actorId: ${typeof actorId}`) - } - if (!/^[0-9a-f]+$/.test(actorId)) { - throw new RangeError('actorId must consist only of lowercase hex digits') - } - if (actorId.length % 2 !== 0) { - throw new RangeError('actorId must consist of an even number of digits') - } -} - -/** - * Takes a set of objects that have been updated (in `updated`) and an updated state object - * `state`, and returns a new immutable document root object based on `doc` that reflects - * those updates. - */ -function updateRootObject(doc, updated, state) { - let newDoc = updated._root - if (!newDoc) { - newDoc = cloneRootObject(doc[CACHE]._root) - updated._root = newDoc - } - Object.defineProperty(newDoc, OPTIONS, {value: doc[OPTIONS]}) - Object.defineProperty(newDoc, CACHE, {value: updated}) - Object.defineProperty(newDoc, STATE, {value: state}) + let max_insert; - if (doc[OPTIONS].freeze) { - for (let objectId of Object.keys(updated)) { - if (updated[objectId] instanceof Table) { - updated[objectId]._freeze() - } else if (updated[objectId] instanceof Text) { - Object.freeze(updated[objectId].elems) - Object.freeze(updated[objectId]) - } else { - Object.freeze(updated[objectId]) - Object.freeze(updated[objectId][CONFLICTS]) + /* Process the input block. */ + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + if (s.lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s.lookahead < MIN_LOOKAHEAD && flush === Z_NO_FLUSH) { + return BS_NEED_MORE; } + if (s.lookahead === 0) { break; } /* flush the current block */ } - } - for (let objectId of Object.keys(doc[CACHE])) { - if (!updated[objectId]) { - updated[objectId] = doc[CACHE][objectId] + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + hash_head = 0/*NIL*/; + if (s.lookahead >= MIN_MATCH) { + /*** INSERT_STRING(s, s.strstart, hash_head); ***/ + s.ins_h = HASH(s, s.ins_h, s.window[s.strstart + MIN_MATCH - 1]); + hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h]; + s.head[s.ins_h] = s.strstart; + /***/ } - } - if (doc[OPTIONS].freeze) { - Object.freeze(updated) - } - return newDoc -} + /* Find the longest match, discarding those <= prev_length. + */ + s.prev_length = s.match_length; + s.prev_match = s.match_start; + s.match_length = MIN_MATCH - 1; -/** - * Adds a new change request to the list of pending requests, and returns an - * updated document root object. - * The details of the change are taken from the context object `context`. - * `options` contains properties that may affect how the change is processed; in - * particular, the `message` property of `options` is an optional human-readable - * string describing the change. - */ -function makeChange(doc, context, options) { - const actor = getActorId(doc) - if (!actor) { - throw new Error('Actor ID must be initialized with setActorId() before making a change') - } - const state = copyObject(doc[STATE]) - state.seq += 1 + if (hash_head !== 0/*NIL*/ && s.prev_length < s.max_lazy_match && + s.strstart - hash_head <= (s.w_size - MIN_LOOKAHEAD)/*MAX_DIST(s)*/) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ + s.match_length = longest_match(s, hash_head); + /* longest_match() sets match_start */ - const change = { - actor, - seq: state.seq, - startOp: state.maxOp + 1, - deps: state.deps, - time: (options && typeof options.time === 'number') ? options.time - : Math.round(new Date().getTime() / 1000), - message: (options && typeof options.message === 'string') ? options.message : '', - ops: context.ops - } + if (s.match_length <= 5 && + (s.strategy === Z_FILTERED || (s.match_length === MIN_MATCH && s.strstart - s.match_start > 4096/*TOO_FAR*/))) { - if (doc[OPTIONS].backend) { - const [backendState, patch, binaryChange] = doc[OPTIONS].backend.applyLocalChange(state.backendState, change) - state.backendState = backendState - state.lastLocalChange = binaryChange - // NOTE: When performing a local change, the patch is effectively applied twice -- once by the - // context invoking interpretPatch as soon as any change is made, and the second time here - // (after a round-trip through the backend). This is perhaps more robust, as changes only take - // effect in the form processed by the backend, but the downside is a performance cost. - // Should we change this? - const newDoc = applyPatchToDoc(doc, patch, state, true) - const patchCallback = options && options.patchCallback || doc[OPTIONS].patchCallback - if (patchCallback) patchCallback(patch, doc, newDoc, true, [binaryChange]) - return [newDoc, change] + /* If prev_match is also MIN_MATCH, match_start is garbage + * but we will ignore the current match anyway. + */ + s.match_length = MIN_MATCH - 1; + } + } + /* If there was a match at the previous step and the current + * match is not better, output the previous match: + */ + if (s.prev_length >= MIN_MATCH && s.match_length <= s.prev_length) { + max_insert = s.strstart + s.lookahead - MIN_MATCH; + /* Do not insert strings in hash table beyond this. */ - } else { - const queuedRequest = {actor, seq: change.seq, before: doc} - state.requests = state.requests.concat([queuedRequest]) - state.maxOp = state.maxOp + countOps(change.ops) - state.deps = [] - return [updateRootObject(doc, context ? context.updated : {}, state), change] - } -} + //check_match(s, s.strstart-1, s.prev_match, s.prev_length); -function countOps(ops) { - let count = 0 - for (const op of ops) { - if (op.action === 'set' && op.values) { - count += op.values.length - } else { - count += 1 - } - } - return count -} + /***_tr_tally_dist(s, s.strstart - 1 - s.prev_match, + s.prev_length - MIN_MATCH, bflush);***/ + bflush = _tr_tally(s, s.strstart - 1 - s.prev_match, s.prev_length - MIN_MATCH); + /* Insert in hash table all strings up to the end of the match. + * strstart-1 and strstart are already inserted. If there is not + * enough lookahead, the last two strings are not inserted in + * the hash table. + */ + s.lookahead -= s.prev_length - 1; + s.prev_length -= 2; + do { + if (++s.strstart <= max_insert) { + /*** INSERT_STRING(s, s.strstart, hash_head); ***/ + s.ins_h = HASH(s, s.ins_h, s.window[s.strstart + MIN_MATCH - 1]); + hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h]; + s.head[s.ins_h] = s.strstart; + /***/ + } + } while (--s.prev_length !== 0); + s.match_available = 0; + s.match_length = MIN_MATCH - 1; + s.strstart++; -/** - * Returns the binary encoding of the last change made by the local actor. - */ -function getLastLocalChange(doc) { - return doc[STATE] && doc[STATE].lastLocalChange ? doc[STATE].lastLocalChange : null -} + if (bflush) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + } -/** - * Applies the changes described in `patch` to the document with root object - * `doc`. The state object `state` is attached to the new root object. - * `fromBackend` should be set to `true` if the patch came from the backend, - * and to `false` if the patch is a transient local (optimistically applied) - * change from the frontend. - */ -function applyPatchToDoc(doc, patch, state, fromBackend) { - const actor = getActorId(doc) - const updated = {} - interpretPatch(patch.diffs, doc, updated) + } else if (s.match_available) { + /* If there was no match at the previous position, output a + * single literal. If there was a match but the current match + * is longer, truncate the previous match to a single literal. + */ + //Tracevv((stderr,"%c", s->window[s->strstart-1])); + /*** _tr_tally_lit(s, s.window[s.strstart-1], bflush); ***/ + bflush = _tr_tally(s, 0, s.window[s.strstart - 1]); - if (fromBackend) { - if (!patch.clock) throw new RangeError('patch is missing clock field') - if (patch.clock[actor] && patch.clock[actor] > state.seq) { - state.seq = patch.clock[actor] + if (bflush) { + /*** FLUSH_BLOCK_ONLY(s, 0) ***/ + flush_block_only(s, false); + /***/ + } + s.strstart++; + s.lookahead--; + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + } else { + /* There is no previous match to compare with, wait for + * the next step to decide. + */ + s.match_available = 1; + s.strstart++; + s.lookahead--; } - state.clock = patch.clock - state.deps = patch.deps - state.maxOp = Math.max(state.maxOp, patch.maxOp) } - return updateRootObject(doc, updated, state) -} + //Assert (flush != Z_NO_FLUSH, "no flush?"); + if (s.match_available) { + //Tracevv((stderr,"%c", s->window[s->strstart-1])); + /*** _tr_tally_lit(s, s.window[s.strstart-1], bflush); ***/ + bflush = _tr_tally(s, 0, s.window[s.strstart - 1]); -/** - * Creates an empty document object with no changes. - */ -function init(options) { - if (typeof options === 'string') { - options = {actorId: options} - } else if (typeof options === 'undefined') { - options = {} - } else if (!isObject(options)) { - throw new TypeError(`Unsupported value for init() options: ${options}`) + s.match_available = 0; } - - if (!options.deferActorId) { - if (options.actorId === undefined) { - options.actorId = uuid() + s.insert = s.strstart < MIN_MATCH - 1 ? s.strstart : MIN_MATCH - 1; + if (flush === Z_FINISH) { + /*** FLUSH_BLOCK(s, 1); ***/ + flush_block_only(s, true); + if (s.strm.avail_out === 0) { + return BS_FINISH_STARTED; } - checkActorId(options.actorId) + /***/ + return BS_FINISH_DONE; } - - if (options.observable) { - const patchCallback = options.patchCallback, observable = options.observable - options.patchCallback = (patch, before, after, local, changes) => { - if (patchCallback) patchCallback(patch, before, after, local, changes) - observable.patchCallback(patch, before, after, local, changes) + if (s.sym_next) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; } + /***/ } - const root = {}, cache = {_root: root} - const state = {seq: 0, maxOp: 0, requests: [], clock: {}, deps: []} - if (options.backend) { - state.backendState = options.backend.init() - state.lastLocalChange = null - } - Object.defineProperty(root, OBJECT_ID, {value: '_root'}) - Object.defineProperty(root, OPTIONS, {value: Object.freeze(options)}) - Object.defineProperty(root, CONFLICTS, {value: Object.freeze({})}) - Object.defineProperty(root, CACHE, {value: Object.freeze(cache)}) - Object.defineProperty(root, STATE, {value: Object.freeze(state)}) - return Object.freeze(root) -} - -/** - * Returns a new document object initialized with the given state. - */ -function from(initialState, options) { - return change(init(options), 'Initialization', doc => Object.assign(doc, initialState)) -} + return BS_BLOCK_DONE; +}; -/** - * Changes a document `doc` according to actions taken by the local user. - * `options` is an object that can contain the following properties: - * - `message`: an optional descriptive string that is attached to the change. - * If `options` is a string, it is treated as `message`. - * - * The actual change is made within the callback function `callback`, which is - * given a mutable version of the document as argument. Returns a two-element - * array `[doc, request]` where `doc` is the updated document, and `request` - * is the change request to send to the backend. If nothing was actually - * changed, returns the original `doc` and a `null` change request. +/* =========================================================================== + * For Z_RLE, simply look for runs of bytes, generate matches only of distance + * one. Do not maintain a hash table. (It will be regenerated if this run of + * deflate switches away from Z_RLE.) */ -function change(doc, options, callback) { - if (doc[OBJECT_ID] !== '_root') { - throw new TypeError('The first argument to Automerge.change must be the document root') - } - if (doc[CHANGE]) { - throw new TypeError('Calls to Automerge.change cannot be nested') - } - if (typeof options === 'function' && callback === undefined) { - [options, callback] = [callback, options] - } - if (typeof options === 'string') { - options = {message: options} - } - if (options !== undefined && !isObject(options)) { - throw new TypeError('Unsupported type of options') - } +const deflate_rle = (s, flush) => { - const actorId = getActorId(doc) - if (!actorId) { - throw new Error('Actor ID must be initialized with setActorId() before making a change') - } - const context = new Context(doc, actorId) - callback(rootObjectProxy(context)) + let bflush; /* set if current block must be flushed */ + let prev; /* byte at distance one to match */ + let scan, strend; /* scan goes up to strend for length of run */ - if (Object.keys(context.updated).length === 0) { - // If the callback didn't change anything, return the original document object unchanged - return [doc, null] - } else { - return makeChange(doc, context, options) - } -} + const _win = s.window; -/** - * Triggers a new change request on the document `doc` without actually - * modifying its data. `options` is an object as described in the documentation - * for the `change` function. This function can be useful for acknowledging the - * receipt of some message (as it's incorported into the `deps` field of the - * change). Returns a two-element array `[doc, request]` where `doc` is the - * updated document, and `request` is the change request to send to the backend. - */ -function emptyChange(doc, options) { - if (doc[OBJECT_ID] !== '_root') { - throw new TypeError('The first argument to Automerge.emptyChange must be the document root') - } - if (typeof options === 'string') { - options = {message: options} - } - if (options !== undefined && !isObject(options)) { - throw new TypeError('Unsupported type of options') - } + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the longest run, plus one for the unrolled loop. + */ + if (s.lookahead <= MAX_MATCH) { + fill_window(s); + if (s.lookahead <= MAX_MATCH && flush === Z_NO_FLUSH) { + return BS_NEED_MORE; + } + if (s.lookahead === 0) { break; } /* flush the current block */ + } - const actorId = getActorId(doc) - if (!actorId) { - throw new Error('Actor ID must be initialized with setActorId() before making a change') - } - return makeChange(doc, new Context(doc, actorId), options) -} + /* See how many times the previous byte repeats */ + s.match_length = 0; + if (s.lookahead >= MIN_MATCH && s.strstart > 0) { + scan = s.strstart - 1; + prev = _win[scan]; + if (prev === _win[++scan] && prev === _win[++scan] && prev === _win[++scan]) { + strend = s.strstart + MAX_MATCH; + do { + /*jshint noempty:false*/ + } while (prev === _win[++scan] && prev === _win[++scan] && + prev === _win[++scan] && prev === _win[++scan] && + prev === _win[++scan] && prev === _win[++scan] && + prev === _win[++scan] && prev === _win[++scan] && + scan < strend); + s.match_length = MAX_MATCH - (strend - scan); + if (s.match_length > s.lookahead) { + s.match_length = s.lookahead; + } + } + //Assert(scan <= s->window+(uInt)(s->window_size-1), "wild scan"); + } -/** - * Applies `patch` to the document root object `doc`. This patch must come - * from the backend; it may be the result of a local change or a remote change. - * If it is the result of a local change, the `seq` field from the change - * request should be included in the patch, so that we can match them up here. - */ -function applyPatch(doc, patch, backendState = undefined) { - if (doc[OBJECT_ID] !== '_root') { - throw new TypeError('The first argument to Frontend.applyPatch must be the document root') - } - const state = copyObject(doc[STATE]) + /* Emit match if have run of MIN_MATCH or longer, else emit literal */ + if (s.match_length >= MIN_MATCH) { + //check_match(s, s.strstart, s.strstart - 1, s.match_length); - if (doc[OPTIONS].backend) { - if (!backendState) { - throw new RangeError('applyPatch must be called with the updated backend state') - } - state.backendState = backendState - return applyPatchToDoc(doc, patch, state, true) - } + /*** _tr_tally_dist(s, 1, s.match_length - MIN_MATCH, bflush); ***/ + bflush = _tr_tally(s, 1, s.match_length - MIN_MATCH); - let baseDoc + s.lookahead -= s.match_length; + s.strstart += s.match_length; + s.match_length = 0; + } else { + /* No match, output a literal byte */ + //Tracevv((stderr,"%c", s->window[s->strstart])); + /*** _tr_tally_lit(s, s.window[s.strstart], bflush); ***/ + bflush = _tr_tally(s, 0, s.window[s.strstart]); - if (state.requests.length > 0) { - baseDoc = state.requests[0].before - if (patch.actor === getActorId(doc)) { - if (state.requests[0].seq !== patch.seq) { - throw new RangeError(`Mismatched sequence number: patch ${patch.seq} does not match next request ${state.requests[0].seq}`) + s.lookahead--; + s.strstart++; + } + if (bflush) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; } - state.requests = state.requests.slice(1) - } else { - state.requests = state.requests.slice() + /***/ } - } else { - baseDoc = doc - state.requests = [] } - - let newDoc = applyPatchToDoc(baseDoc, patch, state, true) - if (state.requests.length === 0) { - return newDoc - } else { - state.requests[0] = copyObject(state.requests[0]) - state.requests[0].before = newDoc - return updateRootObject(doc, {}, state) + s.insert = 0; + if (flush === Z_FINISH) { + /*** FLUSH_BLOCK(s, 1); ***/ + flush_block_only(s, true); + if (s.strm.avail_out === 0) { + return BS_FINISH_STARTED; + } + /***/ + return BS_FINISH_DONE; } -} - -/** - * Returns the Automerge object ID of the given object. - */ -function getObjectId(object) { - return object[OBJECT_ID] -} - -/** - * Returns the object with the given Automerge object ID. Note: when called - * within a change callback, the returned object is read-only (not a mutable - * proxy object). - */ -function getObjectById(doc, objectId) { - // It would be nice to return a proxied object in a change callback. - // However, that requires knowing the path from the root to the current - // object, which we don't have if we jumped straight to the object by its ID. - // If we maintained an index from object ID to parent ID we could work out the path. - if (doc[CHANGE]) { - throw new TypeError('Cannot use getObjectById in a change callback') - } - return doc[CACHE][objectId] -} - -/** - * Returns the Automerge actor ID of the given document. - */ -function getActorId(doc) { - return doc[STATE].actorId || doc[OPTIONS].actorId -} - -/** - * Sets the Automerge actor ID on the document object `doc`, returning a - * document object with updated metadata. - */ -function setActorId(doc, actorId) { - checkActorId(actorId) - const state = Object.assign({}, doc[STATE], {actorId}) - return updateRootObject(doc, {}, state) -} - -/** - * Fetches the conflicts on the property `key` of `object`, which may be any - * object in a document. If `object` is a list, then `key` must be a list - * index; if `object` is a map, then `key` must be a property name. - */ -function getConflicts(object, key) { - if (object[CONFLICTS] && object[CONFLICTS][key] && - Object.keys(object[CONFLICTS][key]).length > 1) { - return object[CONFLICTS][key] - } -} - -/** - * Returns the backend state associated with the document `doc` (only used if - * a backend implementation is passed to `init()`). - */ -function getBackendState(doc, callerName = null, argPos = 'first') { - if (doc[OBJECT_ID] !== '_root') { - // Most likely cause of passing an array here is forgetting to deconstruct the return value of - // Automerge.applyChanges(). - const extraMsg = Array.isArray(doc) ? '. Note: Automerge.applyChanges now returns an array.' : '' - if (callerName) { - throw new TypeError(`The ${argPos} argument to Automerge.${callerName} must be the document root${extraMsg}`) - } else { - throw new TypeError(`Argument is not an Automerge document root${extraMsg}`) + if (s.sym_next) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; } + /***/ } - return doc[STATE].backendState -} + return BS_BLOCK_DONE; +}; -/** - * Given an array or text object from an Automerge document, returns an array - * containing the unique element ID of each list element/character. +/* =========================================================================== + * For Z_HUFFMAN_ONLY, do not look for matches. Do not maintain a hash table. + * (It will be regenerated if this run of deflate switches away from Huffman.) */ -function getElementIds(list) { - if (list instanceof Text) { - return list.elems.map(elem => elem.elemId) - } else { - return list[ELEM_IDS] - } -} +const deflate_huff = (s, flush) => { -module.exports = { - init, from, change, emptyChange, applyPatch, - getObjectId, getObjectById, getActorId, setActorId, getConflicts, getLastLocalChange, - getBackendState, getElementIds, - Text, Table, Counter, Observable, Float64, Int, Uint -} + let bflush; /* set if current block must be flushed */ -},{"../src/common":87,"../src/uuid":88,"./apply_patch":55,"./constants":56,"./context":57,"./counter":58,"./numbers":60,"./observable":61,"./proxies":62,"./table":63,"./text":64}],60:[function(require,module,exports){ -// Convience classes to allow users to stricly specify the number type they want + for (;;) { + /* Make sure that we have a literal to write. */ + if (s.lookahead === 0) { + fill_window(s); + if (s.lookahead === 0) { + if (flush === Z_NO_FLUSH) { + return BS_NEED_MORE; + } + break; /* flush the current block */ + } + } -class Int { - constructor(value) { - if (!(Number.isInteger(value) && value <= Number.MAX_SAFE_INTEGER && value >= Number.MIN_SAFE_INTEGER)) { - throw new RangeError(`Value ${value} cannot be a uint`) + /* Output a literal byte */ + s.match_length = 0; + //Tracevv((stderr,"%c", s->window[s->strstart])); + /*** _tr_tally_lit(s, s.window[s.strstart], bflush); ***/ + bflush = _tr_tally(s, 0, s.window[s.strstart]); + s.lookahead--; + s.strstart++; + if (bflush) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ } - this.value = value - Object.freeze(this) } -} - -class Uint { - constructor(value) { - if (!(Number.isInteger(value) && value <= Number.MAX_SAFE_INTEGER && value >= 0)) { - throw new RangeError(`Value ${value} cannot be a uint`) + s.insert = 0; + if (flush === Z_FINISH) { + /*** FLUSH_BLOCK(s, 1); ***/ + flush_block_only(s, true); + if (s.strm.avail_out === 0) { + return BS_FINISH_STARTED; } - this.value = value - Object.freeze(this) + /***/ + return BS_FINISH_DONE; } -} - -class Float64 { - constructor(value) { - if (typeof value !== 'number') { - throw new RangeError(`Value ${value} cannot be a float64`) + if (s.sym_next) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; } - this.value = value || 0.0 - Object.freeze(this) + /***/ } + return BS_BLOCK_DONE; +}; + +/* Values for max_lazy_match, good_match and max_chain_length, depending on + * the desired pack level (0..9). The values given below have been tuned to + * exclude worst case performance for pathological files. Better values may be + * found for specific files. + */ +function Config(good_length, max_lazy, nice_length, max_chain, func) { + + this.good_length = good_length; + this.max_lazy = max_lazy; + this.nice_length = nice_length; + this.max_chain = max_chain; + this.func = func; } -module.exports = { Int, Uint, Float64 } +const configuration_table = [ + /* good lazy nice chain */ + new Config(0, 0, 0, 0, deflate_stored), /* 0 store only */ + new Config(4, 4, 8, 4, deflate_fast), /* 1 max speed, no lazy matches */ + new Config(4, 5, 16, 8, deflate_fast), /* 2 */ + new Config(4, 6, 32, 32, deflate_fast), /* 3 */ -},{}],61:[function(require,module,exports){ -const { OBJECT_ID, CONFLICTS } = require('./constants') + new Config(4, 4, 16, 16, deflate_slow), /* 4 lazy matches */ + new Config(8, 16, 32, 32, deflate_slow), /* 5 */ + new Config(8, 16, 128, 128, deflate_slow), /* 6 */ + new Config(8, 32, 128, 256, deflate_slow), /* 7 */ + new Config(32, 128, 258, 1024, deflate_slow), /* 8 */ + new Config(32, 258, 258, 4096, deflate_slow) /* 9 max compression */ +]; -/** - * Allows an application to register a callback when a particular object in - * a document changes. - * - * NOTE: This API is experimental and may change without warning in minor releases. + +/* =========================================================================== + * Initialize the "longest match" routines for a new zlib stream */ -class Observable { - constructor() { - this.observers = {} // map from objectId to array of observers for that object - } +const lm_init = (s) => { - /** - * Called by an Automerge document when `patch` is applied. `before` is the - * state of the document before the patch, and `after` is the state after - * applying it. `local` is true if the update is a result of locally calling - * `Automerge.change()`, and false otherwise. `changes` is an array of - * changes that were applied to the document (as Uint8Arrays). - */ - patchCallback(patch, before, after, local, changes) { - this._objectUpdate(patch.diffs, before, after, local, changes) - } + s.window_size = 2 * s.w_size; - /** - * Recursively walks a patch and calls the callbacks for all objects that - * appear in the patch. + /*** CLEAR_HASH(s); ***/ + zero(s.head); // Fill with NIL (= 0); + + /* Set the default configuration parameters: */ - _objectUpdate(diff, before, after, local, changes) { - if (!diff.objectId) return - if (this.observers[diff.objectId]) { - for (let callback of this.observers[diff.objectId]) { - callback(diff, before, after, local, changes) - } - } + s.max_lazy_match = configuration_table[s.level].max_lazy; + s.good_match = configuration_table[s.level].good_length; + s.nice_match = configuration_table[s.level].nice_length; + s.max_chain_length = configuration_table[s.level].max_chain; - if (diff.type === 'map' && diff.props) { - for (const propName of Object.keys(diff.props)) { - for (const opId of Object.keys(diff.props[propName])) { - this._objectUpdate(diff.props[propName][opId], - before && before[CONFLICTS] && before[CONFLICTS][propName] && before[CONFLICTS][propName][opId], - after && after[CONFLICTS] && after[CONFLICTS][propName] && after[CONFLICTS][propName][opId], - local, changes) - } - } + s.strstart = 0; + s.block_start = 0; + s.lookahead = 0; + s.insert = 0; + s.match_length = s.prev_length = MIN_MATCH - 1; + s.match_available = 0; + s.ins_h = 0; +}; - } else if (diff.type === 'table' && diff.props) { - for (const rowId of Object.keys(diff.props)) { - for (const opId of Object.keys(diff.props[rowId])) { - this._objectUpdate(diff.props[rowId][opId], - before && before.byId(rowId), - after && after.byId(rowId), - local, changes) - } - } - } else if (diff.type === 'list' && diff.edits) { - let offset = 0 - for (const edit of diff.edits) { - if (edit.action === 'insert') { - offset -= 1 - this._objectUpdate(edit.value, undefined, - after && after[CONFLICTS] && after[CONFLICTS][edit.index] && after[CONFLICTS][edit.index][edit.elemId], - local, changes) - } else if (edit.action === 'multi-insert') { - offset -= edit.values.length - } else if (edit.action === 'update') { - this._objectUpdate(edit.value, - before && before[CONFLICTS] && before[CONFLICTS][edit.index + offset] && - before[CONFLICTS][edit.index + offset][edit.opId], - after && after[CONFLICTS] && after[CONFLICTS][edit.index] && after[CONFLICTS][edit.index][edit.opId], - local, changes) - } else if (edit.action === 'remove') { - offset += edit.count - } - } +function DeflateState() { + this.strm = null; /* pointer back to this zlib stream */ + this.status = 0; /* as the name implies */ + this.pending_buf = null; /* output still pending */ + this.pending_buf_size = 0; /* size of pending_buf */ + this.pending_out = 0; /* next pending byte to output to the stream */ + this.pending = 0; /* nb of bytes in the pending buffer */ + this.wrap = 0; /* bit 0 true for zlib, bit 1 true for gzip */ + this.gzhead = null; /* gzip header information to write */ + this.gzindex = 0; /* where in extra, name, or comment */ + this.method = Z_DEFLATED; /* can only be DEFLATED */ + this.last_flush = -1; /* value of flush param for previous deflate call */ - } else if (diff.type === 'text' && diff.edits) { - let offset = 0 - for (const edit of diff.edits) { - if (edit.action === 'insert') { - offset -= 1 - this._objectUpdate(edit.value, undefined, after && after.get(edit.index), local, changes) - } else if (edit.action === 'multi-insert') { - offset -= edit.values.length - } else if (edit.action === 'update') { - this._objectUpdate(edit.value, - before && before.get(edit.index + offset), - after && after.get(edit.index), - local, changes) - } else if (edit.action === 'remove') { - offset += edit.count - } - } - } - } + this.w_size = 0; /* LZ77 window size (32K by default) */ + this.w_bits = 0; /* log2(w_size) (8..16) */ + this.w_mask = 0; /* w_size - 1 */ - /** - * Call this to register a callback that will get called whenever a particular - * object in a document changes. The callback is passed five arguments: the - * part of the patch describing the update to that object, the old state of - * the object, the new state of the object, a boolean that is true if the - * change is the result of calling `Automerge.change()` locally, and the array - * of binary changes applied to the document. + this.window = null; + /* Sliding window. Input bytes are read into the second half of the window, + * and move to the first half later to keep a dictionary of at least wSize + * bytes. With this organization, matches are limited to a distance of + * wSize-MAX_MATCH bytes, but this ensures that IO is always + * performed with a length multiple of the block size. */ - observe(object, callback) { - const objectId = object[OBJECT_ID] - if (!objectId) throw new TypeError('The observed object must be part of an Automerge document') - if (!this.observers[objectId]) this.observers[objectId] = [] - this.observers[objectId].push(callback) - } -} -module.exports = { Observable } + this.window_size = 0; + /* Actual size of window: 2*wSize, except when the user input buffer + * is directly used as sliding window. + */ -},{"./constants":56}],62:[function(require,module,exports){ -const { OBJECT_ID, CHANGE, STATE } = require('./constants') -const { createArrayOfNulls } = require('../src/common') -const { Text } = require('./text') -const { Table } = require('./table') + this.prev = null; + /* Link to older string with same hash index. To limit the size of this + * array to 64K, this link is maintained only for the last 32K strings. + * An index in this array is thus a window index modulo 32K. + */ -function parseListIndex(key) { - if (typeof key === 'string' && /^[0-9]+$/.test(key)) key = parseInt(key, 10) - if (typeof key !== 'number') { - throw new TypeError('A list index must be a number, but you passed ' + JSON.stringify(key)) - } - if (key < 0 || isNaN(key) || key === Infinity || key === -Infinity) { - throw new RangeError('A list index must be positive, but you passed ' + key) - } - return key -} + this.head = null; /* Heads of the hash chains or NIL. */ -function listMethods(context, listId, path) { - const methods = { - deleteAt(index, numDelete) { - context.splice(path, parseListIndex(index), numDelete || 1, []) - return this - }, + this.ins_h = 0; /* hash index of string to be inserted */ + this.hash_size = 0; /* number of elements in hash table */ + this.hash_bits = 0; /* log2(hash_size) */ + this.hash_mask = 0; /* hash_size-1 */ - fill(value, start, end) { - let list = context.getObject(listId) - for (let index = parseListIndex(start || 0); index < parseListIndex(end || list.length); index++) { - context.setListIndex(path, index, value) - } - return this - }, + this.hash_shift = 0; + /* Number of bits by which ins_h must be shifted at each input + * step. It must be such that after MIN_MATCH steps, the oldest + * byte no longer takes part in the hash key, that is: + * hash_shift * MIN_MATCH >= hash_bits + */ - indexOf(o, start = 0) { - const id = o[OBJECT_ID] - if (id) { - const list = context.getObject(listId) - for (let index = start; index < list.length; index++) { - if (list[index][OBJECT_ID] === id) { - return index - } - } - return -1 - } else { - return context.getObject(listId).indexOf(o, start) - } - }, + this.block_start = 0; + /* Window position at the beginning of the current output block. Gets + * negative when the window is moved backwards. + */ - insertAt(index, ...values) { - context.splice(path, parseListIndex(index), 0, values) - return this - }, + this.match_length = 0; /* length of best match */ + this.prev_match = 0; /* previous match */ + this.match_available = 0; /* set if previous match exists */ + this.strstart = 0; /* start of string to insert */ + this.match_start = 0; /* start of matching string */ + this.lookahead = 0; /* number of valid bytes ahead in window */ - pop() { - let list = context.getObject(listId) - if (list.length == 0) return - const last = context.getObjectField(path, listId, list.length - 1) - context.splice(path, list.length - 1, 1, []) - return last - }, + this.prev_length = 0; + /* Length of the best match at previous step. Matches not greater than this + * are discarded. This is used in the lazy match evaluation. + */ - push(...values) { - let list = context.getObject(listId) - context.splice(path, list.length, 0, values) - // need to getObject() again because the list object above may be immutable - return context.getObject(listId).length - }, + this.max_chain_length = 0; + /* To speed up deflation, hash chains are never searched beyond this + * length. A higher limit improves compression ratio but degrades the + * speed. + */ - shift() { - let list = context.getObject(listId) - if (list.length == 0) return - const first = context.getObjectField(path, listId, 0) - context.splice(path, 0, 1, []) - return first - }, + this.max_lazy_match = 0; + /* Attempt to find a better match only when the current match is strictly + * smaller than this value. This mechanism is used only for compression + * levels >= 4. + */ + // That's alias to max_lazy_match, don't use directly + //this.max_insert_length = 0; + /* Insert new strings in the hash table only if the match length is not + * greater than this length. This saves time but degrades compression. + * max_insert_length is used only for compression levels <= 3. + */ - splice(start, deleteCount, ...values) { - let list = context.getObject(listId) - start = parseListIndex(start) - if (deleteCount === undefined || deleteCount > list.length - start) { - deleteCount = list.length - start - } - const deleted = [] - for (let n = 0; n < deleteCount; n++) { - deleted.push(context.getObjectField(path, listId, start + n)) - } - context.splice(path, start, deleteCount, values) - return deleted - }, + this.level = 0; /* compression level (1..9) */ + this.strategy = 0; /* favor or force Huffman coding*/ - unshift(...values) { - context.splice(path, 0, 0, values) - return context.getObject(listId).length - } - } + this.good_match = 0; + /* Use a faster search when the previous match is longer than this */ - for (let iterator of ['entries', 'keys', 'values']) { - let list = context.getObject(listId) - methods[iterator] = () => list[iterator]() - } + this.nice_match = 0; /* Stop searching when current match exceeds this */ - // Read-only methods that can delegate to the JavaScript built-in implementations - for (let method of ['concat', 'every', 'filter', 'find', 'findIndex', 'forEach', 'includes', - 'join', 'lastIndexOf', 'map', 'reduce', 'reduceRight', - 'slice', 'some', 'toLocaleString', 'toString']) { - methods[method] = (...args) => { - const list = context.getObject(listId) - .map((item, index) => context.getObjectField(path, listId, index)) - return list[method](...args) - } - } + /* used by trees.c: */ - return methods -} + /* Didn't use ct_data typedef below to suppress compiler warning */ -const MapHandler = { - get (target, key) { - const { context, objectId, path } = target - if (key === OBJECT_ID) return objectId - if (key === CHANGE) return context - if (key === STATE) return {actorId: context.actorId} - return context.getObjectField(path, objectId, key) - }, + // struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ + // struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ + // struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ - set (target, key, value) { - const { context, path, readonly } = target - if (Array.isArray(readonly) && readonly.indexOf(key) >= 0) { - throw new RangeError(`Object property "${key}" cannot be modified`) - } - context.setMapKey(path, key, value) - return true - }, + // Use flat array of DOUBLE size, with interleaved fata, + // because JS does not support effective + this.dyn_ltree = new Uint16Array(HEAP_SIZE * 2); + this.dyn_dtree = new Uint16Array((2 * D_CODES + 1) * 2); + this.bl_tree = new Uint16Array((2 * BL_CODES + 1) * 2); + zero(this.dyn_ltree); + zero(this.dyn_dtree); + zero(this.bl_tree); - deleteProperty (target, key) { - const { context, path, readonly } = target - if (Array.isArray(readonly) && readonly.indexOf(key) >= 0) { - throw new RangeError(`Object property "${key}" cannot be modified`) - } - context.deleteMapKey(path, key) - return true - }, - - has (target, key) { - const { context, objectId } = target - return [OBJECT_ID, CHANGE].includes(key) || (key in context.getObject(objectId)) - }, + this.l_desc = null; /* desc. for literal tree */ + this.d_desc = null; /* desc. for distance tree */ + this.bl_desc = null; /* desc. for bit length tree */ - getOwnPropertyDescriptor (target, key) { - const { context, objectId } = target - const object = context.getObject(objectId) - if (key in object) { - return { - configurable: true, enumerable: true, - value: context.getObjectField(objectId, key) - } - } - }, + //ush bl_count[MAX_BITS+1]; + this.bl_count = new Uint16Array(MAX_BITS + 1); + /* number of codes at each bit length for an optimal tree */ - ownKeys (target) { - const { context, objectId } = target - return Object.keys(context.getObject(objectId)) - } -} + //int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ + this.heap = new Uint16Array(2 * L_CODES + 1); /* heap used to build the Huffman trees */ + zero(this.heap); -const ListHandler = { - get (target, key) { - const [context, objectId, path] = target - if (key === Symbol.iterator) return context.getObject(objectId)[Symbol.iterator] - if (key === OBJECT_ID) return objectId - if (key === CHANGE) return context - if (key === 'length') return context.getObject(objectId).length - if (typeof key === 'string' && /^[0-9]+$/.test(key)) { - return context.getObjectField(path, objectId, parseListIndex(key)) - } - return listMethods(context, objectId, path)[key] - }, + this.heap_len = 0; /* number of elements in the heap */ + this.heap_max = 0; /* element of largest frequency */ + /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. + * The same heap array is used to build all trees. + */ - set (target, key, value) { - const [context, objectId, path] = target - if (key === 'length') { - if (typeof value !== 'number') { - throw new RangeError("Invalid array length") - } - const length = context.getObject(objectId).length - if (length > value) { - context.splice(path, value, length - value, []) - } else { - context.splice(path, length, 0, createArrayOfNulls(value - length)) - } - } else { - context.setListIndex(path, parseListIndex(key), value) - } - return true - }, + this.depth = new Uint16Array(2 * L_CODES + 1); //uch depth[2*L_CODES+1]; + zero(this.depth); + /* Depth of each subtree used as tie breaker for trees of equal frequency + */ - deleteProperty (target, key) { - const [context, /* objectId */, path] = target - context.splice(path, parseListIndex(key), 1, []) - return true - }, + this.sym_buf = 0; /* buffer for distances and literals/lengths */ - has (target, key) { - const [context, objectId, /* path */] = target - if (typeof key === 'string' && /^[0-9]+$/.test(key)) { - return parseListIndex(key) < context.getObject(objectId).length - } - return ['length', OBJECT_ID, CHANGE].includes(key) - }, + this.lit_bufsize = 0; + /* Size of match buffer for literals/lengths. There are 4 reasons for + * limiting lit_bufsize to 64K: + * - frequencies can be kept in 16 bit counters + * - if compression is not successful for the first block, all input + * data is still in the window so we can still emit a stored block even + * when input comes from standard input. (This can also be done for + * all blocks if lit_bufsize is not greater than 32K.) + * - if compression is not successful for a file smaller than 64K, we can + * even emit a stored file instead of a stored block (saving 5 bytes). + * This is applicable only for zip (not gzip or zlib). + * - creating new Huffman trees less frequently may not provide fast + * adaptation to changes in the input data statistics. (Take for + * example a binary file with poorly compressible code followed by + * a highly compressible string table.) Smaller buffer sizes give + * fast adaptation but have of course the overhead of transmitting + * trees more frequently. + * - I can't count above 4 + */ - getOwnPropertyDescriptor (target, key) { - const [context, objectId, /* path */] = target - const object = context.getObject(objectId) + this.sym_next = 0; /* running index in sym_buf */ + this.sym_end = 0; /* symbol table full when sym_next reaches this */ - if (key === 'length') return {writable: true, value: object.length} - if (key === OBJECT_ID) return {configurable: false, enumerable: false, value: objectId} + this.opt_len = 0; /* bit length of current block with optimal trees */ + this.static_len = 0; /* bit length of current block with static trees */ + this.matches = 0; /* number of string matches in current block */ + this.insert = 0; /* bytes at end of window left to insert */ - if (typeof key === 'string' && /^[0-9]+$/.test(key)) { - const index = parseListIndex(key) - if (index < object.length) return { - configurable: true, enumerable: true, - value: context.getObjectField(objectId, index) - } - } - }, - ownKeys (target) { - const [context, objectId, /* path */] = target - const object = context.getObject(objectId) - let keys = ['length'] - for (let key of Object.keys(object)) keys.push(key) - return keys - } -} + this.bi_buf = 0; + /* Output buffer. bits are inserted starting at the bottom (least + * significant bits). + */ + this.bi_valid = 0; + /* Number of valid bits in bi_buf. All bits above the last valid bit + * are always zero. + */ -function mapProxy(context, objectId, path, readonly) { - return new Proxy({context, objectId, path, readonly}, MapHandler) + // Used for window memory init. We safely ignore it for JS. That makes + // sense only for pointers and memory check tools. + //this.high_water = 0; + /* High water mark offset in window for initialized bytes -- bytes above + * this are set to zero in order to avoid memory check warnings when + * longest match routines access bytes past the input. This is then + * updated to the new high water mark. + */ } -function listProxy(context, objectId, path) { - return new Proxy([context, objectId, path], ListHandler) -} -/** - * Instantiates a proxy object for the given `objectId`. - * This function is added as a method to the context object by rootObjectProxy(). - * When it is called, `this` is the context object. - * `readonly` is a list of map property names that cannot be modified. +/* ========================================================================= + * Check for a valid deflate stream state. Return 0 if ok, 1 if not. */ -function instantiateProxy(path, objectId, readonly) { - const object = this.getObject(objectId) - if (Array.isArray(object)) { - return listProxy(this, objectId, path) - } else if (object instanceof Text || object instanceof Table) { - return object.getWriteable(this, path) - } else { - return mapProxy(this, objectId, path, readonly) +const deflateStateCheck = (strm) => { + + if (!strm) { + return 1; } -} + const s = strm.state; + if (!s || s.strm !== strm || (s.status !== INIT_STATE && +//#ifdef GZIP + s.status !== GZIP_STATE && +//#endif + s.status !== EXTRA_STATE && + s.status !== NAME_STATE && + s.status !== COMMENT_STATE && + s.status !== HCRC_STATE && + s.status !== BUSY_STATE && + s.status !== FINISH_STATE)) { + return 1; + } + return 0; +}; -function rootObjectProxy(context) { - context.instantiateObject = instantiateProxy - return mapProxy(context, '_root', []) -} -module.exports = { rootObjectProxy } +const deflateResetKeep = (strm) => { -},{"../src/common":87,"./constants":56,"./table":63,"./text":64}],63:[function(require,module,exports){ -const { OBJECT_ID, CONFLICTS } = require('./constants') -const { isObject, copyObject } = require('../src/common') + if (deflateStateCheck(strm)) { + return err(strm, Z_STREAM_ERROR); + } -function compareRows(properties, row1, row2) { - for (let prop of properties) { - if (row1[prop] === row2[prop]) continue + strm.total_in = strm.total_out = 0; + strm.data_type = Z_UNKNOWN; - if (typeof row1[prop] === 'number' && typeof row2[prop] === 'number') { - return row1[prop] - row2[prop] - } else { - const prop1 = '' + row1[prop], prop2 = '' + row2[prop] - if (prop1 === prop2) continue - if (prop1 < prop2) return -1; else return +1 - } + const s = strm.state; + s.pending = 0; + s.pending_out = 0; + + if (s.wrap < 0) { + s.wrap = -s.wrap; + /* was made negative by deflate(..., Z_FINISH); */ } - return 0 -} + s.status = +//#ifdef GZIP + s.wrap === 2 ? GZIP_STATE : +//#endif + s.wrap ? INIT_STATE : BUSY_STATE; + strm.adler = (s.wrap === 2) ? + 0 // crc32(0, Z_NULL, 0) + : + 1; // adler32(0, Z_NULL, 0) + s.last_flush = -2; + _tr_init(s); + return Z_OK; +}; -/** - * A relational-style unordered collection of records (rows). Each row is an - * object that maps column names to values. The set of rows is represented by - * a map from UUID to row object. - */ -class Table { - /** - * This constructor is used by application code when creating a new Table - * object within a change callback. - */ - constructor() { - this.entries = Object.freeze({}) - this.opIds = Object.freeze({}) - Object.freeze(this) - } +const deflateReset = (strm) => { - /** - * Looks up a row in the table by its unique ID. - */ - byId(id) { - return this.entries[id] + const ret = deflateResetKeep(strm); + if (ret === Z_OK) { + lm_init(strm.state); } + return ret; +}; - /** - * Returns an array containing the unique IDs of all rows in the table, in no - * particular order. - */ - get ids() { - return Object.keys(this.entries).filter(key => { - const entry = this.entries[key] - return isObject(entry) && entry.id === key - }) - } - /** - * Returns the number of rows in the table. - */ - get count() { - return this.ids.length - } +const deflateSetHeader = (strm, head) => { - /** - * Returns an array containing all of the rows in the table, in no particular - * order. - */ - get rows() { - return this.ids.map(id => this.byId(id)) + if (deflateStateCheck(strm) || strm.state.wrap !== 2) { + return Z_STREAM_ERROR; } + strm.state.gzhead = head; + return Z_OK; +}; - /** - * The standard JavaScript `filter()` method, which passes each row to the - * callback function and returns all rows for which the it returns true. - */ - filter(callback, thisArg) { - return this.rows.filter(callback, thisArg) - } - /** - * The standard JavaScript `find()` method, which passes each row to the - * callback function and returns the first row for which it returns true. - */ - find(callback, thisArg) { - return this.rows.find(callback, thisArg) - } +const deflateInit2 = (strm, level, method, windowBits, memLevel, strategy) => { - /** - * The standard JavaScript `map()` method, which passes each row to the - * callback function and returns a list of its return values. - */ - map(callback, thisArg) { - return this.rows.map(callback, thisArg) + if (!strm) { // === Z_NULL + return Z_STREAM_ERROR; } + let wrap = 1; - /** - * Returns the list of rows, sorted by one of the following: - * - If a function argument is given, it compares rows as per - * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#Description - * - If a string argument is given, it is interpreted as a column name and - * rows are sorted according to that column. - * - If an array of strings is given, it is interpreted as a list of column - * names, and rows are sorted lexicographically by those columns. - * - If no argument is given, it sorts by row ID by default. - */ - sort(arg) { - if (typeof arg === 'function') { - return this.rows.sort(arg) - } else if (typeof arg === 'string') { - return this.rows.sort((row1, row2) => compareRows([arg], row1, row2)) - } else if (Array.isArray(arg)) { - return this.rows.sort((row1, row2) => compareRows(arg, row1, row2)) - } else if (arg === undefined) { - return this.rows.sort((row1, row2) => compareRows(['id'], row1, row2)) - } else { - throw new TypeError(`Unsupported sorting argument: ${arg}`) - } + if (level === Z_DEFAULT_COMPRESSION) { + level = 6; } - /** - * When iterating over a table, you get all rows in the table, in no - * particular order. - */ - [Symbol.iterator] () { - let rows = this.rows, index = -1 - return { - next () { - index += 1 - if (index < rows.length) { - return {done: false, value: rows[index]} - } else { - return {done: true} - } - } - } + if (windowBits < 0) { /* suppress zlib wrapper */ + wrap = 0; + windowBits = -windowBits; } - /** - * Returns a shallow clone of this object. This clone is used while applying - * a patch to the table, and `freeze()` is called on it when we have finished - * applying the patch. - */ - _clone() { - if (!this[OBJECT_ID]) { - throw new RangeError('clone() requires the objectId to be set') - } - return instantiateTable(this[OBJECT_ID], copyObject(this.entries), copyObject(this.opIds)) + else if (windowBits > 15) { + wrap = 2; /* write gzip wrapper instead */ + windowBits -= 16; } - /** - * Sets the entry with key `id` to `value`. `opId` is the ID of the operation - * performing this assignment. This method is for internal use only; it is - * not part of the public API of Automerge.Table. - */ - _set(id, value, opId) { - if (Object.isFrozen(this.entries)) { - throw new Error('A table can only be modified in a change function') - } - if (isObject(value) && !Array.isArray(value)) { - Object.defineProperty(value, 'id', {value: id, enumerable: true}) - } - this.entries[id] = value - this.opIds[id] = opId + + if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method !== Z_DEFLATED || + windowBits < 8 || windowBits > 15 || level < 0 || level > 9 || + strategy < 0 || strategy > Z_FIXED || (windowBits === 8 && wrap !== 1)) { + return err(strm, Z_STREAM_ERROR); } - /** - * Removes the row with unique ID `id` from the table. - */ - remove(id) { - if (Object.isFrozen(this.entries)) { - throw new Error('A table can only be modified in a change function') - } - delete this.entries[id] - delete this.opIds[id] + + if (windowBits === 8) { + windowBits = 9; } + /* until 256-byte window bug fixed */ - /** - * Makes this object immutable. This is called after a change has been made. + const s = new DeflateState(); + + strm.state = s; + s.strm = strm; + s.status = INIT_STATE; /* to pass state test in deflateReset() */ + + s.wrap = wrap; + s.gzhead = null; + s.w_bits = windowBits; + s.w_size = 1 << s.w_bits; + s.w_mask = s.w_size - 1; + + s.hash_bits = memLevel + 7; + s.hash_size = 1 << s.hash_bits; + s.hash_mask = s.hash_size - 1; + s.hash_shift = ~~((s.hash_bits + MIN_MATCH - 1) / MIN_MATCH); + + s.window = new Uint8Array(s.w_size * 2); + s.head = new Uint16Array(s.hash_size); + s.prev = new Uint16Array(s.w_size); + + // Don't need mem init magic for JS. + //s.high_water = 0; /* nothing written to s->window yet */ + + s.lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */ + + /* We overlay pending_buf and sym_buf. This works since the average size + * for length/distance pairs over any compressed block is assured to be 31 + * bits or less. + * + * Analysis: The longest fixed codes are a length code of 8 bits plus 5 + * extra bits, for lengths 131 to 257. The longest fixed distance codes are + * 5 bits plus 13 extra bits, for distances 16385 to 32768. The longest + * possible fixed-codes length/distance pair is then 31 bits total. + * + * sym_buf starts one-fourth of the way into pending_buf. So there are + * three bytes in sym_buf for every four bytes in pending_buf. Each symbol + * in sym_buf is three bytes -- two for the distance and one for the + * literal/length. As each symbol is consumed, the pointer to the next + * sym_buf value to read moves forward three bytes. From that symbol, up to + * 31 bits are written to pending_buf. The closest the written pending_buf + * bits gets to the next sym_buf symbol to read is just before the last + * code is written. At that time, 31*(n-2) bits have been written, just + * after 24*(n-2) bits have been consumed from sym_buf. sym_buf starts at + * 8*n bits into pending_buf. (Note that the symbol buffer fills when n-1 + * symbols are written.) The closest the writing gets to what is unread is + * then n+14 bits. Here n is lit_bufsize, which is 16384 by default, and + * can range from 128 to 32768. + * + * Therefore, at a minimum, there are 142 bits of space between what is + * written and what is read in the overlain buffers, so the symbols cannot + * be overwritten by the compressed data. That space is actually 139 bits, + * due to the three-bit fixed-code block header. + * + * That covers the case where either Z_FIXED is specified, forcing fixed + * codes, or when the use of fixed codes is chosen, because that choice + * results in a smaller compressed block than dynamic codes. That latter + * condition then assures that the above analysis also covers all dynamic + * blocks. A dynamic-code block will only be chosen to be emitted if it has + * fewer bits than a fixed-code block would for the same set of symbols. + * Therefore its average symbol length is assured to be less than 31. So + * the compressed data for a dynamic block also cannot overwrite the + * symbols from which it is being constructed. */ - _freeze() { - Object.freeze(this.entries) - Object.freeze(this.opIds) - Object.freeze(this) - } - /** - * Returns a writeable instance of this table. This instance is returned when - * the table is accessed within a change callback. `context` is the proxy - * context that keeps track of the mutations. + s.pending_buf_size = s.lit_bufsize * 4; + s.pending_buf = new Uint8Array(s.pending_buf_size); + + // It is offset from `s.pending_buf` (size is `s.lit_bufsize * 2`) + //s->sym_buf = s->pending_buf + s->lit_bufsize; + s.sym_buf = s.lit_bufsize; + + //s->sym_end = (s->lit_bufsize - 1) * 3; + s.sym_end = (s.lit_bufsize - 1) * 3; + /* We avoid equality with lit_bufsize*3 because of wraparound at 64K + * on 16 bit machines and because stored blocks are restricted to + * 64K-1 bytes. */ - getWriteable(context, path) { - if (!this[OBJECT_ID]) { - throw new RangeError('getWriteable() requires the objectId to be set') - } - const instance = Object.create(WriteableTable.prototype) - instance[OBJECT_ID] = this[OBJECT_ID] - instance.context = context - instance.entries = this.entries - instance.opIds = this.opIds - instance.path = path - return instance + s.level = level; + s.strategy = strategy; + s.method = method; + + return deflateReset(strm); +}; + +const deflateInit = (strm, level) => { + + return deflateInit2(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY); +}; + + +/* ========================================================================= */ +const deflate = (strm, flush) => { + + if (deflateStateCheck(strm) || flush > Z_BLOCK || flush < 0) { + return strm ? err(strm, Z_STREAM_ERROR) : Z_STREAM_ERROR; } - /** - * Returns an object containing the table entries, indexed by objectID, - * for serializing an Automerge document to JSON. - */ - toJSON() { - const rows = {} - for (let id of this.ids) rows[id] = this.byId(id) - return rows + const s = strm.state; + + if (!strm.output || + (strm.avail_in !== 0 && !strm.input) || + (s.status === FINISH_STATE && flush !== Z_FINISH)) { + return err(strm, (strm.avail_out === 0) ? Z_BUF_ERROR : Z_STREAM_ERROR); } -} -/** - * An instance of this class is used when a table is accessed within a change - * callback. - */ -class WriteableTable extends Table { - /** - * Returns a proxied version of the row with ID `id`. This row object can be - * modified within a change callback. - */ - byId(id) { - if (isObject(this.entries[id]) && this.entries[id].id === id) { - const objectId = this.entries[id][OBJECT_ID] - const path = this.path.concat([{key: id, objectId}]) - return this.context.instantiateObject(path, objectId, ['id']) + const old_flush = s.last_flush; + s.last_flush = flush; + + /* Flush as much pending output as possible */ + if (s.pending !== 0) { + flush_pending(strm); + if (strm.avail_out === 0) { + /* Since avail_out is 0, deflate will be called again with + * more output space, but possibly with both pending and + * avail_in equal to zero. There won't be anything to do, + * but this is not an error situation so make sure we + * return OK instead of BUF_ERROR at next call of deflate: + */ + s.last_flush = -1; + return Z_OK; } + + /* Make sure there is something to do and avoid duplicate consecutive + * flushes. For repeated and useless calls with Z_FINISH, we keep + * returning Z_STREAM_END instead of Z_BUF_ERROR. + */ + } else if (strm.avail_in === 0 && rank(flush) <= rank(old_flush) && + flush !== Z_FINISH) { + return err(strm, Z_BUF_ERROR); } - /** - * Adds a new row to the table. The row is given as a map from - * column name to value. Returns the objectId of the new row. - */ - add(row) { - return this.context.addTableRow(this.path, row) + /* User must not provide more input after the first FINISH: */ + if (s.status === FINISH_STATE && strm.avail_in !== 0) { + return err(strm, Z_BUF_ERROR); } - /** - * Removes the row with ID `id` from the table. Throws an exception if the row - * does not exist in the table. - */ - remove(id) { - if (isObject(this.entries[id]) && this.entries[id].id === id) { - this.context.deleteTableRow(this.path, id, this.opIds[id]) + /* Write the header */ + if (s.status === INIT_STATE && s.wrap === 0) { + s.status = BUSY_STATE; + } + if (s.status === INIT_STATE) { + /* zlib header */ + let header = (Z_DEFLATED + ((s.w_bits - 8) << 4)) << 8; + let level_flags = -1; + + if (s.strategy >= Z_HUFFMAN_ONLY || s.level < 2) { + level_flags = 0; + } else if (s.level < 6) { + level_flags = 1; + } else if (s.level === 6) { + level_flags = 2; } else { - throw new RangeError(`There is no row with ID ${id} in this table`) + level_flags = 3; } - } -} - -/** - * This function is used to instantiate a Table object in the context of - * applying a patch (see apply_patch.js). - */ -function instantiateTable(objectId, entries, opIds) { - const instance = Object.create(Table.prototype) - if (!objectId) { - throw new RangeError('instantiateTable requires an objectId to be given') - } - instance[OBJECT_ID] = objectId - instance[CONFLICTS] = Object.freeze({}) - instance.entries = entries || {} - instance.opIds = opIds || {} - return instance -} - -module.exports = { Table, instantiateTable } + header |= (level_flags << 6); + if (s.strstart !== 0) { header |= PRESET_DICT; } + header += 31 - (header % 31); -},{"../src/common":87,"./constants":56}],64:[function(require,module,exports){ -const { OBJECT_ID } = require('./constants') -const { isObject } = require('../src/common') + putShortMSB(s, header); -class Text { - constructor (text) { - if (typeof text === 'string') { - const elems = [...text].map(value => ({value})) - return instantiateText(undefined, elems) // eslint-disable-line - } else if (Array.isArray(text)) { - const elems = text.map(value => ({value})) - return instantiateText(undefined, elems) // eslint-disable-line - } else if (text === undefined) { - return instantiateText(undefined, []) // eslint-disable-line - } else { - throw new TypeError(`Unsupported initial value for Text: ${text}`) + /* Save the adler32 of the preset dictionary: */ + if (s.strstart !== 0) { + putShortMSB(s, strm.adler >>> 16); + putShortMSB(s, strm.adler & 0xffff); } - } + strm.adler = 1; // adler32(0L, Z_NULL, 0); + s.status = BUSY_STATE; - get length () { - return this.elems.length + /* Compression must start with an empty pending buffer */ + flush_pending(strm); + if (s.pending !== 0) { + s.last_flush = -1; + return Z_OK; + } } +//#ifdef GZIP + if (s.status === GZIP_STATE) { + /* gzip header */ + strm.adler = 0; //crc32(0L, Z_NULL, 0); + put_byte(s, 31); + put_byte(s, 139); + put_byte(s, 8); + if (!s.gzhead) { // s->gzhead == Z_NULL + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, s.level === 9 ? 2 : + (s.strategy >= Z_HUFFMAN_ONLY || s.level < 2 ? + 4 : 0)); + put_byte(s, OS_CODE); + s.status = BUSY_STATE; - get (index) { - const value = this.elems[index].value - if (this.context && isObject(value)) { - const objectId = value[OBJECT_ID] - const path = this.path.concat([{key: index, objectId}]) - return this.context.instantiateObject(path, objectId) - } else { - return value + /* Compression must start with an empty pending buffer */ + flush_pending(strm); + if (s.pending !== 0) { + s.last_flush = -1; + return Z_OK; + } + } + else { + put_byte(s, (s.gzhead.text ? 1 : 0) + + (s.gzhead.hcrc ? 2 : 0) + + (!s.gzhead.extra ? 0 : 4) + + (!s.gzhead.name ? 0 : 8) + + (!s.gzhead.comment ? 0 : 16) + ); + put_byte(s, s.gzhead.time & 0xff); + put_byte(s, (s.gzhead.time >> 8) & 0xff); + put_byte(s, (s.gzhead.time >> 16) & 0xff); + put_byte(s, (s.gzhead.time >> 24) & 0xff); + put_byte(s, s.level === 9 ? 2 : + (s.strategy >= Z_HUFFMAN_ONLY || s.level < 2 ? + 4 : 0)); + put_byte(s, s.gzhead.os & 0xff); + if (s.gzhead.extra && s.gzhead.extra.length) { + put_byte(s, s.gzhead.extra.length & 0xff); + put_byte(s, (s.gzhead.extra.length >> 8) & 0xff); + } + if (s.gzhead.hcrc) { + strm.adler = crc32(strm.adler, s.pending_buf, s.pending, 0); + } + s.gzindex = 0; + s.status = EXTRA_STATE; } } - - getElemId (index) { - return this.elems[index].elemId + if (s.status === EXTRA_STATE) { + if (s.gzhead.extra/* != Z_NULL*/) { + let beg = s.pending; /* start of bytes to update crc */ + let left = (s.gzhead.extra.length & 0xffff) - s.gzindex; + while (s.pending + left > s.pending_buf_size) { + let copy = s.pending_buf_size - s.pending; + // zmemcpy(s.pending_buf + s.pending, + // s.gzhead.extra + s.gzindex, copy); + s.pending_buf.set(s.gzhead.extra.subarray(s.gzindex, s.gzindex + copy), s.pending); + s.pending = s.pending_buf_size; + //--- HCRC_UPDATE(beg) ---// + if (s.gzhead.hcrc && s.pending > beg) { + strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); + } + //---// + s.gzindex += copy; + flush_pending(strm); + if (s.pending !== 0) { + s.last_flush = -1; + return Z_OK; + } + beg = 0; + left -= copy; + } + // JS specific: s.gzhead.extra may be TypedArray or Array for backward compatibility + // TypedArray.slice and TypedArray.from don't exist in IE10-IE11 + let gzhead_extra = new Uint8Array(s.gzhead.extra); + // zmemcpy(s->pending_buf + s->pending, + // s->gzhead->extra + s->gzindex, left); + s.pending_buf.set(gzhead_extra.subarray(s.gzindex, s.gzindex + left), s.pending); + s.pending += left; + //--- HCRC_UPDATE(beg) ---// + if (s.gzhead.hcrc && s.pending > beg) { + strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); + } + //---// + s.gzindex = 0; + } + s.status = NAME_STATE; } - - /** - * Iterates over the text elements character by character, including any - * inline objects. - */ - [Symbol.iterator] () { - let elems = this.elems, index = -1 - return { - next () { - index += 1 - if (index < elems.length) { - return {done: false, value: elems[index].value} + if (s.status === NAME_STATE) { + if (s.gzhead.name/* != Z_NULL*/) { + let beg = s.pending; /* start of bytes to update crc */ + let val; + do { + if (s.pending === s.pending_buf_size) { + //--- HCRC_UPDATE(beg) ---// + if (s.gzhead.hcrc && s.pending > beg) { + strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); + } + //---// + flush_pending(strm); + if (s.pending !== 0) { + s.last_flush = -1; + return Z_OK; + } + beg = 0; + } + // JS specific: little magic to add zero terminator to end of string + if (s.gzindex < s.gzhead.name.length) { + val = s.gzhead.name.charCodeAt(s.gzindex++) & 0xff; } else { - return {done: true} + val = 0; } + put_byte(s, val); + } while (val !== 0); + //--- HCRC_UPDATE(beg) ---// + if (s.gzhead.hcrc && s.pending > beg) { + strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); } + //---// + s.gzindex = 0; } + s.status = COMMENT_STATE; } - - /** - * Returns the content of the Text object as a simple string, ignoring any - * non-character elements. - */ - toString() { - // Concatting to a string is faster than creating an array and then - // .join()ing for small (<100KB) arrays. - // https://jsperf.com/join-vs-loop-w-type-test - let str = '' - for (const elem of this.elems) { - if (typeof elem.value === 'string') str += elem.value + if (s.status === COMMENT_STATE) { + if (s.gzhead.comment/* != Z_NULL*/) { + let beg = s.pending; /* start of bytes to update crc */ + let val; + do { + if (s.pending === s.pending_buf_size) { + //--- HCRC_UPDATE(beg) ---// + if (s.gzhead.hcrc && s.pending > beg) { + strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); + } + //---// + flush_pending(strm); + if (s.pending !== 0) { + s.last_flush = -1; + return Z_OK; + } + beg = 0; + } + // JS specific: little magic to add zero terminator to end of string + if (s.gzindex < s.gzhead.comment.length) { + val = s.gzhead.comment.charCodeAt(s.gzindex++) & 0xff; + } else { + val = 0; + } + put_byte(s, val); + } while (val !== 0); + //--- HCRC_UPDATE(beg) ---// + if (s.gzhead.hcrc && s.pending > beg) { + strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); + } + //---// } - return str + s.status = HCRC_STATE; } - - /** - * Returns the content of the Text object as a sequence of strings, - * interleaved with non-character elements. - * - * For example, the value ['a', 'b', {x: 3}, 'c', 'd'] has spans: - * => ['ab', {x: 3}, 'cd'] - */ - toSpans() { - let spans = [] - let chars = '' - for (const elem of this.elems) { - if (typeof elem.value === 'string') { - chars += elem.value - } else { - if (chars.length > 0) { - spans.push(chars) - chars = '' + if (s.status === HCRC_STATE) { + if (s.gzhead.hcrc) { + if (s.pending + 2 > s.pending_buf_size) { + flush_pending(strm); + if (s.pending !== 0) { + s.last_flush = -1; + return Z_OK; } - spans.push(elem.value) } + put_byte(s, strm.adler & 0xff); + put_byte(s, (strm.adler >> 8) & 0xff); + strm.adler = 0; //crc32(0L, Z_NULL, 0); } - if (chars.length > 0) { - spans.push(chars) + s.status = BUSY_STATE; + + /* Compression must start with an empty pending buffer */ + flush_pending(strm); + if (s.pending !== 0) { + s.last_flush = -1; + return Z_OK; } - return spans } +//#endif - /** - * Returns the content of the Text object as a simple string, so that the - * JSON serialization of an Automerge document represents text nicely. + /* Start a new block or continue the current one. */ - toJSON() { - return this.toString() - } + if (strm.avail_in !== 0 || s.lookahead !== 0 || + (flush !== Z_NO_FLUSH && s.status !== FINISH_STATE)) { + let bstate = s.level === 0 ? deflate_stored(s, flush) : + s.strategy === Z_HUFFMAN_ONLY ? deflate_huff(s, flush) : + s.strategy === Z_RLE ? deflate_rle(s, flush) : + configuration_table[s.level].func(s, flush); - /** - * Returns a writeable instance of this object. This instance is returned when - * the text object is accessed within a change callback. `context` is the - * proxy context that keeps track of the mutations. - */ - getWriteable(context, path) { - if (!this[OBJECT_ID]) { - throw new RangeError('getWriteable() requires the objectId to be set') + if (bstate === BS_FINISH_STARTED || bstate === BS_FINISH_DONE) { + s.status = FINISH_STATE; + } + if (bstate === BS_NEED_MORE || bstate === BS_FINISH_STARTED) { + if (strm.avail_out === 0) { + s.last_flush = -1; + /* avoid BUF_ERROR next call, see above */ + } + return Z_OK; + /* If flush != Z_NO_FLUSH && avail_out == 0, the next call + * of deflate should use the same flush parameter to make sure + * that the flush is complete. So we don't have to output an + * empty block here, this will be done at next call. This also + * ensures that for a very small output buffer, we emit at most + * one empty block. + */ } + if (bstate === BS_BLOCK_DONE) { + if (flush === Z_PARTIAL_FLUSH) { + _tr_align(s); + } + else if (flush !== Z_BLOCK) { /* FULL_FLUSH or SYNC_FLUSH */ - const instance = instantiateText(this[OBJECT_ID], this.elems) - instance.context = context - instance.path = path - return instance - } + _tr_stored_block(s, 0, 0, false); + /* For a full flush, this empty block will be recognized + * as a special marker by inflate_sync(). + */ + if (flush === Z_FULL_FLUSH) { + /*** CLEAR_HASH(s); ***/ /* forget history */ + zero(s.head); // Fill with NIL (= 0); - /** - * Updates the list item at position `index` to a new value `value`. - */ - set (index, value) { - if (this.context) { - this.context.setListIndex(this.path, index, value) - } else if (!this[OBJECT_ID]) { - this.elems[index].value = value - } else { - throw new TypeError('Automerge.Text object cannot be modified outside of a change block') + if (s.lookahead === 0) { + s.strstart = 0; + s.block_start = 0; + s.insert = 0; + } + } + } + flush_pending(strm); + if (strm.avail_out === 0) { + s.last_flush = -1; /* avoid BUF_ERROR at next call, see above */ + return Z_OK; + } } - return this } - /** - * Inserts new list items `values` starting at position `index`. - */ - insertAt(index, ...values) { - if (this.context) { - this.context.splice(this.path, index, 0, values) - } else if (!this[OBJECT_ID]) { - this.elems.splice(index, 0, ...values.map(value => ({value}))) - } else { - throw new TypeError('Automerge.Text object cannot be modified outside of a change block') - } - return this + if (flush !== Z_FINISH) { return Z_OK; } + if (s.wrap <= 0) { return Z_STREAM_END; } + + /* Write the trailer */ + if (s.wrap === 2) { + put_byte(s, strm.adler & 0xff); + put_byte(s, (strm.adler >> 8) & 0xff); + put_byte(s, (strm.adler >> 16) & 0xff); + put_byte(s, (strm.adler >> 24) & 0xff); + put_byte(s, strm.total_in & 0xff); + put_byte(s, (strm.total_in >> 8) & 0xff); + put_byte(s, (strm.total_in >> 16) & 0xff); + put_byte(s, (strm.total_in >> 24) & 0xff); + } + else + { + putShortMSB(s, strm.adler >>> 16); + putShortMSB(s, strm.adler & 0xffff); } - /** - * Deletes `numDelete` list items starting at position `index`. - * if `numDelete` is not given, one item is deleted. + flush_pending(strm); + /* If avail_out is zero, the application will call deflate again + * to flush the rest. */ - deleteAt(index, numDelete = 1) { - if (this.context) { - this.context.splice(this.path, index, numDelete, []) - } else if (!this[OBJECT_ID]) { - this.elems.splice(index, numDelete) - } else { - throw new TypeError('Automerge.Text object cannot be modified outside of a change block') - } - return this - } -} + if (s.wrap > 0) { s.wrap = -s.wrap; } + /* write the trailer only once! */ + return s.pending !== 0 ? Z_OK : Z_STREAM_END; +}; -// Read-only methods that can delegate to the JavaScript built-in array -for (let method of ['concat', 'every', 'filter', 'find', 'findIndex', 'forEach', 'includes', - 'indexOf', 'join', 'lastIndexOf', 'map', 'reduce', 'reduceRight', - 'slice', 'some', 'toLocaleString']) { - Text.prototype[method] = function (...args) { - const array = [...this] - return array[method](...args) - } -} -function instantiateText(objectId, elems) { - const instance = Object.create(Text.prototype) - instance[OBJECT_ID] = objectId - instance.elems = elems - return instance -} +const deflateEnd = (strm) => { -module.exports = { Text, instantiateText } + if (deflateStateCheck(strm)) { + return Z_STREAM_ERROR; + } -},{"../src/common":87,"./constants":56}],65:[function(require,module,exports){ -// Top level file is just a mixin of submodules & constants -'use strict'; + const status = strm.state.status; -const { Deflate, deflate, deflateRaw, gzip } = require('./lib/deflate'); + strm.state = null; -const { Inflate, inflate, inflateRaw, ungzip } = require('./lib/inflate'); + return status === BUSY_STATE ? err(strm, Z_DATA_ERROR) : Z_OK; +}; -const constants = require('./lib/zlib/constants'); -module.exports.Deflate = Deflate; -module.exports.deflate = deflate; -module.exports.deflateRaw = deflateRaw; -module.exports.gzip = gzip; -module.exports.Inflate = Inflate; -module.exports.inflate = inflate; -module.exports.inflateRaw = inflateRaw; -module.exports.ungzip = ungzip; -module.exports.constants = constants; +/* ========================================================================= + * Initializes the compression dictionary from the given byte + * sequence without producing any compressed output. + */ +const deflateSetDictionary = (strm, dictionary) => { -},{"./lib/deflate":66,"./lib/inflate":67,"./lib/zlib/constants":71}],66:[function(require,module,exports){ -'use strict'; + let dictLength = dictionary.length; + if (deflateStateCheck(strm)) { + return Z_STREAM_ERROR; + } -const zlib_deflate = require('./zlib/deflate'); -const utils = require('./utils/common'); -const strings = require('./utils/strings'); -const msg = require('./zlib/messages'); -const ZStream = require('./zlib/zstream'); + const s = strm.state; + const wrap = s.wrap; -const toString = Object.prototype.toString; + if (wrap === 2 || (wrap === 1 && s.status !== INIT_STATE) || s.lookahead) { + return Z_STREAM_ERROR; + } -/* Public constants ==========================================================*/ -/* ===========================================================================*/ + /* when using zlib wrappers, compute Adler-32 for provided dictionary */ + if (wrap === 1) { + /* adler32(strm->adler, dictionary, dictLength); */ + strm.adler = adler32(strm.adler, dictionary, dictLength, 0); + } -const { - Z_NO_FLUSH, Z_SYNC_FLUSH, Z_FULL_FLUSH, Z_FINISH, - Z_OK, Z_STREAM_END, - Z_DEFAULT_COMPRESSION, - Z_DEFAULT_STRATEGY, - Z_DEFLATED -} = require('./zlib/constants'); + s.wrap = 0; /* avoid computing Adler-32 in read_buf */ -/* ===========================================================================*/ + /* if dictionary would fill window, just replace the history */ + if (dictLength >= s.w_size) { + if (wrap === 0) { /* already empty otherwise */ + /*** CLEAR_HASH(s); ***/ + zero(s.head); // Fill with NIL (= 0); + s.strstart = 0; + s.block_start = 0; + s.insert = 0; + } + /* use the tail */ + // dictionary = dictionary.slice(dictLength - s.w_size); + let tmpDict = new Uint8Array(s.w_size); + tmpDict.set(dictionary.subarray(dictLength - s.w_size, dictLength), 0); + dictionary = tmpDict; + dictLength = s.w_size; + } + /* insert dictionary into window and hash */ + const avail = strm.avail_in; + const next = strm.next_in; + const input = strm.input; + strm.avail_in = dictLength; + strm.next_in = 0; + strm.input = dictionary; + fill_window(s); + while (s.lookahead >= MIN_MATCH) { + let str = s.strstart; + let n = s.lookahead - (MIN_MATCH - 1); + do { + /* UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); */ + s.ins_h = HASH(s, s.ins_h, s.window[str + MIN_MATCH - 1]); + s.prev[str & s.w_mask] = s.head[s.ins_h]; -/** - * class Deflate - * - * Generic JS-style wrapper for zlib calls. If you don't need - * streaming behaviour - use more simple functions: [[deflate]], - * [[deflateRaw]] and [[gzip]]. - **/ + s.head[s.ins_h] = str; + str++; + } while (--n); + s.strstart = str; + s.lookahead = MIN_MATCH - 1; + fill_window(s); + } + s.strstart += s.lookahead; + s.block_start = s.strstart; + s.insert = s.lookahead; + s.lookahead = 0; + s.match_length = s.prev_length = MIN_MATCH - 1; + s.match_available = 0; + strm.next_in = next; + strm.input = input; + strm.avail_in = avail; + s.wrap = wrap; + return Z_OK; +}; -/* internal - * Deflate.chunks -> Array - * - * Chunks of output data, if [[Deflate#onData]] not overridden. - **/ -/** - * Deflate.result -> Uint8Array - * - * Compressed result, generated by default [[Deflate#onData]] - * and [[Deflate#onEnd]] handlers. Filled after you push last chunk - * (call [[Deflate#push]] with `Z_FINISH` / `true` param). - **/ +module.exports.deflateInit = deflateInit; +module.exports.deflateInit2 = deflateInit2; +module.exports.deflateReset = deflateReset; +module.exports.deflateResetKeep = deflateResetKeep; +module.exports.deflateSetHeader = deflateSetHeader; +module.exports.deflate = deflate; +module.exports.deflateEnd = deflateEnd; +module.exports.deflateSetDictionary = deflateSetDictionary; +module.exports.deflateInfo = 'pako deflate (from Nodeca project)'; -/** - * Deflate.err -> Number - * - * Error code after deflate finished. 0 (Z_OK) on success. - * You will not need it in real life, because deflate errors - * are possible only on wrong options or bad `onData` / `onEnd` - * custom handlers. - **/ +/* Not implemented +module.exports.deflateBound = deflateBound; +module.exports.deflateCopy = deflateCopy; +module.exports.deflateGetDictionary = deflateGetDictionary; +module.exports.deflateParams = deflateParams; +module.exports.deflatePending = deflatePending; +module.exports.deflatePrime = deflatePrime; +module.exports.deflateTune = deflateTune; +*/ -/** - * Deflate.msg -> String - * - * Error message, if [[Deflate.err]] != 0 - **/ +},{"./adler32":70,"./constants":71,"./crc32":72,"./messages":78,"./trees":79}],74:[function(require,module,exports){ +'use strict'; +// (C) 1995-2013 Jean-loup Gailly and Mark Adler +// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. -/** - * new Deflate(options) - * - options (Object): zlib deflate options. - * - * Creates new deflator instance with specified params. Throws exception - * on bad params. Supported options: - * - * - `level` - * - `windowBits` - * - `memLevel` - * - `strategy` - * - `dictionary` - * - * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced) - * for more information on these. - * - * Additional options, for internal needs: - * - * - `chunkSize` - size of generated data chunks (16K by default) - * - `raw` (Boolean) - do raw deflate - * - `gzip` (Boolean) - create gzip wrapper - * - `header` (Object) - custom header for gzip - * - `text` (Boolean) - true if compressed data believed to be text - * - `time` (Number) - modification time, unix timestamp - * - `os` (Number) - operation system code - * - `extra` (Array) - array of bytes with extra data (max 65536) - * - `name` (String) - file name (binary string) - * - `comment` (String) - comment (binary string) - * - `hcrc` (Boolean) - true if header crc should be added - * - * ##### Example: - * - * ```javascript - * const pako = require('pako') - * , chunk1 = new Uint8Array([1,2,3,4,5,6,7,8,9]) - * , chunk2 = new Uint8Array([10,11,12,13,14,15,16,17,18,19]); - * - * const deflate = new pako.Deflate({ level: 3}); - * - * deflate.push(chunk1, false); - * deflate.push(chunk2, true); // true -> last chunk - * - * if (deflate.err) { throw new Error(deflate.err); } - * - * console.log(deflate.result); - * ``` - **/ -function Deflate(options) { - this.options = utils.assign({ - level: Z_DEFAULT_COMPRESSION, - method: Z_DEFLATED, - chunkSize: 16384, - windowBits: 15, - memLevel: 8, - strategy: Z_DEFAULT_STRATEGY - }, options || {}); +function GZheader() { + /* true if compressed data believed to be text */ + this.text = 0; + /* modification time */ + this.time = 0; + /* extra flags (not used when writing a gzip file) */ + this.xflags = 0; + /* operating system */ + this.os = 0; + /* pointer to extra field or Z_NULL if none */ + this.extra = null; + /* extra field length (valid if extra != Z_NULL) */ + this.extra_len = 0; // Actually, we don't need it in JS, + // but leave for few code modifications - let opt = this.options; + // + // Setup limits is not necessary because in js we should not preallocate memory + // for inflate use constant limit in 65536 bytes + // - if (opt.raw && (opt.windowBits > 0)) { - opt.windowBits = -opt.windowBits; - } + /* space at extra (only when reading header) */ + // this.extra_max = 0; + /* pointer to zero-terminated file name or Z_NULL */ + this.name = ''; + /* space at name (only when reading header) */ + // this.name_max = 0; + /* pointer to zero-terminated comment or Z_NULL */ + this.comment = ''; + /* space at comment (only when reading header) */ + // this.comm_max = 0; + /* true if there was or will be a header crc */ + this.hcrc = 0; + /* true when done reading gzip header (not used when writing a gzip file) */ + this.done = false; +} - else if (opt.gzip && (opt.windowBits > 0) && (opt.windowBits < 16)) { - opt.windowBits += 16; - } +module.exports = GZheader; - this.err = 0; // error code, if happens (0 = Z_OK) - this.msg = ''; // error message - this.ended = false; // used to avoid multiple onEnd() calls - this.chunks = []; // chunks of compressed data +},{}],75:[function(require,module,exports){ +'use strict'; - this.strm = new ZStream(); - this.strm.avail_out = 0; +// (C) 1995-2013 Jean-loup Gailly and Mark Adler +// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. - let status = zlib_deflate.deflateInit2( - this.strm, - opt.level, - opt.method, - opt.windowBits, - opt.memLevel, - opt.strategy - ); +// See state defs from inflate.js +const BAD = 16209; /* got a data error -- remain here until reset */ +const TYPE = 16191; /* i: waiting for type bits, including last-flag bit */ - if (status !== Z_OK) { - throw new Error(msg[status]); - } +/* + Decode literal, length, and distance codes and write out the resulting + literal and match bytes until either not enough input or output is + available, an end-of-block is encountered, or a data error is encountered. + When large enough input and output buffers are supplied to inflate(), for + example, a 16K input buffer and a 64K output buffer, more than 95% of the + inflate execution time is spent in this routine. - if (opt.header) { - zlib_deflate.deflateSetHeader(this.strm, opt.header); - } + Entry assumptions: - if (opt.dictionary) { - let dict; - // Convert data if needed - if (typeof opt.dictionary === 'string') { - // If we need to compress text, change encoding to utf8. - dict = strings.string2buf(opt.dictionary); - } else if (toString.call(opt.dictionary) === '[object ArrayBuffer]') { - dict = new Uint8Array(opt.dictionary); - } else { - dict = opt.dictionary; - } + state.mode === LEN + strm.avail_in >= 6 + strm.avail_out >= 258 + start >= strm.avail_out + state.bits < 8 - status = zlib_deflate.deflateSetDictionary(this.strm, dict); + On return, state.mode is one of: - if (status !== Z_OK) { - throw new Error(msg[status]); - } + LEN -- ran out of enough output space or enough available input + TYPE -- reached end of block code, inflate() to interpret next block + BAD -- error in block data - this._dict_set = true; - } -} + Notes: -/** - * Deflate#push(data[, flush_mode]) -> Boolean - * - data (Uint8Array|ArrayBuffer|String): input data. Strings will be - * converted to utf8 byte sequence. - * - flush_mode (Number|Boolean): 0..6 for corresponding Z_NO_FLUSH..Z_TREE modes. - * See constants. Skipped or `false` means Z_NO_FLUSH, `true` means Z_FINISH. - * - * Sends input data to deflate pipe, generating [[Deflate#onData]] calls with - * new compressed chunks. Returns `true` on success. The last data block must - * have `flush_mode` Z_FINISH (or `true`). That will flush internal pending - * buffers and call [[Deflate#onEnd]]. - * - * On fail call [[Deflate#onEnd]] with error code and return false. - * - * ##### Example - * - * ```javascript - * push(chunk, false); // push one of data chunks - * ... - * push(chunk, true); // push last chunk - * ``` - **/ -Deflate.prototype.push = function (data, flush_mode) { - const strm = this.strm; - const chunkSize = this.options.chunkSize; - let status, _flush_mode; + - The maximum input bits used by a length/distance pair is 15 bits for the + length code, 5 bits for the length extra, 15 bits for the distance code, + and 13 bits for the distance extra. This totals 48 bits, or six bytes. + Therefore if strm.avail_in >= 6, then there is enough input to avoid + checking for available input while decoding. - if (this.ended) { return false; } + - The maximum bytes that a single length/distance pair can output is 258 + bytes, which is the maximum length that can be coded. inflate_fast() + requires strm.avail_out >= 258 for each loop to avoid checking for + output space. + */ +module.exports = function inflate_fast(strm, start) { + let _in; /* local strm.input */ + let last; /* have enough input while in < last */ + let _out; /* local strm.output */ + let beg; /* inflate()'s initial strm.output */ + let end; /* while out < end, enough space available */ +//#ifdef INFLATE_STRICT + let dmax; /* maximum distance from zlib header */ +//#endif + let wsize; /* window size or zero if not using window */ + let whave; /* valid bytes in the window */ + let wnext; /* window write index */ + // Use `s_window` instead `window`, avoid conflict with instrumentation tools + let s_window; /* allocated sliding window, if wsize != 0 */ + let hold; /* local strm.hold */ + let bits; /* local strm.bits */ + let lcode; /* local strm.lencode */ + let dcode; /* local strm.distcode */ + let lmask; /* mask for first level of length codes */ + let dmask; /* mask for first level of distance codes */ + let here; /* retrieved table entry */ + let op; /* code bits, operation, extra bits, or */ + /* window position, window bytes to copy */ + let len; /* match length, unused bytes */ + let dist; /* match distance */ + let from; /* where to copy match from */ + let from_source; - if (flush_mode === ~~flush_mode) _flush_mode = flush_mode; - else _flush_mode = flush_mode === true ? Z_FINISH : Z_NO_FLUSH; - // Convert data if needed - if (typeof data === 'string') { - // If we need to compress text, change encoding to utf8. - strm.input = strings.string2buf(data); - } else if (toString.call(data) === '[object ArrayBuffer]') { - strm.input = new Uint8Array(data); - } else { - strm.input = data; - } + let input, output; // JS specific, because we have no pointers - strm.next_in = 0; - strm.avail_in = strm.input.length; + /* copy state to local variables */ + const state = strm.state; + //here = state.here; + _in = strm.next_in; + input = strm.input; + last = _in + (strm.avail_in - 5); + _out = strm.next_out; + output = strm.output; + beg = _out - (start - strm.avail_out); + end = _out + (strm.avail_out - 257); +//#ifdef INFLATE_STRICT + dmax = state.dmax; +//#endif + wsize = state.wsize; + whave = state.whave; + wnext = state.wnext; + s_window = state.window; + hold = state.hold; + bits = state.bits; + lcode = state.lencode; + dcode = state.distcode; + lmask = (1 << state.lenbits) - 1; + dmask = (1 << state.distbits) - 1; - for (;;) { - if (strm.avail_out === 0) { - strm.output = new Uint8Array(chunkSize); - strm.next_out = 0; - strm.avail_out = chunkSize; - } - // Make sure avail_out > 6 to avoid repeating markers - if ((_flush_mode === Z_SYNC_FLUSH || _flush_mode === Z_FULL_FLUSH) && strm.avail_out <= 6) { - this.onData(strm.output.subarray(0, strm.next_out)); - strm.avail_out = 0; - continue; + /* decode literals and length/distances until end-of-block or not enough + input data or output space */ + + top: + do { + if (bits < 15) { + hold += input[_in++] << bits; + bits += 8; + hold += input[_in++] << bits; + bits += 8; } - status = zlib_deflate.deflate(strm, _flush_mode); + here = lcode[hold & lmask]; - // Ended => flush and finish - if (status === Z_STREAM_END) { - if (strm.next_out > 0) { - this.onData(strm.output.subarray(0, strm.next_out)); + dolen: + for (;;) { // Goto emulation + op = here >>> 24/*here.bits*/; + hold >>>= op; + bits -= op; + op = (here >>> 16) & 0xff/*here.op*/; + if (op === 0) { /* literal */ + //Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? + // "inflate: literal '%c'\n" : + // "inflate: literal 0x%02x\n", here.val)); + output[_out++] = here & 0xffff/*here.val*/; } - status = zlib_deflate.deflateEnd(this.strm); - this.onEnd(status); - this.ended = true; - return status === Z_OK; - } + else if (op & 16) { /* length base */ + len = here & 0xffff/*here.val*/; + op &= 15; /* number of extra bits */ + if (op) { + if (bits < op) { + hold += input[_in++] << bits; + bits += 8; + } + len += hold & ((1 << op) - 1); + hold >>>= op; + bits -= op; + } + //Tracevv((stderr, "inflate: length %u\n", len)); + if (bits < 15) { + hold += input[_in++] << bits; + bits += 8; + hold += input[_in++] << bits; + bits += 8; + } + here = dcode[hold & dmask]; - // Flush if out buffer full - if (strm.avail_out === 0) { - this.onData(strm.output); - continue; - } + dodist: + for (;;) { // goto emulation + op = here >>> 24/*here.bits*/; + hold >>>= op; + bits -= op; + op = (here >>> 16) & 0xff/*here.op*/; - // Flush if requested and has data - if (_flush_mode > 0 && strm.next_out > 0) { - this.onData(strm.output.subarray(0, strm.next_out)); - strm.avail_out = 0; - continue; - } + if (op & 16) { /* distance base */ + dist = here & 0xffff/*here.val*/; + op &= 15; /* number of extra bits */ + if (bits < op) { + hold += input[_in++] << bits; + bits += 8; + if (bits < op) { + hold += input[_in++] << bits; + bits += 8; + } + } + dist += hold & ((1 << op) - 1); +//#ifdef INFLATE_STRICT + if (dist > dmax) { + strm.msg = 'invalid distance too far back'; + state.mode = BAD; + break top; + } +//#endif + hold >>>= op; + bits -= op; + //Tracevv((stderr, "inflate: distance %u\n", dist)); + op = _out - beg; /* max distance in output */ + if (dist > op) { /* see if copy from window */ + op = dist - op; /* distance back in window */ + if (op > whave) { + if (state.sane) { + strm.msg = 'invalid distance too far back'; + state.mode = BAD; + break top; + } - if (strm.avail_in === 0) break; - } +// (!) This block is disabled in zlib defaults, +// don't enable it for binary compatibility +//#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR +// if (len <= op - whave) { +// do { +// output[_out++] = 0; +// } while (--len); +// continue top; +// } +// len -= op - whave; +// do { +// output[_out++] = 0; +// } while (--op > whave); +// if (op === 0) { +// from = _out - dist; +// do { +// output[_out++] = output[from++]; +// } while (--len); +// continue top; +// } +//#endif + } + from = 0; // window index + from_source = s_window; + if (wnext === 0) { /* very common case */ + from += wsize - op; + if (op < len) { /* some from window */ + len -= op; + do { + output[_out++] = s_window[from++]; + } while (--op); + from = _out - dist; /* rest from output */ + from_source = output; + } + } + else if (wnext < op) { /* wrap around window */ + from += wsize + wnext - op; + op -= wnext; + if (op < len) { /* some from end of window */ + len -= op; + do { + output[_out++] = s_window[from++]; + } while (--op); + from = 0; + if (wnext < len) { /* some from start of window */ + op = wnext; + len -= op; + do { + output[_out++] = s_window[from++]; + } while (--op); + from = _out - dist; /* rest from output */ + from_source = output; + } + } + } + else { /* contiguous in window */ + from += wnext - op; + if (op < len) { /* some from window */ + len -= op; + do { + output[_out++] = s_window[from++]; + } while (--op); + from = _out - dist; /* rest from output */ + from_source = output; + } + } + while (len > 2) { + output[_out++] = from_source[from++]; + output[_out++] = from_source[from++]; + output[_out++] = from_source[from++]; + len -= 3; + } + if (len) { + output[_out++] = from_source[from++]; + if (len > 1) { + output[_out++] = from_source[from++]; + } + } + } + else { + from = _out - dist; /* copy direct from output */ + do { /* minimum length is three */ + output[_out++] = output[from++]; + output[_out++] = output[from++]; + output[_out++] = output[from++]; + len -= 3; + } while (len > 2); + if (len) { + output[_out++] = output[from++]; + if (len > 1) { + output[_out++] = output[from++]; + } + } + } + } + else if ((op & 64) === 0) { /* 2nd level distance code */ + here = dcode[(here & 0xffff)/*here.val*/ + (hold & ((1 << op) - 1))]; + continue dodist; + } + else { + strm.msg = 'invalid distance code'; + state.mode = BAD; + break top; + } - return true; -}; + break; // need to emulate goto via "continue" + } + } + else if ((op & 64) === 0) { /* 2nd level length code */ + here = lcode[(here & 0xffff)/*here.val*/ + (hold & ((1 << op) - 1))]; + continue dolen; + } + else if (op & 32) { /* end-of-block */ + //Tracevv((stderr, "inflate: end of block\n")); + state.mode = TYPE; + break top; + } + else { + strm.msg = 'invalid literal/length code'; + state.mode = BAD; + break top; + } + break; // need to emulate goto via "continue" + } + } while (_in < last && _out < end); -/** - * Deflate#onData(chunk) -> Void - * - chunk (Uint8Array): output data. - * - * By default, stores data blocks in `chunks[]` property and glue - * those in `onEnd`. Override this handler, if you need another behaviour. - **/ -Deflate.prototype.onData = function (chunk) { - this.chunks.push(chunk); + /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ + len = bits >> 3; + _in -= len; + bits -= len << 3; + hold &= (1 << bits) - 1; + + /* update state and return */ + strm.next_in = _in; + strm.next_out = _out; + strm.avail_in = (_in < last ? 5 + (last - _in) : 5 - (_in - last)); + strm.avail_out = (_out < end ? 257 + (end - _out) : 257 - (_out - end)); + state.hold = hold; + state.bits = bits; + return; }; +},{}],76:[function(require,module,exports){ +'use strict'; -/** - * Deflate#onEnd(status) -> Void - * - status (Number): deflate status. 0 (Z_OK) on success, - * other if not. - * - * Called once after you tell deflate that the input stream is - * complete (Z_FINISH). By default - join collected chunks, - * free memory and fill `results` / `err` properties. - **/ -Deflate.prototype.onEnd = function (status) { - // On success - join - if (status === Z_OK) { - this.result = utils.flattenChunks(this.chunks); - } - this.chunks = []; - this.err = status; - this.msg = this.strm.msg; -}; +// (C) 1995-2013 Jean-loup Gailly and Mark Adler +// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. +const adler32 = require('./adler32'); +const crc32 = require('./crc32'); +const inflate_fast = require('./inffast'); +const inflate_table = require('./inftrees'); -/** - * deflate(data[, options]) -> Uint8Array - * - data (Uint8Array|String): input data to compress. - * - options (Object): zlib deflate options. - * - * Compress `data` with deflate algorithm and `options`. - * - * Supported options are: - * - * - level - * - windowBits - * - memLevel - * - strategy - * - dictionary - * - * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced) - * for more information on these. - * - * Sugar (options): - * - * - `raw` (Boolean) - say that we work with raw stream, if you don't wish to specify - * negative windowBits implicitly. - * - * ##### Example: - * - * ```javascript - * const pako = require('pako') - * const data = new Uint8Array([1,2,3,4,5,6,7,8,9]); - * - * console.log(pako.deflate(data)); - * ``` - **/ -function deflate(input, options) { - const deflator = new Deflate(options); +const CODES = 0; +const LENS = 1; +const DISTS = 2; - deflator.push(input, true); +/* Public constants ==========================================================*/ +/* ===========================================================================*/ - // That will never happens, if you don't cheat with options :) - if (deflator.err) { throw deflator.msg || msg[deflator.err]; } +const { + Z_FINISH, Z_BLOCK, Z_TREES, + Z_OK, Z_STREAM_END, Z_NEED_DICT, Z_STREAM_ERROR, Z_DATA_ERROR, Z_MEM_ERROR, Z_BUF_ERROR, + Z_DEFLATED +} = require('./constants'); - return deflator.result; -} +/* STATES ====================================================================*/ +/* ===========================================================================*/ -/** - * deflateRaw(data[, options]) -> Uint8Array - * - data (Uint8Array|String): input data to compress. - * - options (Object): zlib deflate options. - * - * The same as [[deflate]], but creates raw data, without wrapper - * (header and adler32 crc). - **/ -function deflateRaw(input, options) { - options = options || {}; - options.raw = true; - return deflate(input, options); -} +const HEAD = 16180; /* i: waiting for magic header */ +const FLAGS = 16181; /* i: waiting for method and flags (gzip) */ +const TIME = 16182; /* i: waiting for modification time (gzip) */ +const OS = 16183; /* i: waiting for extra flags and operating system (gzip) */ +const EXLEN = 16184; /* i: waiting for extra length (gzip) */ +const EXTRA = 16185; /* i: waiting for extra bytes (gzip) */ +const NAME = 16186; /* i: waiting for end of file name (gzip) */ +const COMMENT = 16187; /* i: waiting for end of comment (gzip) */ +const HCRC = 16188; /* i: waiting for header crc (gzip) */ +const DICTID = 16189; /* i: waiting for dictionary check value */ +const DICT = 16190; /* waiting for inflateSetDictionary() call */ +const TYPE = 16191; /* i: waiting for type bits, including last-flag bit */ +const TYPEDO = 16192; /* i: same, but skip check to exit inflate on new block */ +const STORED = 16193; /* i: waiting for stored size (length and complement) */ +const COPY_ = 16194; /* i/o: same as COPY below, but only first time in */ +const COPY = 16195; /* i/o: waiting for input or output to copy stored block */ +const TABLE = 16196; /* i: waiting for dynamic block table lengths */ +const LENLENS = 16197; /* i: waiting for code length code lengths */ +const CODELENS = 16198; /* i: waiting for length/lit and distance code lengths */ +const LEN_ = 16199; /* i: same as LEN below, but only first time in */ +const LEN = 16200; /* i: waiting for length/lit/eob code */ +const LENEXT = 16201; /* i: waiting for length extra bits */ +const DIST = 16202; /* i: waiting for distance code */ +const DISTEXT = 16203; /* i: waiting for distance extra bits */ +const MATCH = 16204; /* o: waiting for output space to copy string */ +const LIT = 16205; /* o: waiting for output space to write literal */ +const CHECK = 16206; /* i: waiting for 32-bit check value */ +const LENGTH = 16207; /* i: waiting for 32-bit length (gzip) */ +const DONE = 16208; /* finished check, done -- remain here until reset */ +const BAD = 16209; /* got a data error -- remain here until reset */ +const MEM = 16210; /* got an inflate() memory error -- remain here until reset */ +const SYNC = 16211; /* looking for synchronization bytes to restart inflate() */ -/** - * gzip(data[, options]) -> Uint8Array - * - data (Uint8Array|String): input data to compress. - * - options (Object): zlib deflate options. - * - * The same as [[deflate]], but create gzip wrapper instead of - * deflate one. - **/ -function gzip(input, options) { - options = options || {}; - options.gzip = true; - return deflate(input, options); -} +/* ===========================================================================*/ -module.exports.Deflate = Deflate; -module.exports.deflate = deflate; -module.exports.deflateRaw = deflateRaw; -module.exports.gzip = gzip; -module.exports.constants = require('./zlib/constants'); -},{"./utils/common":68,"./utils/strings":69,"./zlib/constants":71,"./zlib/deflate":73,"./zlib/messages":78,"./zlib/zstream":80}],67:[function(require,module,exports){ -'use strict'; +const ENOUGH_LENS = 852; +const ENOUGH_DISTS = 592; +//const ENOUGH = (ENOUGH_LENS+ENOUGH_DISTS); +const MAX_WBITS = 15; +/* 32K LZ77 window */ +const DEF_WBITS = MAX_WBITS; -const zlib_inflate = require('./zlib/inflate'); -const utils = require('./utils/common'); -const strings = require('./utils/strings'); -const msg = require('./zlib/messages'); -const ZStream = require('./zlib/zstream'); -const GZheader = require('./zlib/gzheader'); -const toString = Object.prototype.toString; +const zswap32 = (q) => { -/* Public constants ==========================================================*/ -/* ===========================================================================*/ + return (((q >>> 24) & 0xff) + + ((q >>> 8) & 0xff00) + + ((q & 0xff00) << 8) + + ((q & 0xff) << 24)); +}; -const { - Z_NO_FLUSH, Z_FINISH, - Z_OK, Z_STREAM_END, Z_NEED_DICT, Z_STREAM_ERROR, Z_DATA_ERROR, Z_MEM_ERROR -} = require('./zlib/constants'); -/* ===========================================================================*/ +function InflateState() { + this.strm = null; /* pointer back to this zlib stream */ + this.mode = 0; /* current inflate mode */ + this.last = false; /* true if processing last block */ + this.wrap = 0; /* bit 0 true for zlib, bit 1 true for gzip, + bit 2 true to validate check value */ + this.havedict = false; /* true if dictionary provided */ + this.flags = 0; /* gzip header method and flags (0 if zlib), or + -1 if raw or no header yet */ + this.dmax = 0; /* zlib header max distance (INFLATE_STRICT) */ + this.check = 0; /* protected copy of check value */ + this.total = 0; /* protected copy of output count */ + // TODO: may be {} + this.head = null; /* where to save gzip header information */ + /* sliding window */ + this.wbits = 0; /* log base 2 of requested window size */ + this.wsize = 0; /* window size or zero if not using window */ + this.whave = 0; /* valid bytes in the window */ + this.wnext = 0; /* window write index */ + this.window = null; /* allocated sliding window, if needed */ -/** - * class Inflate - * - * Generic JS-style wrapper for zlib calls. If you don't need - * streaming behaviour - use more simple functions: [[inflate]] - * and [[inflateRaw]]. - **/ + /* bit accumulator */ + this.hold = 0; /* input bit accumulator */ + this.bits = 0; /* number of bits in "in" */ -/* internal - * inflate.chunks -> Array - * - * Chunks of output data, if [[Inflate#onData]] not overridden. - **/ + /* for string and stored block copying */ + this.length = 0; /* literal or length of data to copy */ + this.offset = 0; /* distance back to copy string from */ -/** - * Inflate.result -> Uint8Array|String - * - * Uncompressed result, generated by default [[Inflate#onData]] - * and [[Inflate#onEnd]] handlers. Filled after you push last chunk - * (call [[Inflate#push]] with `Z_FINISH` / `true` param). - **/ + /* for table and code decoding */ + this.extra = 0; /* extra bits needed */ -/** - * Inflate.err -> Number - * - * Error code after inflate finished. 0 (Z_OK) on success. - * Should be checked if broken data possible. - **/ + /* fixed and dynamic code tables */ + this.lencode = null; /* starting table for length/literal codes */ + this.distcode = null; /* starting table for distance codes */ + this.lenbits = 0; /* index bits for lencode */ + this.distbits = 0; /* index bits for distcode */ -/** - * Inflate.msg -> String - * - * Error message, if [[Inflate.err]] != 0 - **/ + /* dynamic table building */ + this.ncode = 0; /* number of code length code lengths */ + this.nlen = 0; /* number of length code lengths */ + this.ndist = 0; /* number of distance code lengths */ + this.have = 0; /* number of code lengths in lens[] */ + this.next = null; /* next available space in codes[] */ + this.lens = new Uint16Array(320); /* temporary storage for code lengths */ + this.work = new Uint16Array(288); /* work area for code table building */ -/** - * new Inflate(options) - * - options (Object): zlib inflate options. - * - * Creates new inflator instance with specified params. Throws exception - * on bad params. Supported options: - * - * - `windowBits` - * - `dictionary` - * - * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced) - * for more information on these. - * - * Additional options, for internal needs: - * - * - `chunkSize` - size of generated data chunks (16K by default) - * - `raw` (Boolean) - do raw inflate - * - `to` (String) - if equal to 'string', then result will be converted - * from utf8 to utf16 (javascript) string. When string output requested, - * chunk length can differ from `chunkSize`, depending on content. - * - * By default, when no options set, autodetect deflate/gzip data format via - * wrapper header. - * - * ##### Example: - * - * ```javascript - * const pako = require('pako') - * const chunk1 = new Uint8Array([1,2,3,4,5,6,7,8,9]) - * const chunk2 = new Uint8Array([10,11,12,13,14,15,16,17,18,19]); - * - * const inflate = new pako.Inflate({ level: 3}); - * - * inflate.push(chunk1, false); - * inflate.push(chunk2, true); // true -> last chunk - * - * if (inflate.err) { throw new Error(inflate.err); } - * - * console.log(inflate.result); - * ``` - **/ -function Inflate(options) { - this.options = utils.assign({ - chunkSize: 1024 * 64, - windowBits: 15, - to: '' - }, options || {}); + /* + because we don't have pointers in js, we use lencode and distcode directly + as buffers so we don't need codes + */ + //this.codes = new Int32Array(ENOUGH); /* space for code tables */ + this.lendyn = null; /* dynamic table for length/literal codes (JS specific) */ + this.distdyn = null; /* dynamic table for distance codes (JS specific) */ + this.sane = 0; /* if false, allow invalid distance too far */ + this.back = 0; /* bits back of last unprocessed length/lit */ + this.was = 0; /* initial length of match */ +} - const opt = this.options; - // Force window size for `raw` data, if not set directly, - // because we have no header for autodetect. - if (opt.raw && (opt.windowBits >= 0) && (opt.windowBits < 16)) { - opt.windowBits = -opt.windowBits; - if (opt.windowBits === 0) { opt.windowBits = -15; } - } +const inflateStateCheck = (strm) => { - // If `windowBits` not defined (and mode not raw) - set autodetect flag for gzip/deflate - if ((opt.windowBits >= 0) && (opt.windowBits < 16) && - !(options && options.windowBits)) { - opt.windowBits += 32; + if (!strm) { + return 1; } - - // Gzip header has no info about windows size, we can do autodetect only - // for deflate. So, if window size not set, force it to max when gzip possible - if ((opt.windowBits > 15) && (opt.windowBits < 48)) { - // bit 3 (16) -> gzipped data - // bit 4 (32) -> autodetect gzip/deflate - if ((opt.windowBits & 15) === 0) { - opt.windowBits |= 15; - } + const state = strm.state; + if (!state || state.strm !== strm || + state.mode < HEAD || state.mode > SYNC) { + return 1; } + return 0; +}; - this.err = 0; // error code, if happens (0 = Z_OK) - this.msg = ''; // error message - this.ended = false; // used to avoid multiple onEnd() calls - this.chunks = []; // chunks of compressed data - - this.strm = new ZStream(); - this.strm.avail_out = 0; - let status = zlib_inflate.inflateInit2( - this.strm, - opt.windowBits - ); +const inflateResetKeep = (strm) => { - if (status !== Z_OK) { - throw new Error(msg[status]); + if (inflateStateCheck(strm)) { return Z_STREAM_ERROR; } + const state = strm.state; + strm.total_in = strm.total_out = state.total = 0; + strm.msg = ''; /*Z_NULL*/ + if (state.wrap) { /* to support ill-conceived Java test suite */ + strm.adler = state.wrap & 1; } + state.mode = HEAD; + state.last = 0; + state.havedict = 0; + state.flags = -1; + state.dmax = 32768; + state.head = null/*Z_NULL*/; + state.hold = 0; + state.bits = 0; + //state.lencode = state.distcode = state.next = state.codes; + state.lencode = state.lendyn = new Int32Array(ENOUGH_LENS); + state.distcode = state.distdyn = new Int32Array(ENOUGH_DISTS); - this.header = new GZheader(); + state.sane = 1; + state.back = -1; + //Tracev((stderr, "inflate: reset\n")); + return Z_OK; +}; - zlib_inflate.inflateGetHeader(this.strm, this.header); - // Setup dictionary - if (opt.dictionary) { - // Convert data if needed - if (typeof opt.dictionary === 'string') { - opt.dictionary = strings.string2buf(opt.dictionary); - } else if (toString.call(opt.dictionary) === '[object ArrayBuffer]') { - opt.dictionary = new Uint8Array(opt.dictionary); - } - if (opt.raw) { //In raw mode we need to set the dictionary early - status = zlib_inflate.inflateSetDictionary(this.strm, opt.dictionary); - if (status !== Z_OK) { - throw new Error(msg[status]); - } - } - } -} +const inflateReset = (strm) => { -/** - * Inflate#push(data[, flush_mode]) -> Boolean - * - data (Uint8Array|ArrayBuffer): input data - * - flush_mode (Number|Boolean): 0..6 for corresponding Z_NO_FLUSH..Z_TREE - * flush modes. See constants. Skipped or `false` means Z_NO_FLUSH, - * `true` means Z_FINISH. - * - * Sends input data to inflate pipe, generating [[Inflate#onData]] calls with - * new output chunks. Returns `true` on success. If end of stream detected, - * [[Inflate#onEnd]] will be called. - * - * `flush_mode` is not needed for normal operation, because end of stream - * detected automatically. You may try to use it for advanced things, but - * this functionality was not tested. - * - * On fail call [[Inflate#onEnd]] with error code and return false. - * - * ##### Example - * - * ```javascript - * push(chunk, false); // push one of data chunks - * ... - * push(chunk, true); // push last chunk - * ``` - **/ -Inflate.prototype.push = function (data, flush_mode) { - const strm = this.strm; - const chunkSize = this.options.chunkSize; - const dictionary = this.options.dictionary; - let status, _flush_mode, last_avail_out; + if (inflateStateCheck(strm)) { return Z_STREAM_ERROR; } + const state = strm.state; + state.wsize = 0; + state.whave = 0; + state.wnext = 0; + return inflateResetKeep(strm); - if (this.ended) return false; +}; - if (flush_mode === ~~flush_mode) _flush_mode = flush_mode; - else _flush_mode = flush_mode === true ? Z_FINISH : Z_NO_FLUSH; - // Convert data if needed - if (toString.call(data) === '[object ArrayBuffer]') { - strm.input = new Uint8Array(data); - } else { - strm.input = data; - } +const inflateReset2 = (strm, windowBits) => { + let wrap; - strm.next_in = 0; - strm.avail_in = strm.input.length; + /* get the state */ + if (inflateStateCheck(strm)) { return Z_STREAM_ERROR; } + const state = strm.state; - for (;;) { - if (strm.avail_out === 0) { - strm.output = new Uint8Array(chunkSize); - strm.next_out = 0; - strm.avail_out = chunkSize; + /* extract wrap request from windowBits parameter */ + if (windowBits < 0) { + wrap = 0; + windowBits = -windowBits; + } + else { + wrap = (windowBits >> 4) + 5; + if (windowBits < 48) { + windowBits &= 15; } + } - status = zlib_inflate.inflate(strm, _flush_mode); + /* set number of window bits, free window if different */ + if (windowBits && (windowBits < 8 || windowBits > 15)) { + return Z_STREAM_ERROR; + } + if (state.window !== null && state.wbits !== windowBits) { + state.window = null; + } - if (status === Z_NEED_DICT && dictionary) { - status = zlib_inflate.inflateSetDictionary(strm, dictionary); + /* update state and reset the rest of it */ + state.wrap = wrap; + state.wbits = windowBits; + return inflateReset(strm); +}; - if (status === Z_OK) { - status = zlib_inflate.inflate(strm, _flush_mode); - } else if (status === Z_DATA_ERROR) { - // Replace code with more verbose - status = Z_NEED_DICT; - } - } - // Skip snyc markers if more data follows and not raw mode - while (strm.avail_in > 0 && - status === Z_STREAM_END && - strm.state.wrap > 0 && - data[strm.next_in] !== 0) - { - zlib_inflate.inflateReset(strm); - status = zlib_inflate.inflate(strm, _flush_mode); - } +const inflateInit2 = (strm, windowBits) => { - switch (status) { - case Z_STREAM_ERROR: - case Z_DATA_ERROR: - case Z_NEED_DICT: - case Z_MEM_ERROR: - this.onEnd(status); - this.ended = true; - return false; - } + if (!strm) { return Z_STREAM_ERROR; } + //strm.msg = Z_NULL; /* in case we return an error */ - // Remember real `avail_out` value, because we may patch out buffer content - // to align utf8 strings boundaries. - last_avail_out = strm.avail_out; + const state = new InflateState(); - if (strm.next_out) { - if (strm.avail_out === 0 || status === Z_STREAM_END) { + //if (state === Z_NULL) return Z_MEM_ERROR; + //Tracev((stderr, "inflate: allocated\n")); + strm.state = state; + state.strm = strm; + state.window = null/*Z_NULL*/; + state.mode = HEAD; /* to pass state test in inflateReset2() */ + const ret = inflateReset2(strm, windowBits); + if (ret !== Z_OK) { + strm.state = null/*Z_NULL*/; + } + return ret; +}; - if (this.options.to === 'string') { - let next_out_utf8 = strings.utf8border(strm.output, strm.next_out); +const inflateInit = (strm) => { - let tail = strm.next_out - next_out_utf8; - let utf8str = strings.buf2string(strm.output, next_out_utf8); + return inflateInit2(strm, DEF_WBITS); +}; - // move tail & realign counters - strm.next_out = tail; - strm.avail_out = chunkSize - tail; - if (tail) strm.output.set(strm.output.subarray(next_out_utf8, next_out_utf8 + tail), 0); - this.onData(utf8str); +/* + Return state with length and distance decoding tables and index sizes set to + fixed code decoding. Normally this returns fixed tables from inffixed.h. + If BUILDFIXED is defined, then instead this routine builds the tables the + first time it's called, and returns those tables the first time and + thereafter. This reduces the size of the code by about 2K bytes, in + exchange for a little execution time. However, BUILDFIXED should not be + used for threaded applications, since the rewriting of the tables and virgin + may not be thread-safe. + */ +let virgin = true; - } else { - this.onData(strm.output.length === strm.next_out ? strm.output : strm.output.subarray(0, strm.next_out)); - } - } - } - - // Must repeat iteration if out buffer is full - if (status === Z_OK && last_avail_out === 0) continue; - - // Finalize if end of stream reached. - if (status === Z_STREAM_END) { - status = zlib_inflate.inflateEnd(this.strm); - this.onEnd(status); - this.ended = true; - return true; - } - - if (strm.avail_in === 0) break; - } - - return true; -}; - - -/** - * Inflate#onData(chunk) -> Void - * - chunk (Uint8Array|String): output data. When string output requested, - * each chunk will be string. - * - * By default, stores data blocks in `chunks[]` property and glue - * those in `onEnd`. Override this handler, if you need another behaviour. - **/ -Inflate.prototype.onData = function (chunk) { - this.chunks.push(chunk); -}; - - -/** - * Inflate#onEnd(status) -> Void - * - status (Number): inflate status. 0 (Z_OK) on success, - * other if not. - * - * Called either after you tell inflate that the input stream is - * complete (Z_FINISH). By default - join collected chunks, - * free memory and fill `results` / `err` properties. - **/ -Inflate.prototype.onEnd = function (status) { - // On success - join - if (status === Z_OK) { - if (this.options.to === 'string') { - this.result = this.chunks.join(''); - } else { - this.result = utils.flattenChunks(this.chunks); - } - } - this.chunks = []; - this.err = status; - this.msg = this.strm.msg; -}; - - -/** - * inflate(data[, options]) -> Uint8Array|String - * - data (Uint8Array): input data to decompress. - * - options (Object): zlib inflate options. - * - * Decompress `data` with inflate/ungzip and `options`. Autodetect - * format via wrapper header by default. That's why we don't provide - * separate `ungzip` method. - * - * Supported options are: - * - * - windowBits - * - * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced) - * for more information. - * - * Sugar (options): - * - * - `raw` (Boolean) - say that we work with raw stream, if you don't wish to specify - * negative windowBits implicitly. - * - `to` (String) - if equal to 'string', then result will be converted - * from utf8 to utf16 (javascript) string. When string output requested, - * chunk length can differ from `chunkSize`, depending on content. - * - * - * ##### Example: - * - * ```javascript - * const pako = require('pako'); - * const input = pako.deflate(new Uint8Array([1,2,3,4,5,6,7,8,9])); - * let output; - * - * try { - * output = pako.inflate(input); - * } catch (err) { - * console.log(err); - * } - * ``` - **/ -function inflate(input, options) { - const inflator = new Inflate(options); - - inflator.push(input); - - // That will never happens, if you don't cheat with options :) - if (inflator.err) throw inflator.msg || msg[inflator.err]; - - return inflator.result; -} - - -/** - * inflateRaw(data[, options]) -> Uint8Array|String - * - data (Uint8Array): input data to decompress. - * - options (Object): zlib inflate options. - * - * The same as [[inflate]], but creates raw data, without wrapper - * (header and adler32 crc). - **/ -function inflateRaw(input, options) { - options = options || {}; - options.raw = true; - return inflate(input, options); -} - - -/** - * ungzip(data[, options]) -> Uint8Array|String - * - data (Uint8Array): input data to decompress. - * - options (Object): zlib inflate options. - * - * Just shortcut to [[inflate]], because it autodetects format - * by header.content. Done for convenience. - **/ - - -module.exports.Inflate = Inflate; -module.exports.inflate = inflate; -module.exports.inflateRaw = inflateRaw; -module.exports.ungzip = inflate; -module.exports.constants = require('./zlib/constants'); - -},{"./utils/common":68,"./utils/strings":69,"./zlib/constants":71,"./zlib/gzheader":74,"./zlib/inflate":76,"./zlib/messages":78,"./zlib/zstream":80}],68:[function(require,module,exports){ -'use strict'; - - -const _has = (obj, key) => { - return Object.prototype.hasOwnProperty.call(obj, key); -}; - -module.exports.assign = function (obj /*from1, from2, from3, ...*/) { - const sources = Array.prototype.slice.call(arguments, 1); - while (sources.length) { - const source = sources.shift(); - if (!source) { continue; } +let lenfix, distfix; // We have no pointers in JS, so keep tables separate - if (typeof source !== 'object') { - throw new TypeError(source + 'must be non-object'); - } - for (const p in source) { - if (_has(source, p)) { - obj[p] = source[p]; - } - } - } +const fixedtables = (state) => { - return obj; -}; + /* build fixed huffman tables if first call (may not be thread safe) */ + if (virgin) { + lenfix = new Int32Array(512); + distfix = new Int32Array(32); + /* literal/length table */ + let sym = 0; + while (sym < 144) { state.lens[sym++] = 8; } + while (sym < 256) { state.lens[sym++] = 9; } + while (sym < 280) { state.lens[sym++] = 7; } + while (sym < 288) { state.lens[sym++] = 8; } -// Join array of chunks to single array. -module.exports.flattenChunks = (chunks) => { - // calculate data length - let len = 0; + inflate_table(LENS, state.lens, 0, 288, lenfix, 0, state.work, { bits: 9 }); - for (let i = 0, l = chunks.length; i < l; i++) { - len += chunks[i].length; - } + /* distance table */ + sym = 0; + while (sym < 32) { state.lens[sym++] = 5; } - // join chunks - const result = new Uint8Array(len); + inflate_table(DISTS, state.lens, 0, 32, distfix, 0, state.work, { bits: 5 }); - for (let i = 0, pos = 0, l = chunks.length; i < l; i++) { - let chunk = chunks[i]; - result.set(chunk, pos); - pos += chunk.length; + /* do this just once */ + virgin = false; } - return result; + state.lencode = lenfix; + state.lenbits = 9; + state.distcode = distfix; + state.distbits = 5; }; -},{}],69:[function(require,module,exports){ -// String encode/decode helpers -'use strict'; - - -// Quick check if we can use fast array to bin string conversion -// -// - apply(Array) can fail on Android 2.2 -// - apply(Uint8Array) can fail on iOS 5.1 Safari -// -let STR_APPLY_UIA_OK = true; -try { String.fromCharCode.apply(null, new Uint8Array(1)); } catch (__) { STR_APPLY_UIA_OK = false; } +/* + Update the window with the last wsize (normally 32K) bytes written before + returning. If window does not exist yet, create it. This is only called + when a window is already in use, or when output has been written during this + inflate call, but the end of the deflate stream has not been reached yet. + It is also called to create a window for dictionary data when a dictionary + is loaded. + Providing output buffers larger than 32K to inflate() should provide a speed + advantage, since only the last 32K of output is copied to the sliding window + upon return from inflate(), and since all distances after the first 32K of + output will fall in the output data, making match copies simpler and faster. + The advantage may be dependent on the size of the processor's data caches. + */ +const updatewindow = (strm, src, end, copy) => { -// Table with utf8 lengths (calculated by first byte of sequence) -// Note, that 5 & 6-byte values and some 4-byte values can not be represented in JS, -// because max possible codepoint is 0x10ffff -const _utf8len = new Uint8Array(256); -for (let q = 0; q < 256; q++) { - _utf8len[q] = (q >= 252 ? 6 : q >= 248 ? 5 : q >= 240 ? 4 : q >= 224 ? 3 : q >= 192 ? 2 : 1); -} -_utf8len[254] = _utf8len[254] = 1; // Invalid sequence start + let dist; + const state = strm.state; + /* if it hasn't been done already, allocate space for the window */ + if (state.window === null) { + state.wsize = 1 << state.wbits; + state.wnext = 0; + state.whave = 0; -// convert string to array (typed, when possible) -module.exports.string2buf = (str) => { - if (typeof TextEncoder === 'function' && TextEncoder.prototype.encode) { - return new TextEncoder().encode(str); + state.window = new Uint8Array(state.wsize); } - let buf, c, c2, m_pos, i, str_len = str.length, buf_len = 0; - - // count binary size - for (m_pos = 0; m_pos < str_len; m_pos++) { - c = str.charCodeAt(m_pos); - if ((c & 0xfc00) === 0xd800 && (m_pos + 1 < str_len)) { - c2 = str.charCodeAt(m_pos + 1); - if ((c2 & 0xfc00) === 0xdc00) { - c = 0x10000 + ((c - 0xd800) << 10) + (c2 - 0xdc00); - m_pos++; - } - } - buf_len += c < 0x80 ? 1 : c < 0x800 ? 2 : c < 0x10000 ? 3 : 4; + /* copy state->wsize or less output bytes into the circular window */ + if (copy >= state.wsize) { + state.window.set(src.subarray(end - state.wsize, end), 0); + state.wnext = 0; + state.whave = state.wsize; } - - // allocate buffer - buf = new Uint8Array(buf_len); - - // convert - for (i = 0, m_pos = 0; i < buf_len; m_pos++) { - c = str.charCodeAt(m_pos); - if ((c & 0xfc00) === 0xd800 && (m_pos + 1 < str_len)) { - c2 = str.charCodeAt(m_pos + 1); - if ((c2 & 0xfc00) === 0xdc00) { - c = 0x10000 + ((c - 0xd800) << 10) + (c2 - 0xdc00); - m_pos++; - } + else { + dist = state.wsize - state.wnext; + if (dist > copy) { + dist = copy; } - if (c < 0x80) { - /* one byte */ - buf[i++] = c; - } else if (c < 0x800) { - /* two bytes */ - buf[i++] = 0xC0 | (c >>> 6); - buf[i++] = 0x80 | (c & 0x3f); - } else if (c < 0x10000) { - /* three bytes */ - buf[i++] = 0xE0 | (c >>> 12); - buf[i++] = 0x80 | (c >>> 6 & 0x3f); - buf[i++] = 0x80 | (c & 0x3f); - } else { - /* four bytes */ - buf[i++] = 0xf0 | (c >>> 18); - buf[i++] = 0x80 | (c >>> 12 & 0x3f); - buf[i++] = 0x80 | (c >>> 6 & 0x3f); - buf[i++] = 0x80 | (c & 0x3f); + //zmemcpy(state->window + state->wnext, end - copy, dist); + state.window.set(src.subarray(end - copy, end - copy + dist), state.wnext); + copy -= dist; + if (copy) { + //zmemcpy(state->window, end - copy, copy); + state.window.set(src.subarray(end - copy, end), 0); + state.wnext = copy; + state.whave = state.wsize; } - } - - return buf; -}; - -// Helper -const buf2binstring = (buf, len) => { - // On Chrome, the arguments in a function call that are allowed is `65534`. - // If the length of the buffer is smaller than that, we can use this optimization, - // otherwise we will take a slower path. - if (len < 65534) { - if (buf.subarray && STR_APPLY_UIA_OK) { - return String.fromCharCode.apply(null, buf.length === len ? buf : buf.subarray(0, len)); + else { + state.wnext += dist; + if (state.wnext === state.wsize) { state.wnext = 0; } + if (state.whave < state.wsize) { state.whave += dist; } } } - - let result = ''; - for (let i = 0; i < len; i++) { - result += String.fromCharCode(buf[i]); - } - return result; + return 0; }; -// convert array to string -module.exports.buf2string = (buf, max) => { - const len = max || buf.length; - - if (typeof TextDecoder === 'function' && TextDecoder.prototype.decode) { - return new TextDecoder().decode(buf.subarray(0, max)); - } - - let i, out; - - // Reserve max possible length (2 words per char) - // NB: by unknown reasons, Array is significantly faster for - // String.fromCharCode.apply than Uint16Array. - const utf16buf = new Array(len * 2); +const inflate = (strm, flush) => { - for (out = 0, i = 0; i < len;) { - let c = buf[i++]; - // quick process ascii - if (c < 0x80) { utf16buf[out++] = c; continue; } + let state; + let input, output; // input/output buffers + let next; /* next input INDEX */ + let put; /* next output INDEX */ + let have, left; /* available input and output */ + let hold; /* bit buffer */ + let bits; /* bits in bit buffer */ + let _in, _out; /* save starting available input and output */ + let copy; /* number of stored or match bytes to copy */ + let from; /* where to copy match bytes from */ + let from_source; + let here = 0; /* current decoding table entry */ + let here_bits, here_op, here_val; // paked "here" denormalized (JS specific) + //let last; /* parent table entry */ + let last_bits, last_op, last_val; // paked "last" denormalized (JS specific) + let len; /* length to copy for repeats, bits to drop */ + let ret; /* return code */ + const hbuf = new Uint8Array(4); /* buffer for gzip header crc calculation */ + let opts; - let c_len = _utf8len[c]; - // skip 5 & 6 byte codes - if (c_len > 4) { utf16buf[out++] = 0xfffd; i += c_len - 1; continue; } + let n; // temporary variable for NEED_BITS - // apply mask on first byte - c &= c_len === 2 ? 0x1f : c_len === 3 ? 0x0f : 0x07; - // join the rest - while (c_len > 1 && i < len) { - c = (c << 6) | (buf[i++] & 0x3f); - c_len--; - } + const order = /* permutation of code lengths */ + new Uint8Array([ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 ]); - // terminated by end of string? - if (c_len > 1) { utf16buf[out++] = 0xfffd; continue; } - if (c < 0x10000) { - utf16buf[out++] = c; - } else { - c -= 0x10000; - utf16buf[out++] = 0xd800 | ((c >> 10) & 0x3ff); - utf16buf[out++] = 0xdc00 | (c & 0x3ff); - } + if (inflateStateCheck(strm) || !strm.output || + (!strm.input && strm.avail_in !== 0)) { + return Z_STREAM_ERROR; } - return buf2binstring(utf16buf, out); -}; - - -// Calculate max possible position in utf8 buffer, -// that will not break sequence. If that's not possible -// - (very small limits) return max size as is. -// -// buf[] - utf8 bytes array -// max - length limit (mandatory); -module.exports.utf8border = (buf, max) => { - - max = max || buf.length; - if (max > buf.length) { max = buf.length; } + state = strm.state; + if (state.mode === TYPE) { state.mode = TYPEDO; } /* skip check */ - // go back from last position, until start of sequence found - let pos = max - 1; - while (pos >= 0 && (buf[pos] & 0xC0) === 0x80) { pos--; } - // Very small and broken sequence, - // return max, because we should return something anyway. - if (pos < 0) { return max; } + //--- LOAD() --- + put = strm.next_out; + output = strm.output; + left = strm.avail_out; + next = strm.next_in; + input = strm.input; + have = strm.avail_in; + hold = state.hold; + bits = state.bits; + //--- - // If we came to start of buffer - that means buffer is too small, - // return max too. - if (pos === 0) { return max; } + _in = have; + _out = left; + ret = Z_OK; - return (pos + _utf8len[buf[pos]] > max) ? pos : max; -}; + inf_leave: // goto emulation + for (;;) { + switch (state.mode) { + case HEAD: + if (state.wrap === 0) { + state.mode = TYPEDO; + break; + } + //=== NEEDBITS(16); + while (bits < 16) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + if ((state.wrap & 2) && hold === 0x8b1f) { /* gzip header */ + if (state.wbits === 0) { + state.wbits = 15; + } + state.check = 0/*crc32(0L, Z_NULL, 0)*/; + //=== CRC2(state.check, hold); + hbuf[0] = hold & 0xff; + hbuf[1] = (hold >>> 8) & 0xff; + state.check = crc32(state.check, hbuf, 2, 0); + //===// -},{}],70:[function(require,module,exports){ -'use strict'; + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + state.mode = FLAGS; + break; + } + if (state.head) { + state.head.done = false; + } + if (!(state.wrap & 1) || /* check if zlib header allowed */ + (((hold & 0xff)/*BITS(8)*/ << 8) + (hold >> 8)) % 31) { + strm.msg = 'incorrect header check'; + state.mode = BAD; + break; + } + if ((hold & 0x0f)/*BITS(4)*/ !== Z_DEFLATED) { + strm.msg = 'unknown compression method'; + state.mode = BAD; + break; + } + //--- DROPBITS(4) ---// + hold >>>= 4; + bits -= 4; + //---// + len = (hold & 0x0f)/*BITS(4)*/ + 8; + if (state.wbits === 0) { + state.wbits = len; + } + if (len > 15 || len > state.wbits) { + strm.msg = 'invalid window size'; + state.mode = BAD; + break; + } -// Note: adler32 takes 12% for level 0 and 2% for level 6. -// It isn't worth it to make additional optimizations as in original. -// Small size is preferable. - -// (C) 1995-2013 Jean-loup Gailly and Mark Adler -// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -const adler32 = (adler, buf, len, pos) => { - let s1 = (adler & 0xffff) |0, - s2 = ((adler >>> 16) & 0xffff) |0, - n = 0; - - while (len !== 0) { - // Set limit ~ twice less than 5552, to keep - // s2 in 31-bits, because we force signed ints. - // in other case %= will fail. - n = len > 2000 ? 2000 : len; - len -= n; - - do { - s1 = (s1 + buf[pos++]) |0; - s2 = (s2 + s1) |0; - } while (--n); - - s1 %= 65521; - s2 %= 65521; - } - - return (s1 | (s2 << 16)) |0; -}; + // !!! pako patch. Force use `options.windowBits` if passed. + // Required to always use max window size by default. + state.dmax = 1 << state.wbits; + //state.dmax = 1 << len; + state.flags = 0; /* indicate zlib header */ + //Tracev((stderr, "inflate: zlib header ok\n")); + strm.adler = state.check = 1/*adler32(0L, Z_NULL, 0)*/; + state.mode = hold & 0x200 ? DICTID : TYPE; + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + break; + case FLAGS: + //=== NEEDBITS(16); */ + while (bits < 16) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + state.flags = hold; + if ((state.flags & 0xff) !== Z_DEFLATED) { + strm.msg = 'unknown compression method'; + state.mode = BAD; + break; + } + if (state.flags & 0xe000) { + strm.msg = 'unknown header flags set'; + state.mode = BAD; + break; + } + if (state.head) { + state.head.text = ((hold >> 8) & 1); + } + if ((state.flags & 0x0200) && (state.wrap & 4)) { + //=== CRC2(state.check, hold); + hbuf[0] = hold & 0xff; + hbuf[1] = (hold >>> 8) & 0xff; + state.check = crc32(state.check, hbuf, 2, 0); + //===// + } + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + state.mode = TIME; + /* falls through */ + case TIME: + //=== NEEDBITS(32); */ + while (bits < 32) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + if (state.head) { + state.head.time = hold; + } + if ((state.flags & 0x0200) && (state.wrap & 4)) { + //=== CRC4(state.check, hold) + hbuf[0] = hold & 0xff; + hbuf[1] = (hold >>> 8) & 0xff; + hbuf[2] = (hold >>> 16) & 0xff; + hbuf[3] = (hold >>> 24) & 0xff; + state.check = crc32(state.check, hbuf, 4, 0); + //=== + } + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + state.mode = OS; + /* falls through */ + case OS: + //=== NEEDBITS(16); */ + while (bits < 16) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + if (state.head) { + state.head.xflags = (hold & 0xff); + state.head.os = (hold >> 8); + } + if ((state.flags & 0x0200) && (state.wrap & 4)) { + //=== CRC2(state.check, hold); + hbuf[0] = hold & 0xff; + hbuf[1] = (hold >>> 8) & 0xff; + state.check = crc32(state.check, hbuf, 2, 0); + //===// + } + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + state.mode = EXLEN; + /* falls through */ + case EXLEN: + if (state.flags & 0x0400) { + //=== NEEDBITS(16); */ + while (bits < 16) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + state.length = hold; + if (state.head) { + state.head.extra_len = hold; + } + if ((state.flags & 0x0200) && (state.wrap & 4)) { + //=== CRC2(state.check, hold); + hbuf[0] = hold & 0xff; + hbuf[1] = (hold >>> 8) & 0xff; + state.check = crc32(state.check, hbuf, 2, 0); + //===// + } + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + } + else if (state.head) { + state.head.extra = null/*Z_NULL*/; + } + state.mode = EXTRA; + /* falls through */ + case EXTRA: + if (state.flags & 0x0400) { + copy = state.length; + if (copy > have) { copy = have; } + if (copy) { + if (state.head) { + len = state.head.extra_len - state.length; + if (!state.head.extra) { + // Use untyped array for more convenient processing later + state.head.extra = new Uint8Array(state.head.extra_len); + } + state.head.extra.set( + input.subarray( + next, + // extra field is limited to 65536 bytes + // - no need for additional size check + next + copy + ), + /*len + copy > state.head.extra_max - len ? state.head.extra_max : copy,*/ + len + ); + //zmemcpy(state.head.extra + len, next, + // len + copy > state.head.extra_max ? + // state.head.extra_max - len : copy); + } + if ((state.flags & 0x0200) && (state.wrap & 4)) { + state.check = crc32(state.check, input, copy, next); + } + have -= copy; + next += copy; + state.length -= copy; + } + if (state.length) { break inf_leave; } + } + state.length = 0; + state.mode = NAME; + /* falls through */ + case NAME: + if (state.flags & 0x0800) { + if (have === 0) { break inf_leave; } + copy = 0; + do { + // TODO: 2 or 1 bytes? + len = input[next + copy++]; + /* use constant limit because in js we should not preallocate memory */ + if (state.head && len && + (state.length < 65536 /*state.head.name_max*/)) { + state.head.name += String.fromCharCode(len); + } + } while (len && copy < have); -module.exports = adler32; + if ((state.flags & 0x0200) && (state.wrap & 4)) { + state.check = crc32(state.check, input, copy, next); + } + have -= copy; + next += copy; + if (len) { break inf_leave; } + } + else if (state.head) { + state.head.name = null; + } + state.length = 0; + state.mode = COMMENT; + /* falls through */ + case COMMENT: + if (state.flags & 0x1000) { + if (have === 0) { break inf_leave; } + copy = 0; + do { + len = input[next + copy++]; + /* use constant limit because in js we should not preallocate memory */ + if (state.head && len && + (state.length < 65536 /*state.head.comm_max*/)) { + state.head.comment += String.fromCharCode(len); + } + } while (len && copy < have); + if ((state.flags & 0x0200) && (state.wrap & 4)) { + state.check = crc32(state.check, input, copy, next); + } + have -= copy; + next += copy; + if (len) { break inf_leave; } + } + else if (state.head) { + state.head.comment = null; + } + state.mode = HCRC; + /* falls through */ + case HCRC: + if (state.flags & 0x0200) { + //=== NEEDBITS(16); */ + while (bits < 16) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + if ((state.wrap & 4) && hold !== (state.check & 0xffff)) { + strm.msg = 'header crc mismatch'; + state.mode = BAD; + break; + } + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + } + if (state.head) { + state.head.hcrc = ((state.flags >> 9) & 1); + state.head.done = true; + } + strm.adler = state.check = 0; + state.mode = TYPE; + break; + case DICTID: + //=== NEEDBITS(32); */ + while (bits < 32) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + strm.adler = state.check = zswap32(hold); + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + state.mode = DICT; + /* falls through */ + case DICT: + if (state.havedict === 0) { + //--- RESTORE() --- + strm.next_out = put; + strm.avail_out = left; + strm.next_in = next; + strm.avail_in = have; + state.hold = hold; + state.bits = bits; + //--- + return Z_NEED_DICT; + } + strm.adler = state.check = 1/*adler32(0L, Z_NULL, 0)*/; + state.mode = TYPE; + /* falls through */ + case TYPE: + if (flush === Z_BLOCK || flush === Z_TREES) { break inf_leave; } + /* falls through */ + case TYPEDO: + if (state.last) { + //--- BYTEBITS() ---// + hold >>>= bits & 7; + bits -= bits & 7; + //---// + state.mode = CHECK; + break; + } + //=== NEEDBITS(3); */ + while (bits < 3) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + state.last = (hold & 0x01)/*BITS(1)*/; + //--- DROPBITS(1) ---// + hold >>>= 1; + bits -= 1; + //---// -},{}],71:[function(require,module,exports){ -'use strict'; + switch ((hold & 0x03)/*BITS(2)*/) { + case 0: /* stored block */ + //Tracev((stderr, "inflate: stored block%s\n", + // state.last ? " (last)" : "")); + state.mode = STORED; + break; + case 1: /* fixed block */ + fixedtables(state); + //Tracev((stderr, "inflate: fixed codes block%s\n", + // state.last ? " (last)" : "")); + state.mode = LEN_; /* decode codes */ + if (flush === Z_TREES) { + //--- DROPBITS(2) ---// + hold >>>= 2; + bits -= 2; + //---// + break inf_leave; + } + break; + case 2: /* dynamic block */ + //Tracev((stderr, "inflate: dynamic codes block%s\n", + // state.last ? " (last)" : "")); + state.mode = TABLE; + break; + case 3: + strm.msg = 'invalid block type'; + state.mode = BAD; + } + //--- DROPBITS(2) ---// + hold >>>= 2; + bits -= 2; + //---// + break; + case STORED: + //--- BYTEBITS() ---// /* go to byte boundary */ + hold >>>= bits & 7; + bits -= bits & 7; + //---// + //=== NEEDBITS(32); */ + while (bits < 32) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + if ((hold & 0xffff) !== ((hold >>> 16) ^ 0xffff)) { + strm.msg = 'invalid stored block lengths'; + state.mode = BAD; + break; + } + state.length = hold & 0xffff; + //Tracev((stderr, "inflate: stored length %u\n", + // state.length)); + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + state.mode = COPY_; + if (flush === Z_TREES) { break inf_leave; } + /* falls through */ + case COPY_: + state.mode = COPY; + /* falls through */ + case COPY: + copy = state.length; + if (copy) { + if (copy > have) { copy = have; } + if (copy > left) { copy = left; } + if (copy === 0) { break inf_leave; } + //--- zmemcpy(put, next, copy); --- + output.set(input.subarray(next, next + copy), put); + //---// + have -= copy; + next += copy; + left -= copy; + put += copy; + state.length -= copy; + break; + } + //Tracev((stderr, "inflate: stored end\n")); + state.mode = TYPE; + break; + case TABLE: + //=== NEEDBITS(14); */ + while (bits < 14) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + state.nlen = (hold & 0x1f)/*BITS(5)*/ + 257; + //--- DROPBITS(5) ---// + hold >>>= 5; + bits -= 5; + //---// + state.ndist = (hold & 0x1f)/*BITS(5)*/ + 1; + //--- DROPBITS(5) ---// + hold >>>= 5; + bits -= 5; + //---// + state.ncode = (hold & 0x0f)/*BITS(4)*/ + 4; + //--- DROPBITS(4) ---// + hold >>>= 4; + bits -= 4; + //---// +//#ifndef PKZIP_BUG_WORKAROUND + if (state.nlen > 286 || state.ndist > 30) { + strm.msg = 'too many length or distance symbols'; + state.mode = BAD; + break; + } +//#endif + //Tracev((stderr, "inflate: table sizes ok\n")); + state.have = 0; + state.mode = LENLENS; + /* falls through */ + case LENLENS: + while (state.have < state.ncode) { + //=== NEEDBITS(3); + while (bits < 3) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + state.lens[order[state.have++]] = (hold & 0x07);//BITS(3); + //--- DROPBITS(3) ---// + hold >>>= 3; + bits -= 3; + //---// + } + while (state.have < 19) { + state.lens[order[state.have++]] = 0; + } + // We have separate tables & no pointers. 2 commented lines below not needed. + //state.next = state.codes; + //state.lencode = state.next; + // Switch to use dynamic table + state.lencode = state.lendyn; + state.lenbits = 7; -// (C) 1995-2013 Jean-loup Gailly and Mark Adler -// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. + opts = { bits: state.lenbits }; + ret = inflate_table(CODES, state.lens, 0, 19, state.lencode, 0, state.work, opts); + state.lenbits = opts.bits; -module.exports = { + if (ret) { + strm.msg = 'invalid code lengths set'; + state.mode = BAD; + break; + } + //Tracev((stderr, "inflate: code lengths ok\n")); + state.have = 0; + state.mode = CODELENS; + /* falls through */ + case CODELENS: + while (state.have < state.nlen + state.ndist) { + for (;;) { + here = state.lencode[hold & ((1 << state.lenbits) - 1)];/*BITS(state.lenbits)*/ + here_bits = here >>> 24; + here_op = (here >>> 16) & 0xff; + here_val = here & 0xffff; - /* Allowed flush values; see deflate() and inflate() below for details */ - Z_NO_FLUSH: 0, - Z_PARTIAL_FLUSH: 1, - Z_SYNC_FLUSH: 2, - Z_FULL_FLUSH: 3, - Z_FINISH: 4, - Z_BLOCK: 5, - Z_TREES: 6, - - /* Return codes for the compression/decompression functions. Negative values - * are errors, positive values are used for special but normal events. - */ - Z_OK: 0, - Z_STREAM_END: 1, - Z_NEED_DICT: 2, - Z_ERRNO: -1, - Z_STREAM_ERROR: -2, - Z_DATA_ERROR: -3, - Z_MEM_ERROR: -4, - Z_BUF_ERROR: -5, - //Z_VERSION_ERROR: -6, - - /* compression levels */ - Z_NO_COMPRESSION: 0, - Z_BEST_SPEED: 1, - Z_BEST_COMPRESSION: 9, - Z_DEFAULT_COMPRESSION: -1, - - - Z_FILTERED: 1, - Z_HUFFMAN_ONLY: 2, - Z_RLE: 3, - Z_FIXED: 4, - Z_DEFAULT_STRATEGY: 0, - - /* Possible values of the data_type field (though see inflate()) */ - Z_BINARY: 0, - Z_TEXT: 1, - //Z_ASCII: 1, // = Z_TEXT (deprecated) - Z_UNKNOWN: 2, - - /* The deflate compression method */ - Z_DEFLATED: 8 - //Z_NULL: null // Use -1 or null inline, depending on var type -}; - -},{}],72:[function(require,module,exports){ -'use strict'; - -// Note: we can't get significant speed boost here. -// So write code to minimize size - no pregenerated tables -// and array tools dependencies. - -// (C) 1995-2013 Jean-loup Gailly and Mark Adler -// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. + if ((here_bits) <= bits) { break; } + //--- PULLBYTE() ---// + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + //---// + } + if (here_val < 16) { + //--- DROPBITS(here.bits) ---// + hold >>>= here_bits; + bits -= here_bits; + //---// + state.lens[state.have++] = here_val; + } + else { + if (here_val === 16) { + //=== NEEDBITS(here.bits + 2); + n = here_bits + 2; + while (bits < n) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + //--- DROPBITS(here.bits) ---// + hold >>>= here_bits; + bits -= here_bits; + //---// + if (state.have === 0) { + strm.msg = 'invalid bit length repeat'; + state.mode = BAD; + break; + } + len = state.lens[state.have - 1]; + copy = 3 + (hold & 0x03);//BITS(2); + //--- DROPBITS(2) ---// + hold >>>= 2; + bits -= 2; + //---// + } + else if (here_val === 17) { + //=== NEEDBITS(here.bits + 3); + n = here_bits + 3; + while (bits < n) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + //--- DROPBITS(here.bits) ---// + hold >>>= here_bits; + bits -= here_bits; + //---// + len = 0; + copy = 3 + (hold & 0x07);//BITS(3); + //--- DROPBITS(3) ---// + hold >>>= 3; + bits -= 3; + //---// + } + else { + //=== NEEDBITS(here.bits + 7); + n = here_bits + 7; + while (bits < n) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + //--- DROPBITS(here.bits) ---// + hold >>>= here_bits; + bits -= here_bits; + //---// + len = 0; + copy = 11 + (hold & 0x7f);//BITS(7); + //--- DROPBITS(7) ---// + hold >>>= 7; + bits -= 7; + //---// + } + if (state.have + copy > state.nlen + state.ndist) { + strm.msg = 'invalid bit length repeat'; + state.mode = BAD; + break; + } + while (copy--) { + state.lens[state.have++] = len; + } + } + } -// Use ordinary array, since untyped makes no boost here -const makeTable = () => { - let c, table = []; + /* handle error breaks in while */ + if (state.mode === BAD) { break; } - for (var n = 0; n < 256; n++) { - c = n; - for (var k = 0; k < 8; k++) { - c = ((c & 1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1)); - } - table[n] = c; - } + /* check for end-of-block code (better have one) */ + if (state.lens[256] === 0) { + strm.msg = 'invalid code -- missing end-of-block'; + state.mode = BAD; + break; + } - return table; -}; + /* build code tables -- note: do not change the lenbits or distbits + values here (9 and 6) without reading the comments in inftrees.h + concerning the ENOUGH constants, which depend on those values */ + state.lenbits = 9; -// Create table on load. Just 255 signed longs. Not a problem. -const crcTable = new Uint32Array(makeTable()); + opts = { bits: state.lenbits }; + ret = inflate_table(LENS, state.lens, 0, state.nlen, state.lencode, 0, state.work, opts); + // We have separate tables & no pointers. 2 commented lines below not needed. + // state.next_index = opts.table_index; + state.lenbits = opts.bits; + // state.lencode = state.next; + if (ret) { + strm.msg = 'invalid literal/lengths set'; + state.mode = BAD; + break; + } -const crc32 = (crc, buf, len, pos) => { - const t = crcTable; - const end = pos + len; + state.distbits = 6; + //state.distcode.copy(state.codes); + // Switch to use dynamic table + state.distcode = state.distdyn; + opts = { bits: state.distbits }; + ret = inflate_table(DISTS, state.lens, state.nlen, state.ndist, state.distcode, 0, state.work, opts); + // We have separate tables & no pointers. 2 commented lines below not needed. + // state.next_index = opts.table_index; + state.distbits = opts.bits; + // state.distcode = state.next; - crc ^= -1; + if (ret) { + strm.msg = 'invalid distances set'; + state.mode = BAD; + break; + } + //Tracev((stderr, 'inflate: codes ok\n')); + state.mode = LEN_; + if (flush === Z_TREES) { break inf_leave; } + /* falls through */ + case LEN_: + state.mode = LEN; + /* falls through */ + case LEN: + if (have >= 6 && left >= 258) { + //--- RESTORE() --- + strm.next_out = put; + strm.avail_out = left; + strm.next_in = next; + strm.avail_in = have; + state.hold = hold; + state.bits = bits; + //--- + inflate_fast(strm, _out); + //--- LOAD() --- + put = strm.next_out; + output = strm.output; + left = strm.avail_out; + next = strm.next_in; + input = strm.input; + have = strm.avail_in; + hold = state.hold; + bits = state.bits; + //--- - for (let i = pos; i < end; i++) { - crc = (crc >>> 8) ^ t[(crc ^ buf[i]) & 0xFF]; - } + if (state.mode === TYPE) { + state.back = -1; + } + break; + } + state.back = 0; + for (;;) { + here = state.lencode[hold & ((1 << state.lenbits) - 1)]; /*BITS(state.lenbits)*/ + here_bits = here >>> 24; + here_op = (here >>> 16) & 0xff; + here_val = here & 0xffff; - return (crc ^ (-1)); // >>> 0; -}; + if (here_bits <= bits) { break; } + //--- PULLBYTE() ---// + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + //---// + } + if (here_op && (here_op & 0xf0) === 0) { + last_bits = here_bits; + last_op = here_op; + last_val = here_val; + for (;;) { + here = state.lencode[last_val + + ((hold & ((1 << (last_bits + last_op)) - 1))/*BITS(last.bits + last.op)*/ >> last_bits)]; + here_bits = here >>> 24; + here_op = (here >>> 16) & 0xff; + here_val = here & 0xffff; + if ((last_bits + here_bits) <= bits) { break; } + //--- PULLBYTE() ---// + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + //---// + } + //--- DROPBITS(last.bits) ---// + hold >>>= last_bits; + bits -= last_bits; + //---// + state.back += last_bits; + } + //--- DROPBITS(here.bits) ---// + hold >>>= here_bits; + bits -= here_bits; + //---// + state.back += here_bits; + state.length = here_val; + if (here_op === 0) { + //Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? + // "inflate: literal '%c'\n" : + // "inflate: literal 0x%02x\n", here.val)); + state.mode = LIT; + break; + } + if (here_op & 32) { + //Tracevv((stderr, "inflate: end of block\n")); + state.back = -1; + state.mode = TYPE; + break; + } + if (here_op & 64) { + strm.msg = 'invalid literal/length code'; + state.mode = BAD; + break; + } + state.extra = here_op & 15; + state.mode = LENEXT; + /* falls through */ + case LENEXT: + if (state.extra) { + //=== NEEDBITS(state.extra); + n = state.extra; + while (bits < n) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + state.length += hold & ((1 << state.extra) - 1)/*BITS(state.extra)*/; + //--- DROPBITS(state.extra) ---// + hold >>>= state.extra; + bits -= state.extra; + //---// + state.back += state.extra; + } + //Tracevv((stderr, "inflate: length %u\n", state.length)); + state.was = state.length; + state.mode = DIST; + /* falls through */ + case DIST: + for (;;) { + here = state.distcode[hold & ((1 << state.distbits) - 1)];/*BITS(state.distbits)*/ + here_bits = here >>> 24; + here_op = (here >>> 16) & 0xff; + here_val = here & 0xffff; -module.exports = crc32; + if ((here_bits) <= bits) { break; } + //--- PULLBYTE() ---// + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + //---// + } + if ((here_op & 0xf0) === 0) { + last_bits = here_bits; + last_op = here_op; + last_val = here_val; + for (;;) { + here = state.distcode[last_val + + ((hold & ((1 << (last_bits + last_op)) - 1))/*BITS(last.bits + last.op)*/ >> last_bits)]; + here_bits = here >>> 24; + here_op = (here >>> 16) & 0xff; + here_val = here & 0xffff; -},{}],73:[function(require,module,exports){ -'use strict'; + if ((last_bits + here_bits) <= bits) { break; } + //--- PULLBYTE() ---// + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + //---// + } + //--- DROPBITS(last.bits) ---// + hold >>>= last_bits; + bits -= last_bits; + //---// + state.back += last_bits; + } + //--- DROPBITS(here.bits) ---// + hold >>>= here_bits; + bits -= here_bits; + //---// + state.back += here_bits; + if (here_op & 64) { + strm.msg = 'invalid distance code'; + state.mode = BAD; + break; + } + state.offset = here_val; + state.extra = (here_op) & 15; + state.mode = DISTEXT; + /* falls through */ + case DISTEXT: + if (state.extra) { + //=== NEEDBITS(state.extra); + n = state.extra; + while (bits < n) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + state.offset += hold & ((1 << state.extra) - 1)/*BITS(state.extra)*/; + //--- DROPBITS(state.extra) ---// + hold >>>= state.extra; + bits -= state.extra; + //---// + state.back += state.extra; + } +//#ifdef INFLATE_STRICT + if (state.offset > state.dmax) { + strm.msg = 'invalid distance too far back'; + state.mode = BAD; + break; + } +//#endif + //Tracevv((stderr, "inflate: distance %u\n", state.offset)); + state.mode = MATCH; + /* falls through */ + case MATCH: + if (left === 0) { break inf_leave; } + copy = _out - left; + if (state.offset > copy) { /* copy from window */ + copy = state.offset - copy; + if (copy > state.whave) { + if (state.sane) { + strm.msg = 'invalid distance too far back'; + state.mode = BAD; + break; + } +// (!) This block is disabled in zlib defaults, +// don't enable it for binary compatibility +//#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR +// Trace((stderr, "inflate.c too far\n")); +// copy -= state.whave; +// if (copy > state.length) { copy = state.length; } +// if (copy > left) { copy = left; } +// left -= copy; +// state.length -= copy; +// do { +// output[put++] = 0; +// } while (--copy); +// if (state.length === 0) { state.mode = LEN; } +// break; +//#endif + } + if (copy > state.wnext) { + copy -= state.wnext; + from = state.wsize - copy; + } + else { + from = state.wnext - copy; + } + if (copy > state.length) { copy = state.length; } + from_source = state.window; + } + else { /* copy from output */ + from_source = output; + from = put - state.offset; + copy = state.length; + } + if (copy > left) { copy = left; } + left -= copy; + state.length -= copy; + do { + output[put++] = from_source[from++]; + } while (--copy); + if (state.length === 0) { state.mode = LEN; } + break; + case LIT: + if (left === 0) { break inf_leave; } + output[put++] = state.length; + left--; + state.mode = LEN; + break; + case CHECK: + if (state.wrap) { + //=== NEEDBITS(32); + while (bits < 32) { + if (have === 0) { break inf_leave; } + have--; + // Use '|' instead of '+' to make sure that result is signed + hold |= input[next++] << bits; + bits += 8; + } + //===// + _out -= left; + strm.total_out += _out; + state.total += _out; + if ((state.wrap & 4) && _out) { + strm.adler = state.check = + /*UPDATE_CHECK(state.check, put - _out, _out);*/ + (state.flags ? crc32(state.check, output, _out, put - _out) : adler32(state.check, output, _out, put - _out)); -// (C) 1995-2013 Jean-loup Gailly and Mark Adler -// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -const { _tr_init, _tr_stored_block, _tr_flush_block, _tr_tally, _tr_align } = require('./trees'); -const adler32 = require('./adler32'); -const crc32 = require('./crc32'); -const msg = require('./messages'); - -/* Public constants ==========================================================*/ -/* ===========================================================================*/ - -const { - Z_NO_FLUSH, Z_PARTIAL_FLUSH, Z_FULL_FLUSH, Z_FINISH, Z_BLOCK, - Z_OK, Z_STREAM_END, Z_STREAM_ERROR, Z_DATA_ERROR, Z_BUF_ERROR, - Z_DEFAULT_COMPRESSION, - Z_FILTERED, Z_HUFFMAN_ONLY, Z_RLE, Z_FIXED, Z_DEFAULT_STRATEGY, - Z_UNKNOWN, - Z_DEFLATED -} = require('./constants'); + } + _out = left; + // NB: crc32 stored as signed 32-bit int, zswap32 returns signed too + if ((state.wrap & 4) && (state.flags ? hold : zswap32(hold)) !== state.check) { + strm.msg = 'incorrect data check'; + state.mode = BAD; + break; + } + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + //Tracev((stderr, "inflate: check matches trailer\n")); + } + state.mode = LENGTH; + /* falls through */ + case LENGTH: + if (state.wrap && state.flags) { + //=== NEEDBITS(32); + while (bits < 32) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + if ((state.wrap & 4) && hold !== (state.total & 0xffffffff)) { + strm.msg = 'incorrect length check'; + state.mode = BAD; + break; + } + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + //Tracev((stderr, "inflate: length matches trailer\n")); + } + state.mode = DONE; + /* falls through */ + case DONE: + ret = Z_STREAM_END; + break inf_leave; + case BAD: + ret = Z_DATA_ERROR; + break inf_leave; + case MEM: + return Z_MEM_ERROR; + case SYNC: + /* falls through */ + default: + return Z_STREAM_ERROR; + } + } -/*============================================================================*/ + // inf_leave <- here is real place for "goto inf_leave", emulated via "break inf_leave" + /* + Return from inflate(), updating the total counts and the check value. + If there was no progress during the inflate() call, return a buffer + error. Call updatewindow() to create and/or update the window state. + Note: a memory error from inflate() is non-recoverable. + */ -const MAX_MEM_LEVEL = 9; -/* Maximum value for memLevel in deflateInit2 */ -const MAX_WBITS = 15; -/* 32K LZ77 window */ -const DEF_MEM_LEVEL = 8; + //--- RESTORE() --- + strm.next_out = put; + strm.avail_out = left; + strm.next_in = next; + strm.avail_in = have; + state.hold = hold; + state.bits = bits; + //--- + if (state.wsize || (_out !== strm.avail_out && state.mode < BAD && + (state.mode < CHECK || flush !== Z_FINISH))) { + if (updatewindow(strm, strm.output, strm.next_out, _out - strm.avail_out)) { + state.mode = MEM; + return Z_MEM_ERROR; + } + } + _in -= strm.avail_in; + _out -= strm.avail_out; + strm.total_in += _in; + strm.total_out += _out; + state.total += _out; + if ((state.wrap & 4) && _out) { + strm.adler = state.check = /*UPDATE_CHECK(state.check, strm.next_out - _out, _out);*/ + (state.flags ? crc32(state.check, output, _out, strm.next_out - _out) : adler32(state.check, output, _out, strm.next_out - _out)); + } + strm.data_type = state.bits + (state.last ? 64 : 0) + + (state.mode === TYPE ? 128 : 0) + + (state.mode === LEN_ || state.mode === COPY_ ? 256 : 0); + if (((_in === 0 && _out === 0) || flush === Z_FINISH) && ret === Z_OK) { + ret = Z_BUF_ERROR; + } + return ret; +}; -const LENGTH_CODES = 29; -/* number of length codes, not counting the special END_BLOCK code */ -const LITERALS = 256; -/* number of literal bytes 0..255 */ -const L_CODES = LITERALS + 1 + LENGTH_CODES; -/* number of Literal or Length codes, including the END_BLOCK code */ -const D_CODES = 30; -/* number of distance codes */ -const BL_CODES = 19; -/* number of codes used to transfer the bit lengths */ -const HEAP_SIZE = 2 * L_CODES + 1; -/* maximum heap size */ -const MAX_BITS = 15; -/* All codes must not exceed MAX_BITS bits */ -const MIN_MATCH = 3; -const MAX_MATCH = 258; -const MIN_LOOKAHEAD = (MAX_MATCH + MIN_MATCH + 1); +const inflateEnd = (strm) => { -const PRESET_DICT = 0x20; + if (inflateStateCheck(strm)) { + return Z_STREAM_ERROR; + } -const INIT_STATE = 42; -const EXTRA_STATE = 69; -const NAME_STATE = 73; -const COMMENT_STATE = 91; -const HCRC_STATE = 103; -const BUSY_STATE = 113; -const FINISH_STATE = 666; + let state = strm.state; + if (state.window) { + state.window = null; + } + strm.state = null; + return Z_OK; +}; -const BS_NEED_MORE = 1; /* block not completed, need more input or more output */ -const BS_BLOCK_DONE = 2; /* block flush performed */ -const BS_FINISH_STARTED = 3; /* finish started, need only more output at next deflate */ -const BS_FINISH_DONE = 4; /* finish done, accept no more input or output */ -const OS_CODE = 0x03; // Unix :) . Don't detect, use this default. +const inflateGetHeader = (strm, head) => { -const err = (strm, errorCode) => { - strm.msg = msg[errorCode]; - return errorCode; -}; + /* check state */ + if (inflateStateCheck(strm)) { return Z_STREAM_ERROR; } + const state = strm.state; + if ((state.wrap & 2) === 0) { return Z_STREAM_ERROR; } -const rank = (f) => { - return ((f) << 1) - ((f) > 4 ? 9 : 0); + /* save header structure */ + state.head = head; + head.done = false; + return Z_OK; }; -const zero = (buf) => { - let len = buf.length; while (--len >= 0) { buf[len] = 0; } -}; +const inflateSetDictionary = (strm, dictionary) => { + const dictLength = dictionary.length; -/* eslint-disable new-cap */ -let HASH_ZLIB = (s, prev, data) => ((prev << s.hash_shift) ^ data) & s.hash_mask; -// This hash causes less collisions, https://github.com/nodeca/pako/issues/135 -// But breaks binary compatibility -//let HASH_FAST = (s, prev, data) => ((prev << 8) + (prev >> 8) + (data << 4)) & s.hash_mask; -let HASH = HASH_ZLIB; + let state; + let dictid; + let ret; -/* ========================================================================= - * Flush as much pending output as possible. All deflate() output goes - * through this function so some applications may wish to modify it - * to avoid allocating a large strm->output buffer and copying into it. - * (See also read_buf()). - */ -const flush_pending = (strm) => { - const s = strm.state; + /* check state */ + if (inflateStateCheck(strm)) { return Z_STREAM_ERROR; } + state = strm.state; - //_tr_flush_bits(s); - let len = s.pending; - if (len > strm.avail_out) { - len = strm.avail_out; + if (state.wrap !== 0 && state.mode !== DICT) { + return Z_STREAM_ERROR; } - if (len === 0) { return; } - strm.output.set(s.pending_buf.subarray(s.pending_out, s.pending_out + len), strm.next_out); - strm.next_out += len; - s.pending_out += len; - strm.total_out += len; - strm.avail_out -= len; - s.pending -= len; - if (s.pending === 0) { - s.pending_out = 0; + /* check for correct dictionary identifier */ + if (state.mode === DICT) { + dictid = 1; /* adler32(0, null, 0)*/ + /* dictid = adler32(dictid, dictionary, dictLength); */ + dictid = adler32(dictid, dictionary, dictLength, 0); + if (dictid !== state.check) { + return Z_DATA_ERROR; + } + } + /* copy dictionary to window using updatewindow(), which will amend the + existing dictionary if appropriate */ + ret = updatewindow(strm, dictionary, dictLength, dictLength); + if (ret) { + state.mode = MEM; + return Z_MEM_ERROR; } + state.havedict = 1; + // Tracev((stderr, "inflate: dictionary set\n")); + return Z_OK; }; -const flush_block_only = (s, last) => { - _tr_flush_block(s, (s.block_start >= 0 ? s.block_start : -1), s.strstart - s.block_start, last); - s.block_start = s.strstart; - flush_pending(s.strm); -}; +module.exports.inflateReset = inflateReset; +module.exports.inflateReset2 = inflateReset2; +module.exports.inflateResetKeep = inflateResetKeep; +module.exports.inflateInit = inflateInit; +module.exports.inflateInit2 = inflateInit2; +module.exports.inflate = inflate; +module.exports.inflateEnd = inflateEnd; +module.exports.inflateGetHeader = inflateGetHeader; +module.exports.inflateSetDictionary = inflateSetDictionary; +module.exports.inflateInfo = 'pako inflate (from Nodeca project)'; +/* Not implemented +module.exports.inflateCodesUsed = inflateCodesUsed; +module.exports.inflateCopy = inflateCopy; +module.exports.inflateGetDictionary = inflateGetDictionary; +module.exports.inflateMark = inflateMark; +module.exports.inflatePrime = inflatePrime; +module.exports.inflateSync = inflateSync; +module.exports.inflateSyncPoint = inflateSyncPoint; +module.exports.inflateUndermine = inflateUndermine; +module.exports.inflateValidate = inflateValidate; +*/ -const put_byte = (s, b) => { - s.pending_buf[s.pending++] = b; -}; +},{"./adler32":70,"./constants":71,"./crc32":72,"./inffast":75,"./inftrees":77}],77:[function(require,module,exports){ +'use strict'; +// (C) 1995-2013 Jean-loup Gailly and Mark Adler +// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. -/* ========================================================================= - * Put a short in the pending buffer. The 16-bit value is put in MSB order. - * IN assertion: the stream state is correct and there is enough room in - * pending_buf. - */ -const putShortMSB = (s, b) => { +const MAXBITS = 15; +const ENOUGH_LENS = 852; +const ENOUGH_DISTS = 592; +//const ENOUGH = (ENOUGH_LENS+ENOUGH_DISTS); - // put_byte(s, (Byte)(b >> 8)); -// put_byte(s, (Byte)(b & 0xff)); - s.pending_buf[s.pending++] = (b >>> 8) & 0xff; - s.pending_buf[s.pending++] = b & 0xff; -}; +const CODES = 0; +const LENS = 1; +const DISTS = 2; +const lbase = new Uint16Array([ /* Length codes 257..285 base */ + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, + 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0 +]); -/* =========================================================================== - * Read a new buffer from the current input stream, update the adler32 - * and total number of bytes read. All deflate() input goes through - * this function so some applications may wish to modify it to avoid - * allocating a large strm->input buffer and copying from it. - * (See also flush_pending()). - */ -const read_buf = (strm, buf, start, size) => { +const lext = new Uint8Array([ /* Length codes 257..285 extra */ + 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, + 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 72, 78 +]); - let len = strm.avail_in; +const dbase = new Uint16Array([ /* Distance codes 0..29 base */ + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, + 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, + 8193, 12289, 16385, 24577, 0, 0 +]); - if (len > size) { len = size; } - if (len === 0) { return 0; } +const dext = new Uint8Array([ /* Distance codes 0..29 extra */ + 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, + 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, + 28, 28, 29, 29, 64, 64 +]); - strm.avail_in -= len; +const inflate_table = (type, lens, lens_index, codes, table, table_index, work, opts) => +{ + const bits = opts.bits; + //here = opts.here; /* table entry for duplication */ - // zmemcpy(buf, strm->next_in, len); - buf.set(strm.input.subarray(strm.next_in, strm.next_in + len), start); - if (strm.state.wrap === 1) { - strm.adler = adler32(strm.adler, buf, len, start); - } + let len = 0; /* a code's length in bits */ + let sym = 0; /* index of code symbols */ + let min = 0, max = 0; /* minimum and maximum code lengths */ + let root = 0; /* number of index bits for root table */ + let curr = 0; /* number of index bits for current table */ + let drop = 0; /* code bits to drop for sub-table */ + let left = 0; /* number of prefix codes available */ + let used = 0; /* code entries in table used */ + let huff = 0; /* Huffman code */ + let incr; /* for incrementing code, index */ + let fill; /* index for replicating entries */ + let low; /* low bits for current root entry */ + let mask; /* mask for low root bits */ + let next; /* next available space in table */ + let base = null; /* base value table to use */ +// let shoextra; /* extra bits table to use */ + let match; /* use base and extra for symbol >= match */ + const count = new Uint16Array(MAXBITS + 1); //[MAXBITS+1]; /* number of codes of each length */ + const offs = new Uint16Array(MAXBITS + 1); //[MAXBITS+1]; /* offsets in table for each length */ + let extra = null; - else if (strm.state.wrap === 2) { - strm.adler = crc32(strm.adler, buf, len, start); - } + let here_bits, here_op, here_val; - strm.next_in += len; - strm.total_in += len; + /* + Process a set of code lengths to create a canonical Huffman code. The + code lengths are lens[0..codes-1]. Each length corresponds to the + symbols 0..codes-1. The Huffman code is generated by first sorting the + symbols by length from short to long, and retaining the symbol order + for codes with equal lengths. Then the code starts with all zero bits + for the first code of the shortest length, and the codes are integer + increments for the same length, and zeros are appended as the length + increases. For the deflate format, these bits are stored backwards + from their more natural integer increment ordering, and so when the + decoding tables are built in the large loop below, the integer codes + are incremented backwards. - return len; -}; + This routine assumes, but does not check, that all of the entries in + lens[] are in the range 0..MAXBITS. The caller must assure this. + 1..MAXBITS is interpreted as that code length. zero means that that + symbol does not occur in this code. + The codes are sorted by computing a count of codes for each length, + creating from that a table of starting indices for each length in the + sorted table, and then entering the symbols in order in the sorted + table. The sorted table is work[], with that space being provided by + the caller. -/* =========================================================================== - * Set match_start to the longest match starting at the given string and - * return its length. Matches shorter or equal to prev_length are discarded, - * in which case the result is equal to prev_length and match_start is - * garbage. - * IN assertions: cur_match is the head of the hash chain for the current - * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1 - * OUT assertion: the match length is not greater than s->lookahead. - */ -const longest_match = (s, cur_match) => { + The length counts are used for other purposes as well, i.e. finding + the minimum and maximum length codes, determining if there are any + codes at all, checking for a valid set of lengths, and looking ahead + at length counts to determine sub-table sizes when building the + decoding tables. + */ - let chain_length = s.max_chain_length; /* max hash chain length */ - let scan = s.strstart; /* current string */ - let match; /* matched string */ - let len; /* length of current match */ - let best_len = s.prev_length; /* best match length so far */ - let nice_match = s.nice_match; /* stop if match long enough */ - const limit = (s.strstart > (s.w_size - MIN_LOOKAHEAD)) ? - s.strstart - (s.w_size - MIN_LOOKAHEAD) : 0/*NIL*/; + /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */ + for (len = 0; len <= MAXBITS; len++) { + count[len] = 0; + } + for (sym = 0; sym < codes; sym++) { + count[lens[lens_index + sym]]++; + } - const _win = s.window; // shortcut + /* bound code lengths, force root to be within code lengths */ + root = bits; + for (max = MAXBITS; max >= 1; max--) { + if (count[max] !== 0) { break; } + } + if (root > max) { + root = max; + } + if (max === 0) { /* no symbols to code at all */ + //table.op[opts.table_index] = 64; //here.op = (var char)64; /* invalid code marker */ + //table.bits[opts.table_index] = 1; //here.bits = (var char)1; + //table.val[opts.table_index++] = 0; //here.val = (var short)0; + table[table_index++] = (1 << 24) | (64 << 16) | 0; - const wmask = s.w_mask; - const prev = s.prev; - /* Stop when cur_match becomes <= limit. To simplify the code, - * we prevent matches with the string of window index 0. - */ + //table.op[opts.table_index] = 64; + //table.bits[opts.table_index] = 1; + //table.val[opts.table_index++] = 0; + table[table_index++] = (1 << 24) | (64 << 16) | 0; - const strend = s.strstart + MAX_MATCH; - let scan_end1 = _win[scan + best_len - 1]; - let scan_end = _win[scan + best_len]; + opts.bits = 1; + return 0; /* no symbols, but wait for decoding to report error */ + } + for (min = 1; min < max; min++) { + if (count[min] !== 0) { break; } + } + if (root < min) { + root = min; + } - /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. - * It is easy to get rid of this optimization if necessary. - */ - // Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); + /* check for an over-subscribed or incomplete set of lengths */ + left = 1; + for (len = 1; len <= MAXBITS; len++) { + left <<= 1; + left -= count[len]; + if (left < 0) { + return -1; + } /* over-subscribed */ + } + if (left > 0 && (type === CODES || max !== 1)) { + return -1; /* incomplete set */ + } - /* Do not waste too much time if we already have a good match: */ - if (s.prev_length >= s.good_match) { - chain_length >>= 2; + /* generate offsets into symbol table for each length for sorting */ + offs[1] = 0; + for (len = 1; len < MAXBITS; len++) { + offs[len + 1] = offs[len] + count[len]; } - /* Do not look for matches beyond the end of the input. This is necessary - * to make deflate deterministic. - */ - if (nice_match > s.lookahead) { nice_match = s.lookahead; } - // Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + /* sort symbols by length, by symbol order within each length */ + for (sym = 0; sym < codes; sym++) { + if (lens[lens_index + sym] !== 0) { + work[offs[lens[lens_index + sym]]++] = sym; + } + } - do { - // Assert(cur_match < s->strstart, "no future"); - match = cur_match; + /* + Create and fill in decoding tables. In this loop, the table being + filled is at next and has curr index bits. The code being used is huff + with length len. That code is converted to an index by dropping drop + bits off of the bottom. For codes where len is less than drop + curr, + those top drop + curr - len bits are incremented through all values to + fill the table with replicated entries. - /* Skip to next match if the match length cannot increase - * or if the match length is less than 2. Note that the checks below - * for insufficient lookahead only occur occasionally for performance - * reasons. Therefore uninitialized memory will be accessed, and - * conditional jumps will be made that depend on those values. - * However the length of the match is limited to the lookahead, so - * the output of deflate is not affected by the uninitialized values. - */ + root is the number of index bits for the root table. When len exceeds + root, sub-tables are created pointed to by the root entry with an index + of the low root bits of huff. This is saved in low to check for when a + new sub-table should be started. drop is zero when the root table is + being filled, and drop is root when sub-tables are being filled. - if (_win[match + best_len] !== scan_end || - _win[match + best_len - 1] !== scan_end1 || - _win[match] !== _win[scan] || - _win[++match] !== _win[scan + 1]) { - continue; - } + When a new sub-table is needed, it is necessary to look ahead in the + code lengths to determine what size sub-table is needed. The length + counts are used for this, and so count[] is decremented as codes are + entered in the tables. - /* The check at best_len-1 can be removed because it will be made - * again later. (This heuristic is not always a win.) - * It is not necessary to compare scan[2] and match[2] since they - * are always equal when the other bytes match, given that - * the hash keys are equal and that HASH_BITS >= 8. - */ - scan += 2; - match++; - // Assert(*scan == *match, "match[2]?"); + used keeps track of how many table entries have been allocated from the + provided *table space. It is checked for LENS and DIST tables against + the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in + the initial root table size constants. See the comments in inftrees.h + for more information. - /* We check for insufficient lookahead only every 8th comparison; - * the 256th check will be made at strstart+258. - */ - do { - /*jshint noempty:false*/ - } while (_win[++scan] === _win[++match] && _win[++scan] === _win[++match] && - _win[++scan] === _win[++match] && _win[++scan] === _win[++match] && - _win[++scan] === _win[++match] && _win[++scan] === _win[++match] && - _win[++scan] === _win[++match] && _win[++scan] === _win[++match] && - scan < strend); + sym increments through all symbols, and the loop terminates when + all codes of length max, i.e. all codes, have been processed. This + routine permits incomplete codes, so another loop after this one fills + in the rest of the decoding tables with invalid code markers. + */ - // Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + /* set up for code type */ + // poor man optimization - use if-else instead of switch, + // to avoid deopts in old v8 + if (type === CODES) { + base = extra = work; /* dummy value--not used */ + match = 20; - len = MAX_MATCH - (strend - scan); - scan = strend - MAX_MATCH; + } else if (type === LENS) { + base = lbase; + extra = lext; + match = 257; - if (len > best_len) { - s.match_start = cur_match; - best_len = len; - if (len >= nice_match) { - break; + } else { /* DISTS */ + base = dbase; + extra = dext; + match = 0; + } + + /* initialize opts for loop */ + huff = 0; /* starting code */ + sym = 0; /* starting code symbol */ + len = min; /* starting code length */ + next = table_index; /* current table to fill in */ + curr = root; /* current table index bits */ + drop = 0; /* current bits to drop from code for index */ + low = -1; /* trigger new sub-table when len > root */ + used = 1 << root; /* use root table entries */ + mask = used - 1; /* mask for comparing low */ + + /* check available table space */ + if ((type === LENS && used > ENOUGH_LENS) || + (type === DISTS && used > ENOUGH_DISTS)) { + return 1; + } + + /* process all codes and make table entries */ + for (;;) { + /* create table entry */ + here_bits = len - drop; + if (work[sym] + 1 < match) { + here_op = 0; + here_val = work[sym]; + } + else if (work[sym] >= match) { + here_op = extra[work[sym] - match]; + here_val = base[work[sym] - match]; + } + else { + here_op = 32 + 64; /* end of block */ + here_val = 0; + } + + /* replicate for those indices with low len bits equal to huff */ + incr = 1 << (len - drop); + fill = 1 << curr; + min = fill; /* save offset to next table */ + do { + fill -= incr; + table[next + (huff >> drop) + fill] = (here_bits << 24) | (here_op << 16) | here_val |0; + } while (fill !== 0); + + /* backwards increment the len-bit code huff */ + incr = 1 << (len - 1); + while (huff & incr) { + incr >>= 1; + } + if (incr !== 0) { + huff &= incr - 1; + huff += incr; + } else { + huff = 0; + } + + /* go to next symbol, update count, len */ + sym++; + if (--count[len] === 0) { + if (len === max) { break; } + len = lens[lens_index + work[sym]]; + } + + /* create new sub-table if needed */ + if (len > root && (huff & mask) !== low) { + /* if first time, transition to sub-tables */ + if (drop === 0) { + drop = root; } - scan_end1 = _win[scan + best_len - 1]; - scan_end = _win[scan + best_len]; + + /* increment past last table */ + next += min; /* here min is 1 << curr */ + + /* determine length of next table */ + curr = len - drop; + left = 1 << curr; + while (curr + drop < max) { + left -= count[curr + drop]; + if (left <= 0) { break; } + curr++; + left <<= 1; + } + + /* check for enough space */ + used += 1 << curr; + if ((type === LENS && used > ENOUGH_LENS) || + (type === DISTS && used > ENOUGH_DISTS)) { + return 1; + } + + /* point entry in root table to sub-table */ + low = huff & mask; + /*table.op[low] = curr; + table.bits[low] = root; + table.val[low] = next - opts.table_index;*/ + table[low] = (root << 24) | (curr << 16) | (next - table_index) |0; } - } while ((cur_match = prev[cur_match & wmask]) > limit && --chain_length !== 0); + } - if (best_len <= s.lookahead) { - return best_len; + /* fill in remaining table entry if code is incomplete (guaranteed to have + at most one remaining entry, since if the code is incomplete, the + maximum code length that was allowed to get this far is one bit) */ + if (huff !== 0) { + //table.op[next + huff] = 64; /* invalid code marker */ + //table.bits[next + huff] = len - drop; + //table.val[next + huff] = 0; + table[next + huff] = ((len - drop) << 24) | (64 << 16) |0; } - return s.lookahead; + + /* set return parameters */ + //opts.table_index += used; + opts.bits = root; + return 0; }; -/* =========================================================================== - * Fill the window when the lookahead becomes insufficient. - * Updates strstart and lookahead. - * - * IN assertion: lookahead < MIN_LOOKAHEAD - * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD - * At least one byte has been read, or avail_in == 0; reads are - * performed for at least two bytes (required for the zip translate_eol - * option -- not supported here). - */ -const fill_window = (s) => { +module.exports = inflate_table; - const _w_size = s.w_size; - let p, n, m, more, str; +},{}],78:[function(require,module,exports){ +'use strict'; - //Assert(s->lookahead < MIN_LOOKAHEAD, "already enough lookahead"); +// (C) 1995-2013 Jean-loup Gailly and Mark Adler +// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. - do { - more = s.window_size - s.lookahead - s.strstart; +module.exports = { + 2: 'need dictionary', /* Z_NEED_DICT 2 */ + 1: 'stream end', /* Z_STREAM_END 1 */ + 0: '', /* Z_OK 0 */ + '-1': 'file error', /* Z_ERRNO (-1) */ + '-2': 'stream error', /* Z_STREAM_ERROR (-2) */ + '-3': 'data error', /* Z_DATA_ERROR (-3) */ + '-4': 'insufficient memory', /* Z_MEM_ERROR (-4) */ + '-5': 'buffer error', /* Z_BUF_ERROR (-5) */ + '-6': 'incompatible version' /* Z_VERSION_ERROR (-6) */ +}; - // JS ints have 32 bit, block below not needed - /* Deal with !@#$% 64K limit: */ - //if (sizeof(int) <= 2) { - // if (more == 0 && s->strstart == 0 && s->lookahead == 0) { - // more = wsize; - // - // } else if (more == (unsigned)(-1)) { - // /* Very unlikely, but possible on 16 bit machine if - // * strstart == 0 && lookahead == 1 (input done a byte at time) - // */ - // more--; - // } - //} +},{}],79:[function(require,module,exports){ +'use strict'; +// (C) 1995-2013 Jean-loup Gailly and Mark Adler +// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. - /* If the window is almost full and there is insufficient lookahead, - * move the upper half to the lower one to make room in the upper half. - */ - if (s.strstart >= _w_size + (_w_size - MIN_LOOKAHEAD)) { +/* eslint-disable space-unary-ops */ - s.window.set(s.window.subarray(_w_size, _w_size + _w_size), 0); - s.match_start -= _w_size; - s.strstart -= _w_size; - /* we now have strstart >= MAX_DIST */ - s.block_start -= _w_size; +/* Public constants ==========================================================*/ +/* ===========================================================================*/ - /* Slide the hash table (could be avoided with 32 bit values - at the expense of memory usage). We slide even when level == 0 - to keep the hash table consistent if we switch back to level > 0 - later. (Using level 0 permanently is not an optimal usage of - zlib, so we don't care about this pathological case.) - */ - n = s.hash_size; - p = n; +//const Z_FILTERED = 1; +//const Z_HUFFMAN_ONLY = 2; +//const Z_RLE = 3; +const Z_FIXED = 4; +//const Z_DEFAULT_STRATEGY = 0; - do { - m = s.head[--p]; - s.head[p] = (m >= _w_size ? m - _w_size : 0); - } while (--n); +/* Possible values of the data_type field (though see inflate()) */ +const Z_BINARY = 0; +const Z_TEXT = 1; +//const Z_ASCII = 1; // = Z_TEXT +const Z_UNKNOWN = 2; - n = _w_size; - p = n; +/*============================================================================*/ - do { - m = s.prev[--p]; - s.prev[p] = (m >= _w_size ? m - _w_size : 0); - /* If n is not on any hash chain, prev[n] is garbage but - * its value will never be used. - */ - } while (--n); - more += _w_size; - } - if (s.strm.avail_in === 0) { - break; - } +function zero(buf) { let len = buf.length; while (--len >= 0) { buf[len] = 0; } } - /* If there was no sliding: - * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && - * more == window_size - lookahead - strstart - * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) - * => more >= window_size - 2*WSIZE + 2 - * In the BIG_MEM or MMAP case (not yet supported), - * window_size == input_size + MIN_LOOKAHEAD && - * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. - * Otherwise, window_size == 2*WSIZE so more >= 2. - * If there was sliding, more >= WSIZE. So in all cases, more >= 2. - */ - //Assert(more >= 2, "more < 2"); - n = read_buf(s.strm, s.window, s.strstart + s.lookahead, more); - s.lookahead += n; +// From zutil.h - /* Initialize the hash value now that we have some input: */ - if (s.lookahead + s.insert >= MIN_MATCH) { - str = s.strstart - s.insert; - s.ins_h = s.window[str]; +const STORED_BLOCK = 0; +const STATIC_TREES = 1; +const DYN_TREES = 2; +/* The three kinds of block type */ - /* UPDATE_HASH(s, s->ins_h, s->window[str + 1]); */ - s.ins_h = HASH(s, s.ins_h, s.window[str + 1]); -//#if MIN_MATCH != 3 -// Call update_hash() MIN_MATCH-3 more times -//#endif - while (s.insert) { - /* UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); */ - s.ins_h = HASH(s, s.ins_h, s.window[str + MIN_MATCH - 1]); +const MIN_MATCH = 3; +const MAX_MATCH = 258; +/* The minimum and maximum match lengths */ - s.prev[str & s.w_mask] = s.head[s.ins_h]; - s.head[s.ins_h] = str; - str++; - s.insert--; - if (s.lookahead + s.insert < MIN_MATCH) { - break; - } - } - } - /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, - * but this is not important since only literal bytes will be emitted. - */ +// From deflate.h +/* =========================================================================== + * Internal compression state. + */ - } while (s.lookahead < MIN_LOOKAHEAD && s.strm.avail_in !== 0); +const LENGTH_CODES = 29; +/* number of length codes, not counting the special END_BLOCK code */ - /* If the WIN_INIT bytes after the end of the current data have never been - * written, then zero those bytes in order to avoid memory check reports of - * the use of uninitialized (or uninitialised as Julian writes) bytes by - * the longest match routines. Update the high water mark for the next - * time through here. WIN_INIT is set to MAX_MATCH since the longest match - * routines allow scanning to strstart + MAX_MATCH, ignoring lookahead. - */ -// if (s.high_water < s.window_size) { -// const curr = s.strstart + s.lookahead; -// let init = 0; -// -// if (s.high_water < curr) { -// /* Previous high water mark below current data -- zero WIN_INIT -// * bytes or up to end of window, whichever is less. -// */ -// init = s.window_size - curr; -// if (init > WIN_INIT) -// init = WIN_INIT; -// zmemzero(s->window + curr, (unsigned)init); -// s->high_water = curr + init; -// } -// else if (s->high_water < (ulg)curr + WIN_INIT) { -// /* High water mark at or above current data, but below current data -// * plus WIN_INIT -- zero out to current data plus WIN_INIT, or up -// * to end of window, whichever is less. -// */ -// init = (ulg)curr + WIN_INIT - s->high_water; -// if (init > s->window_size - s->high_water) -// init = s->window_size - s->high_water; -// zmemzero(s->window + s->high_water, (unsigned)init); -// s->high_water += init; -// } -// } -// -// Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD, -// "not enough room for search"); -}; +const LITERALS = 256; +/* number of literal bytes 0..255 */ -/* =========================================================================== - * Copy without compression as much as possible from the input stream, return - * the current block state. - * This function does not insert new strings in the dictionary since - * uncompressible data is probably not useful. This function is used - * only for the level=0 compression option. - * NOTE: this function should be optimized to avoid extra copying from - * window to pending_buf. - */ -const deflate_stored = (s, flush) => { +const L_CODES = LITERALS + 1 + LENGTH_CODES; +/* number of Literal or Length codes, including the END_BLOCK code */ - /* Stored blocks are limited to 0xffff bytes, pending_buf is limited - * to pending_buf_size, and each stored block has a 5 byte header: - */ - let max_block_size = 0xffff; +const D_CODES = 30; +/* number of distance codes */ - if (max_block_size > s.pending_buf_size - 5) { - max_block_size = s.pending_buf_size - 5; - } +const BL_CODES = 19; +/* number of codes used to transfer the bit lengths */ - /* Copy as much as possible from input to output: */ - for (;;) { - /* Fill the window as much as possible: */ - if (s.lookahead <= 1) { +const HEAP_SIZE = 2 * L_CODES + 1; +/* maximum heap size */ - //Assert(s->strstart < s->w_size+MAX_DIST(s) || - // s->block_start >= (long)s->w_size, "slide too late"); -// if (!(s.strstart < s.w_size + (s.w_size - MIN_LOOKAHEAD) || -// s.block_start >= s.w_size)) { -// throw new Error("slide too late"); -// } +const MAX_BITS = 15; +/* All codes must not exceed MAX_BITS bits */ - fill_window(s); - if (s.lookahead === 0 && flush === Z_NO_FLUSH) { - return BS_NEED_MORE; - } +const Buf_size = 16; +/* size of bit buffer in bi_buf */ - if (s.lookahead === 0) { - break; - } - /* flush the current block */ - } - //Assert(s->block_start >= 0L, "block gone"); -// if (s.block_start < 0) throw new Error("block gone"); - s.strstart += s.lookahead; - s.lookahead = 0; +/* =========================================================================== + * Constants + */ - /* Emit a stored block if pending_buf will be full: */ - const max_start = s.block_start + max_block_size; +const MAX_BL_BITS = 7; +/* Bit length codes must not exceed MAX_BL_BITS bits */ - if (s.strstart === 0 || s.strstart >= max_start) { - /* strstart == 0 is possible when wraparound on 16-bit machine */ - s.lookahead = s.strstart - max_start; - s.strstart = max_start; - /*** FLUSH_BLOCK(s, 0); ***/ - flush_block_only(s, false); - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - /***/ +const END_BLOCK = 256; +/* end of block literal code */ +const REP_3_6 = 16; +/* repeat previous bit length 3-6 times (2 bits of repeat count) */ - } - /* Flush if we may have to slide, otherwise block_start may become - * negative and the data will be gone: - */ - if (s.strstart - s.block_start >= (s.w_size - MIN_LOOKAHEAD)) { - /*** FLUSH_BLOCK(s, 0); ***/ - flush_block_only(s, false); - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - /***/ - } - } +const REPZ_3_10 = 17; +/* repeat a zero length 3-10 times (3 bits of repeat count) */ - s.insert = 0; +const REPZ_11_138 = 18; +/* repeat a zero length 11-138 times (7 bits of repeat count) */ - if (flush === Z_FINISH) { - /*** FLUSH_BLOCK(s, 1); ***/ - flush_block_only(s, true); - if (s.strm.avail_out === 0) { - return BS_FINISH_STARTED; - } - /***/ - return BS_FINISH_DONE; - } +/* eslint-disable comma-spacing,array-bracket-spacing */ +const extra_lbits = /* extra bits for each length code */ + new Uint8Array([0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0]); - if (s.strstart > s.block_start) { - /*** FLUSH_BLOCK(s, 0); ***/ - flush_block_only(s, false); - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - /***/ - } +const extra_dbits = /* extra bits for each distance code */ + new Uint8Array([0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13]); - return BS_NEED_MORE; -}; +const extra_blbits = /* extra bits for each bit length code */ + new Uint8Array([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7]); + +const bl_order = + new Uint8Array([16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15]); +/* eslint-enable comma-spacing,array-bracket-spacing */ + +/* The lengths of the bit length codes are sent in order of decreasing + * probability, to avoid transmitting the lengths for unused bit length codes. + */ /* =========================================================================== - * Compress as much as possible from the input stream, return the current - * block state. - * This function does not perform lazy evaluation of matches and inserts - * new strings in the dictionary only for unmatched strings or for short - * matches. It is used only for the fast compression options. + * Local data. These are initialized only once. */ -const deflate_fast = (s, flush) => { - let hash_head; /* head of the hash chain */ - let bflush; /* set if current block must be flushed */ +// We pre-fill arrays with 0 to avoid uninitialized gaps - for (;;) { - /* Make sure that we always have enough lookahead, except - * at the end of the input file. We need MAX_MATCH bytes - * for the next match, plus MIN_MATCH bytes to insert the - * string following the next match. - */ - if (s.lookahead < MIN_LOOKAHEAD) { - fill_window(s); - if (s.lookahead < MIN_LOOKAHEAD && flush === Z_NO_FLUSH) { - return BS_NEED_MORE; - } - if (s.lookahead === 0) { - break; /* flush the current block */ - } - } +const DIST_CODE_LEN = 512; /* see definition of array dist_code below */ - /* Insert the string window[strstart .. strstart+2] in the - * dictionary, and set hash_head to the head of the hash chain: - */ - hash_head = 0/*NIL*/; - if (s.lookahead >= MIN_MATCH) { - /*** INSERT_STRING(s, s.strstart, hash_head); ***/ - s.ins_h = HASH(s, s.ins_h, s.window[s.strstart + MIN_MATCH - 1]); - hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h]; - s.head[s.ins_h] = s.strstart; - /***/ - } +// !!!! Use flat array instead of structure, Freq = i*2, Len = i*2+1 +const static_ltree = new Array((L_CODES + 2) * 2); +zero(static_ltree); +/* The static literal tree. Since the bit lengths are imposed, there is no + * need for the L_CODES extra codes used during heap construction. However + * The codes 286 and 287 are needed to build a canonical tree (see _tr_init + * below). + */ - /* Find the longest match, discarding those <= prev_length. - * At this point we have always match_length < MIN_MATCH - */ - if (hash_head !== 0/*NIL*/ && ((s.strstart - hash_head) <= (s.w_size - MIN_LOOKAHEAD))) { - /* To simplify the code, we prevent matches with the string - * of window index 0 (in particular we have to avoid a match - * of the string with itself at the start of the input file). - */ - s.match_length = longest_match(s, hash_head); - /* longest_match() sets match_start */ - } - if (s.match_length >= MIN_MATCH) { - // check_match(s, s.strstart, s.match_start, s.match_length); // for debug only +const static_dtree = new Array(D_CODES * 2); +zero(static_dtree); +/* The static distance tree. (Actually a trivial tree since all codes use + * 5 bits.) + */ - /*** _tr_tally_dist(s, s.strstart - s.match_start, - s.match_length - MIN_MATCH, bflush); ***/ - bflush = _tr_tally(s, s.strstart - s.match_start, s.match_length - MIN_MATCH); +const _dist_code = new Array(DIST_CODE_LEN); +zero(_dist_code); +/* Distance codes. The first 256 values correspond to the distances + * 3 .. 258, the last 256 values correspond to the top 8 bits of + * the 15 bit distances. + */ - s.lookahead -= s.match_length; +const _length_code = new Array(MAX_MATCH - MIN_MATCH + 1); +zero(_length_code); +/* length code for each normalized match length (0 == MIN_MATCH) */ - /* Insert new strings in the hash table only if the match length - * is not too large. This saves time but degrades compression. - */ - if (s.match_length <= s.max_lazy_match/*max_insert_length*/ && s.lookahead >= MIN_MATCH) { - s.match_length--; /* string at strstart already in table */ - do { - s.strstart++; - /*** INSERT_STRING(s, s.strstart, hash_head); ***/ - s.ins_h = HASH(s, s.ins_h, s.window[s.strstart + MIN_MATCH - 1]); - hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h]; - s.head[s.ins_h] = s.strstart; - /***/ - /* strstart never exceeds WSIZE-MAX_MATCH, so there are - * always MIN_MATCH bytes ahead. - */ - } while (--s.match_length !== 0); - s.strstart++; - } else - { - s.strstart += s.match_length; - s.match_length = 0; - s.ins_h = s.window[s.strstart]; - /* UPDATE_HASH(s, s.ins_h, s.window[s.strstart+1]); */ - s.ins_h = HASH(s, s.ins_h, s.window[s.strstart + 1]); - -//#if MIN_MATCH != 3 -// Call UPDATE_HASH() MIN_MATCH-3 more times -//#endif - /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not - * matter since it will be recomputed at next deflate call. - */ - } - } else { - /* No match, output a literal byte */ - //Tracevv((stderr,"%c", s.window[s.strstart])); - /*** _tr_tally_lit(s, s.window[s.strstart], bflush); ***/ - bflush = _tr_tally(s, 0, s.window[s.strstart]); - - s.lookahead--; - s.strstart++; - } - if (bflush) { - /*** FLUSH_BLOCK(s, 0); ***/ - flush_block_only(s, false); - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - /***/ - } - } - s.insert = ((s.strstart < (MIN_MATCH - 1)) ? s.strstart : MIN_MATCH - 1); - if (flush === Z_FINISH) { - /*** FLUSH_BLOCK(s, 1); ***/ - flush_block_only(s, true); - if (s.strm.avail_out === 0) { - return BS_FINISH_STARTED; - } - /***/ - return BS_FINISH_DONE; - } - if (s.last_lit) { - /*** FLUSH_BLOCK(s, 0); ***/ - flush_block_only(s, false); - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - /***/ - } - return BS_BLOCK_DONE; -}; - -/* =========================================================================== - * Same as above, but achieves better compression. We use a lazy - * evaluation for matches: a match is finally adopted only if there is - * no better match at the next window position. - */ -const deflate_slow = (s, flush) => { +const base_length = new Array(LENGTH_CODES); +zero(base_length); +/* First normalized length for each code (0 = MIN_MATCH) */ - let hash_head; /* head of hash chain */ - let bflush; /* set if current block must be flushed */ +const base_dist = new Array(D_CODES); +zero(base_dist); +/* First normalized distance for each code (0 = distance of 1) */ - let max_insert; - /* Process the input block. */ - for (;;) { - /* Make sure that we always have enough lookahead, except - * at the end of the input file. We need MAX_MATCH bytes - * for the next match, plus MIN_MATCH bytes to insert the - * string following the next match. - */ - if (s.lookahead < MIN_LOOKAHEAD) { - fill_window(s); - if (s.lookahead < MIN_LOOKAHEAD && flush === Z_NO_FLUSH) { - return BS_NEED_MORE; - } - if (s.lookahead === 0) { break; } /* flush the current block */ - } +function StaticTreeDesc(static_tree, extra_bits, extra_base, elems, max_length) { - /* Insert the string window[strstart .. strstart+2] in the - * dictionary, and set hash_head to the head of the hash chain: - */ - hash_head = 0/*NIL*/; - if (s.lookahead >= MIN_MATCH) { - /*** INSERT_STRING(s, s.strstart, hash_head); ***/ - s.ins_h = HASH(s, s.ins_h, s.window[s.strstart + MIN_MATCH - 1]); - hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h]; - s.head[s.ins_h] = s.strstart; - /***/ - } + this.static_tree = static_tree; /* static tree or NULL */ + this.extra_bits = extra_bits; /* extra bits for each code or NULL */ + this.extra_base = extra_base; /* base index for extra_bits */ + this.elems = elems; /* max number of elements in the tree */ + this.max_length = max_length; /* max bit length for the codes */ - /* Find the longest match, discarding those <= prev_length. - */ - s.prev_length = s.match_length; - s.prev_match = s.match_start; - s.match_length = MIN_MATCH - 1; + // show if `static_tree` has data or dummy - needed for monomorphic objects + this.has_stree = static_tree && static_tree.length; +} - if (hash_head !== 0/*NIL*/ && s.prev_length < s.max_lazy_match && - s.strstart - hash_head <= (s.w_size - MIN_LOOKAHEAD)/*MAX_DIST(s)*/) { - /* To simplify the code, we prevent matches with the string - * of window index 0 (in particular we have to avoid a match - * of the string with itself at the start of the input file). - */ - s.match_length = longest_match(s, hash_head); - /* longest_match() sets match_start */ - if (s.match_length <= 5 && - (s.strategy === Z_FILTERED || (s.match_length === MIN_MATCH && s.strstart - s.match_start > 4096/*TOO_FAR*/))) { +let static_l_desc; +let static_d_desc; +let static_bl_desc; - /* If prev_match is also MIN_MATCH, match_start is garbage - * but we will ignore the current match anyway. - */ - s.match_length = MIN_MATCH - 1; - } - } - /* If there was a match at the previous step and the current - * match is not better, output the previous match: - */ - if (s.prev_length >= MIN_MATCH && s.match_length <= s.prev_length) { - max_insert = s.strstart + s.lookahead - MIN_MATCH; - /* Do not insert strings in hash table beyond this. */ - //check_match(s, s.strstart-1, s.prev_match, s.prev_length); +function TreeDesc(dyn_tree, stat_desc) { + this.dyn_tree = dyn_tree; /* the dynamic tree */ + this.max_code = 0; /* largest code with non zero frequency */ + this.stat_desc = stat_desc; /* the corresponding static tree */ +} - /***_tr_tally_dist(s, s.strstart - 1 - s.prev_match, - s.prev_length - MIN_MATCH, bflush);***/ - bflush = _tr_tally(s, s.strstart - 1 - s.prev_match, s.prev_length - MIN_MATCH); - /* Insert in hash table all strings up to the end of the match. - * strstart-1 and strstart are already inserted. If there is not - * enough lookahead, the last two strings are not inserted in - * the hash table. - */ - s.lookahead -= s.prev_length - 1; - s.prev_length -= 2; - do { - if (++s.strstart <= max_insert) { - /*** INSERT_STRING(s, s.strstart, hash_head); ***/ - s.ins_h = HASH(s, s.ins_h, s.window[s.strstart + MIN_MATCH - 1]); - hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h]; - s.head[s.ins_h] = s.strstart; - /***/ - } - } while (--s.prev_length !== 0); - s.match_available = 0; - s.match_length = MIN_MATCH - 1; - s.strstart++; - if (bflush) { - /*** FLUSH_BLOCK(s, 0); ***/ - flush_block_only(s, false); - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - /***/ - } - } else if (s.match_available) { - /* If there was no match at the previous position, output a - * single literal. If there was a match but the current match - * is longer, truncate the previous match to a single literal. - */ - //Tracevv((stderr,"%c", s->window[s->strstart-1])); - /*** _tr_tally_lit(s, s.window[s.strstart-1], bflush); ***/ - bflush = _tr_tally(s, 0, s.window[s.strstart - 1]); +const d_code = (dist) => { - if (bflush) { - /*** FLUSH_BLOCK_ONLY(s, 0) ***/ - flush_block_only(s, false); - /***/ - } - s.strstart++; - s.lookahead--; - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - } else { - /* There is no previous match to compare with, wait for - * the next step to decide. - */ - s.match_available = 1; - s.strstart++; - s.lookahead--; - } - } - //Assert (flush != Z_NO_FLUSH, "no flush?"); - if (s.match_available) { - //Tracevv((stderr,"%c", s->window[s->strstart-1])); - /*** _tr_tally_lit(s, s.window[s.strstart-1], bflush); ***/ - bflush = _tr_tally(s, 0, s.window[s.strstart - 1]); + return dist < 256 ? _dist_code[dist] : _dist_code[256 + (dist >>> 7)]; +}; - s.match_available = 0; - } - s.insert = s.strstart < MIN_MATCH - 1 ? s.strstart : MIN_MATCH - 1; - if (flush === Z_FINISH) { - /*** FLUSH_BLOCK(s, 1); ***/ - flush_block_only(s, true); - if (s.strm.avail_out === 0) { - return BS_FINISH_STARTED; - } - /***/ - return BS_FINISH_DONE; - } - if (s.last_lit) { - /*** FLUSH_BLOCK(s, 0); ***/ - flush_block_only(s, false); - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - /***/ - } - return BS_BLOCK_DONE; +/* =========================================================================== + * Output a short LSB first on the stream. + * IN assertion: there is enough room in pendingBuf. + */ +const put_short = (s, w) => { +// put_byte(s, (uch)((w) & 0xff)); +// put_byte(s, (uch)((ush)(w) >> 8)); + s.pending_buf[s.pending++] = (w) & 0xff; + s.pending_buf[s.pending++] = (w >>> 8) & 0xff; }; /* =========================================================================== - * For Z_RLE, simply look for runs of bytes, generate matches only of distance - * one. Do not maintain a hash table. (It will be regenerated if this run of - * deflate switches away from Z_RLE.) + * Send a value on a given number of bits. + * IN assertion: length <= 16 and value fits in length bits. */ -const deflate_rle = (s, flush) => { - - let bflush; /* set if current block must be flushed */ - let prev; /* byte at distance one to match */ - let scan, strend; /* scan goes up to strend for length of run */ +const send_bits = (s, value, length) => { - const _win = s.window; + if (s.bi_valid > (Buf_size - length)) { + s.bi_buf |= (value << s.bi_valid) & 0xffff; + put_short(s, s.bi_buf); + s.bi_buf = value >> (Buf_size - s.bi_valid); + s.bi_valid += length - Buf_size; + } else { + s.bi_buf |= (value << s.bi_valid) & 0xffff; + s.bi_valid += length; + } +}; - for (;;) { - /* Make sure that we always have enough lookahead, except - * at the end of the input file. We need MAX_MATCH bytes - * for the longest run, plus one for the unrolled loop. - */ - if (s.lookahead <= MAX_MATCH) { - fill_window(s); - if (s.lookahead <= MAX_MATCH && flush === Z_NO_FLUSH) { - return BS_NEED_MORE; - } - if (s.lookahead === 0) { break; } /* flush the current block */ - } - /* See how many times the previous byte repeats */ - s.match_length = 0; - if (s.lookahead >= MIN_MATCH && s.strstart > 0) { - scan = s.strstart - 1; - prev = _win[scan]; - if (prev === _win[++scan] && prev === _win[++scan] && prev === _win[++scan]) { - strend = s.strstart + MAX_MATCH; - do { - /*jshint noempty:false*/ - } while (prev === _win[++scan] && prev === _win[++scan] && - prev === _win[++scan] && prev === _win[++scan] && - prev === _win[++scan] && prev === _win[++scan] && - prev === _win[++scan] && prev === _win[++scan] && - scan < strend); - s.match_length = MAX_MATCH - (strend - scan); - if (s.match_length > s.lookahead) { - s.match_length = s.lookahead; - } - } - //Assert(scan <= s->window+(uInt)(s->window_size-1), "wild scan"); - } +const send_code = (s, c, tree) => { - /* Emit match if have run of MIN_MATCH or longer, else emit literal */ - if (s.match_length >= MIN_MATCH) { - //check_match(s, s.strstart, s.strstart - 1, s.match_length); + send_bits(s, tree[c * 2]/*.Code*/, tree[c * 2 + 1]/*.Len*/); +}; - /*** _tr_tally_dist(s, 1, s.match_length - MIN_MATCH, bflush); ***/ - bflush = _tr_tally(s, 1, s.match_length - MIN_MATCH); - s.lookahead -= s.match_length; - s.strstart += s.match_length; - s.match_length = 0; - } else { - /* No match, output a literal byte */ - //Tracevv((stderr,"%c", s->window[s->strstart])); - /*** _tr_tally_lit(s, s.window[s.strstart], bflush); ***/ - bflush = _tr_tally(s, 0, s.window[s.strstart]); +/* =========================================================================== + * Reverse the first len bits of a code, using straightforward code (a faster + * method would use a table) + * IN assertion: 1 <= len <= 15 + */ +const bi_reverse = (code, len) => { - s.lookahead--; - s.strstart++; - } - if (bflush) { - /*** FLUSH_BLOCK(s, 0); ***/ - flush_block_only(s, false); - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - /***/ - } - } - s.insert = 0; - if (flush === Z_FINISH) { - /*** FLUSH_BLOCK(s, 1); ***/ - flush_block_only(s, true); - if (s.strm.avail_out === 0) { - return BS_FINISH_STARTED; - } - /***/ - return BS_FINISH_DONE; - } - if (s.last_lit) { - /*** FLUSH_BLOCK(s, 0); ***/ - flush_block_only(s, false); - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - /***/ - } - return BS_BLOCK_DONE; + let res = 0; + do { + res |= code & 1; + code >>>= 1; + res <<= 1; + } while (--len > 0); + return res >>> 1; }; + /* =========================================================================== - * For Z_HUFFMAN_ONLY, do not look for matches. Do not maintain a hash table. - * (It will be regenerated if this run of deflate switches away from Huffman.) + * Flush the bit buffer, keeping at most 7 bits in it. */ -const deflate_huff = (s, flush) => { - - let bflush; /* set if current block must be flushed */ +const bi_flush = (s) => { - for (;;) { - /* Make sure that we have a literal to write. */ - if (s.lookahead === 0) { - fill_window(s); - if (s.lookahead === 0) { - if (flush === Z_NO_FLUSH) { - return BS_NEED_MORE; - } - break; /* flush the current block */ - } - } + if (s.bi_valid === 16) { + put_short(s, s.bi_buf); + s.bi_buf = 0; + s.bi_valid = 0; - /* Output a literal byte */ - s.match_length = 0; - //Tracevv((stderr,"%c", s->window[s->strstart])); - /*** _tr_tally_lit(s, s.window[s.strstart], bflush); ***/ - bflush = _tr_tally(s, 0, s.window[s.strstart]); - s.lookahead--; - s.strstart++; - if (bflush) { - /*** FLUSH_BLOCK(s, 0); ***/ - flush_block_only(s, false); - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - /***/ - } - } - s.insert = 0; - if (flush === Z_FINISH) { - /*** FLUSH_BLOCK(s, 1); ***/ - flush_block_only(s, true); - if (s.strm.avail_out === 0) { - return BS_FINISH_STARTED; - } - /***/ - return BS_FINISH_DONE; - } - if (s.last_lit) { - /*** FLUSH_BLOCK(s, 0); ***/ - flush_block_only(s, false); - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - /***/ + } else if (s.bi_valid >= 8) { + s.pending_buf[s.pending++] = s.bi_buf & 0xff; + s.bi_buf >>= 8; + s.bi_valid -= 8; } - return BS_BLOCK_DONE; }; -/* Values for max_lazy_match, good_match and max_chain_length, depending on - * the desired pack level (0..9). The values given below have been tuned to - * exclude worst case performance for pathological files. Better values may be - * found for specific files. - */ -function Config(good_length, max_lazy, nice_length, max_chain, func) { - - this.good_length = good_length; - this.max_lazy = max_lazy; - this.nice_length = nice_length; - this.max_chain = max_chain; - this.func = func; -} - -const configuration_table = [ - /* good lazy nice chain */ - new Config(0, 0, 0, 0, deflate_stored), /* 0 store only */ - new Config(4, 4, 8, 4, deflate_fast), /* 1 max speed, no lazy matches */ - new Config(4, 5, 16, 8, deflate_fast), /* 2 */ - new Config(4, 6, 32, 32, deflate_fast), /* 3 */ - - new Config(4, 4, 16, 16, deflate_slow), /* 4 lazy matches */ - new Config(8, 16, 32, 32, deflate_slow), /* 5 */ - new Config(8, 16, 128, 128, deflate_slow), /* 6 */ - new Config(8, 32, 128, 256, deflate_slow), /* 7 */ - new Config(32, 128, 258, 1024, deflate_slow), /* 8 */ - new Config(32, 258, 258, 4096, deflate_slow) /* 9 max compression */ -]; - /* =========================================================================== - * Initialize the "longest match" routines for a new zlib stream + * Compute the optimal bit lengths for a tree and update the total bit length + * for the current block. + * IN assertion: the fields freq and dad are set, heap[heap_max] and + * above are the tree nodes sorted by increasing frequency. + * OUT assertions: the field len is set to the optimal bit length, the + * array bl_count contains the frequencies for each bit length. + * The length opt_len is updated; static_len is also updated if stree is + * not null. */ -const lm_init = (s) => { +const gen_bitlen = (s, desc) => { +// deflate_state *s; +// tree_desc *desc; /* the tree descriptor */ - s.window_size = 2 * s.w_size; + const tree = desc.dyn_tree; + const max_code = desc.max_code; + const stree = desc.stat_desc.static_tree; + const has_stree = desc.stat_desc.has_stree; + const extra = desc.stat_desc.extra_bits; + const base = desc.stat_desc.extra_base; + const max_length = desc.stat_desc.max_length; + let h; /* heap index */ + let n, m; /* iterate over the tree elements */ + let bits; /* bit length */ + let xbits; /* extra bits */ + let f; /* frequency */ + let overflow = 0; /* number of elements with bit length too large */ - /*** CLEAR_HASH(s); ***/ - zero(s.head); // Fill with NIL (= 0); + for (bits = 0; bits <= MAX_BITS; bits++) { + s.bl_count[bits] = 0; + } - /* Set the default configuration parameters: + /* In a first pass, compute the optimal bit lengths (which may + * overflow in the case of the bit length tree). */ - s.max_lazy_match = configuration_table[s.level].max_lazy; - s.good_match = configuration_table[s.level].good_length; - s.nice_match = configuration_table[s.level].nice_length; - s.max_chain_length = configuration_table[s.level].max_chain; + tree[s.heap[s.heap_max] * 2 + 1]/*.Len*/ = 0; /* root of the heap */ - s.strstart = 0; - s.block_start = 0; - s.lookahead = 0; - s.insert = 0; - s.match_length = s.prev_length = MIN_MATCH - 1; - s.match_available = 0; - s.ins_h = 0; -}; + for (h = s.heap_max + 1; h < HEAP_SIZE; h++) { + n = s.heap[h]; + bits = tree[tree[n * 2 + 1]/*.Dad*/ * 2 + 1]/*.Len*/ + 1; + if (bits > max_length) { + bits = max_length; + overflow++; + } + tree[n * 2 + 1]/*.Len*/ = bits; + /* We overwrite tree[n].Dad which is no longer needed */ + if (n > max_code) { continue; } /* not a leaf node */ -function DeflateState() { - this.strm = null; /* pointer back to this zlib stream */ - this.status = 0; /* as the name implies */ - this.pending_buf = null; /* output still pending */ - this.pending_buf_size = 0; /* size of pending_buf */ - this.pending_out = 0; /* next pending byte to output to the stream */ - this.pending = 0; /* nb of bytes in the pending buffer */ - this.wrap = 0; /* bit 0 true for zlib, bit 1 true for gzip */ - this.gzhead = null; /* gzip header information to write */ - this.gzindex = 0; /* where in extra, name, or comment */ - this.method = Z_DEFLATED; /* can only be DEFLATED */ - this.last_flush = -1; /* value of flush param for previous deflate call */ - - this.w_size = 0; /* LZ77 window size (32K by default) */ - this.w_bits = 0; /* log2(w_size) (8..16) */ - this.w_mask = 0; /* w_size - 1 */ - - this.window = null; - /* Sliding window. Input bytes are read into the second half of the window, - * and move to the first half later to keep a dictionary of at least wSize - * bytes. With this organization, matches are limited to a distance of - * wSize-MAX_MATCH bytes, but this ensures that IO is always - * performed with a length multiple of the block size. - */ - - this.window_size = 0; - /* Actual size of window: 2*wSize, except when the user input buffer - * is directly used as sliding window. - */ - - this.prev = null; - /* Link to older string with same hash index. To limit the size of this - * array to 64K, this link is maintained only for the last 32K strings. - * An index in this array is thus a window index modulo 32K. - */ - - this.head = null; /* Heads of the hash chains or NIL. */ + s.bl_count[bits]++; + xbits = 0; + if (n >= base) { + xbits = extra[n - base]; + } + f = tree[n * 2]/*.Freq*/; + s.opt_len += f * (bits + xbits); + if (has_stree) { + s.static_len += f * (stree[n * 2 + 1]/*.Len*/ + xbits); + } + } + if (overflow === 0) { return; } - this.ins_h = 0; /* hash index of string to be inserted */ - this.hash_size = 0; /* number of elements in hash table */ - this.hash_bits = 0; /* log2(hash_size) */ - this.hash_mask = 0; /* hash_size-1 */ + // Tracev((stderr,"\nbit length overflow\n")); + /* This happens for example on obj2 and pic of the Calgary corpus */ - this.hash_shift = 0; - /* Number of bits by which ins_h must be shifted at each input - * step. It must be such that after MIN_MATCH steps, the oldest - * byte no longer takes part in the hash key, that is: - * hash_shift * MIN_MATCH >= hash_bits - */ + /* Find the first bit length which could increase: */ + do { + bits = max_length - 1; + while (s.bl_count[bits] === 0) { bits--; } + s.bl_count[bits]--; /* move one leaf down the tree */ + s.bl_count[bits + 1] += 2; /* move one overflow item as its brother */ + s.bl_count[max_length]--; + /* The brother of the overflow item also moves one step up, + * but this does not affect bl_count[max_length] + */ + overflow -= 2; + } while (overflow > 0); - this.block_start = 0; - /* Window position at the beginning of the current output block. Gets - * negative when the window is moved backwards. + /* Now recompute all bit lengths, scanning in increasing frequency. + * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all + * lengths instead of fixing only the wrong ones. This idea is taken + * from 'ar' written by Haruhiko Okumura.) */ + for (bits = max_length; bits !== 0; bits--) { + n = s.bl_count[bits]; + while (n !== 0) { + m = s.heap[--h]; + if (m > max_code) { continue; } + if (tree[m * 2 + 1]/*.Len*/ !== bits) { + // Tracev((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); + s.opt_len += (bits - tree[m * 2 + 1]/*.Len*/) * tree[m * 2]/*.Freq*/; + tree[m * 2 + 1]/*.Len*/ = bits; + } + n--; + } + } +}; - this.match_length = 0; /* length of best match */ - this.prev_match = 0; /* previous match */ - this.match_available = 0; /* set if previous match exists */ - this.strstart = 0; /* start of string to insert */ - this.match_start = 0; /* start of matching string */ - this.lookahead = 0; /* number of valid bytes ahead in window */ - this.prev_length = 0; - /* Length of the best match at previous step. Matches not greater than this - * are discarded. This is used in the lazy match evaluation. - */ +/* =========================================================================== + * Generate the codes for a given tree and bit counts (which need not be + * optimal). + * IN assertion: the array bl_count contains the bit length statistics for + * the given tree and the field len is set for all tree elements. + * OUT assertion: the field code is set for all tree elements of non + * zero code length. + */ +const gen_codes = (tree, max_code, bl_count) => { +// ct_data *tree; /* the tree to decorate */ +// int max_code; /* largest code with non zero frequency */ +// ushf *bl_count; /* number of codes at each bit length */ - this.max_chain_length = 0; - /* To speed up deflation, hash chains are never searched beyond this - * length. A higher limit improves compression ratio but degrades the - * speed. - */ + const next_code = new Array(MAX_BITS + 1); /* next code value for each bit length */ + let code = 0; /* running code value */ + let bits; /* bit index */ + let n; /* code index */ - this.max_lazy_match = 0; - /* Attempt to find a better match only when the current match is strictly - * smaller than this value. This mechanism is used only for compression - * levels >= 4. + /* The distribution counts are first used to generate the code values + * without bit reversal. */ - // That's alias to max_lazy_match, don't use directly - //this.max_insert_length = 0; - /* Insert new strings in the hash table only if the match length is not - * greater than this length. This saves time but degrades compression. - * max_insert_length is used only for compression levels <= 3. + for (bits = 1; bits <= MAX_BITS; bits++) { + code = (code + bl_count[bits - 1]) << 1; + next_code[bits] = code; + } + /* Check that the bit counts in bl_count are consistent. The last code + * must be all ones. */ + //Assert (code + bl_count[MAX_BITS]-1 == (1< { - //ush bl_count[MAX_BITS+1]; - this.bl_count = new Uint16Array(MAX_BITS + 1); + let n; /* iterates over tree elements */ + let bits; /* bit counter */ + let length; /* length value */ + let code; /* code value */ + let dist; /* distance index */ + const bl_count = new Array(MAX_BITS + 1); /* number of codes at each bit length for an optimal tree */ - //int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ - this.heap = new Uint16Array(2 * L_CODES + 1); /* heap used to build the Huffman trees */ - zero(this.heap); + // do check in _tr_init() + //if (static_init_done) return; - this.heap_len = 0; /* number of elements in the heap */ - this.heap_max = 0; /* element of largest frequency */ - /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. - * The same heap array is used to build all trees. - */ + /* For some embedded targets, global variables are not initialized: */ +/*#ifdef NO_INIT_GLOBAL_POINTERS + static_l_desc.static_tree = static_ltree; + static_l_desc.extra_bits = extra_lbits; + static_d_desc.static_tree = static_dtree; + static_d_desc.extra_bits = extra_dbits; + static_bl_desc.extra_bits = extra_blbits; +#endif*/ - this.depth = new Uint16Array(2 * L_CODES + 1); //uch depth[2*L_CODES+1]; - zero(this.depth); - /* Depth of each subtree used as tie breaker for trees of equal frequency + /* Initialize the mapping length (0..255) -> length code (0..28) */ + length = 0; + for (code = 0; code < LENGTH_CODES - 1; code++) { + base_length[code] = length; + for (n = 0; n < (1 << extra_lbits[code]); n++) { + _length_code[length++] = code; + } + } + //Assert (length == 256, "tr_static_init: length != 256"); + /* Note that the length 255 (match length 258) can be represented + * in two different ways: code 284 + 5 bits or code 285, so we + * overwrite length_code[255] to use the best encoding: */ + _length_code[length - 1] = code; - this.l_buf = 0; /* buffer index for literals or lengths */ - - this.lit_bufsize = 0; - /* Size of match buffer for literals/lengths. There are 4 reasons for - * limiting lit_bufsize to 64K: - * - frequencies can be kept in 16 bit counters - * - if compression is not successful for the first block, all input - * data is still in the window so we can still emit a stored block even - * when input comes from standard input. (This can also be done for - * all blocks if lit_bufsize is not greater than 32K.) - * - if compression is not successful for a file smaller than 64K, we can - * even emit a stored file instead of a stored block (saving 5 bytes). - * This is applicable only for zip (not gzip or zlib). - * - creating new Huffman trees less frequently may not provide fast - * adaptation to changes in the input data statistics. (Take for - * example a binary file with poorly compressible code followed by - * a highly compressible string table.) Smaller buffer sizes give - * fast adaptation but have of course the overhead of transmitting - * trees more frequently. - * - I can't count above 4 - */ + /* Initialize the mapping dist (0..32K) -> dist code (0..29) */ + dist = 0; + for (code = 0; code < 16; code++) { + base_dist[code] = dist; + for (n = 0; n < (1 << extra_dbits[code]); n++) { + _dist_code[dist++] = code; + } + } + //Assert (dist == 256, "tr_static_init: dist != 256"); + dist >>= 7; /* from now on, all distances are divided by 128 */ + for (; code < D_CODES; code++) { + base_dist[code] = dist << 7; + for (n = 0; n < (1 << (extra_dbits[code] - 7)); n++) { + _dist_code[256 + dist++] = code; + } + } + //Assert (dist == 256, "tr_static_init: 256+dist != 512"); - this.last_lit = 0; /* running index in l_buf */ + /* Construct the codes of the static literal tree */ + for (bits = 0; bits <= MAX_BITS; bits++) { + bl_count[bits] = 0; + } - this.d_buf = 0; - /* Buffer index for distances. To simplify the code, d_buf and l_buf have - * the same number of elements. To use different lengths, an extra flag - * array would be necessary. + n = 0; + while (n <= 143) { + static_ltree[n * 2 + 1]/*.Len*/ = 8; + n++; + bl_count[8]++; + } + while (n <= 255) { + static_ltree[n * 2 + 1]/*.Len*/ = 9; + n++; + bl_count[9]++; + } + while (n <= 279) { + static_ltree[n * 2 + 1]/*.Len*/ = 7; + n++; + bl_count[7]++; + } + while (n <= 287) { + static_ltree[n * 2 + 1]/*.Len*/ = 8; + n++; + bl_count[8]++; + } + /* Codes 286 and 287 do not exist, but we must include them in the + * tree construction to get a canonical Huffman tree (longest code + * all ones) */ + gen_codes(static_ltree, L_CODES + 1, bl_count); - this.opt_len = 0; /* bit length of current block with optimal trees */ - this.static_len = 0; /* bit length of current block with static trees */ - this.matches = 0; /* number of string matches in current block */ - this.insert = 0; /* bytes at end of window left to insert */ - - - this.bi_buf = 0; - /* Output buffer. bits are inserted starting at the bottom (least - * significant bits). - */ - this.bi_valid = 0; - /* Number of valid bits in bi_buf. All bits above the last valid bit - * are always zero. - */ + /* The static distance tree is trivial: */ + for (n = 0; n < D_CODES; n++) { + static_dtree[n * 2 + 1]/*.Len*/ = 5; + static_dtree[n * 2]/*.Code*/ = bi_reverse(n, 5); + } - // Used for window memory init. We safely ignore it for JS. That makes - // sense only for pointers and memory check tools. - //this.high_water = 0; - /* High water mark offset in window for initialized bytes -- bytes above - * this are set to zero in order to avoid memory check warnings when - * longest match routines access bytes past the input. This is then - * updated to the new high water mark. - */ -} + // Now data ready and we can init static trees + static_l_desc = new StaticTreeDesc(static_ltree, extra_lbits, LITERALS + 1, L_CODES, MAX_BITS); + static_d_desc = new StaticTreeDesc(static_dtree, extra_dbits, 0, D_CODES, MAX_BITS); + static_bl_desc = new StaticTreeDesc(new Array(0), extra_blbits, 0, BL_CODES, MAX_BL_BITS); + //static_init_done = true; +}; -const deflateResetKeep = (strm) => { - if (!strm || !strm.state) { - return err(strm, Z_STREAM_ERROR); - } +/* =========================================================================== + * Initialize a new block. + */ +const init_block = (s) => { - strm.total_in = strm.total_out = 0; - strm.data_type = Z_UNKNOWN; + let n; /* iterates over tree elements */ - const s = strm.state; - s.pending = 0; - s.pending_out = 0; + /* Initialize the trees. */ + for (n = 0; n < L_CODES; n++) { s.dyn_ltree[n * 2]/*.Freq*/ = 0; } + for (n = 0; n < D_CODES; n++) { s.dyn_dtree[n * 2]/*.Freq*/ = 0; } + for (n = 0; n < BL_CODES; n++) { s.bl_tree[n * 2]/*.Freq*/ = 0; } - if (s.wrap < 0) { - s.wrap = -s.wrap; - /* was made negative by deflate(..., Z_FINISH); */ - } - s.status = (s.wrap ? INIT_STATE : BUSY_STATE); - strm.adler = (s.wrap === 2) ? - 0 // crc32(0, Z_NULL, 0) - : - 1; // adler32(0, Z_NULL, 0) - s.last_flush = Z_NO_FLUSH; - _tr_init(s); - return Z_OK; + s.dyn_ltree[END_BLOCK * 2]/*.Freq*/ = 1; + s.opt_len = s.static_len = 0; + s.sym_next = s.matches = 0; }; -const deflateReset = (strm) => { - - const ret = deflateResetKeep(strm); - if (ret === Z_OK) { - lm_init(strm.state); +/* =========================================================================== + * Flush the bit buffer and align the output on a byte boundary + */ +const bi_windup = (s) => +{ + if (s.bi_valid > 8) { + put_short(s, s.bi_buf); + } else if (s.bi_valid > 0) { + //put_byte(s, (Byte)s->bi_buf); + s.pending_buf[s.pending++] = s.bi_buf; } - return ret; + s.bi_buf = 0; + s.bi_valid = 0; }; +/* =========================================================================== + * Compares to subtrees, using the tree depth as tie breaker when + * the subtrees have equal frequency. This minimizes the worst case length. + */ +const smaller = (tree, n, m, depth) => { -const deflateSetHeader = (strm, head) => { - - if (!strm || !strm.state) { return Z_STREAM_ERROR; } - if (strm.state.wrap !== 2) { return Z_STREAM_ERROR; } - strm.state.gzhead = head; - return Z_OK; + const _n2 = n * 2; + const _m2 = m * 2; + return (tree[_n2]/*.Freq*/ < tree[_m2]/*.Freq*/ || + (tree[_n2]/*.Freq*/ === tree[_m2]/*.Freq*/ && depth[n] <= depth[m])); }; +/* =========================================================================== + * Restore the heap property by moving down the tree starting at node k, + * exchanging a node with the smallest of its two sons if necessary, stopping + * when the heap property is re-established (each father smaller than its + * two sons). + */ +const pqdownheap = (s, tree, k) => { +// deflate_state *s; +// ct_data *tree; /* the tree to restore */ +// int k; /* node to move down */ -const deflateInit2 = (strm, level, method, windowBits, memLevel, strategy) => { + const v = s.heap[k]; + let j = k << 1; /* left son of k */ + while (j <= s.heap_len) { + /* Set j to the smallest of the two sons: */ + if (j < s.heap_len && + smaller(tree, s.heap[j + 1], s.heap[j], s.depth)) { + j++; + } + /* Exit if v is smaller than both sons */ + if (smaller(tree, v, s.heap[j], s.depth)) { break; } - if (!strm) { // === Z_NULL - return Z_STREAM_ERROR; - } - let wrap = 1; + /* Exchange v with the smallest son */ + s.heap[k] = s.heap[j]; + k = j; - if (level === Z_DEFAULT_COMPRESSION) { - level = 6; + /* And continue down the tree, setting j to the left son of k */ + j <<= 1; } + s.heap[k] = v; +}; - if (windowBits < 0) { /* suppress zlib wrapper */ - wrap = 0; - windowBits = -windowBits; - } - else if (windowBits > 15) { - wrap = 2; /* write gzip wrapper instead */ - windowBits -= 16; - } +// inlined manually +// const SMALLEST = 1; +/* =========================================================================== + * Send the block data compressed using the given Huffman trees + */ +const compress_block = (s, ltree, dtree) => { +// deflate_state *s; +// const ct_data *ltree; /* literal tree */ +// const ct_data *dtree; /* distance tree */ - if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method !== Z_DEFLATED || - windowBits < 8 || windowBits > 15 || level < 0 || level > 9 || - strategy < 0 || strategy > Z_FIXED) { - return err(strm, Z_STREAM_ERROR); - } + let dist; /* distance of matched string */ + let lc; /* match length or unmatched char (if dist == 0) */ + let sx = 0; /* running index in sym_buf */ + let code; /* the code to send */ + let extra; /* number of extra bits to send */ + if (s.sym_next !== 0) { + do { + dist = s.pending_buf[s.sym_buf + sx++] & 0xff; + dist += (s.pending_buf[s.sym_buf + sx++] & 0xff) << 8; + lc = s.pending_buf[s.sym_buf + sx++]; + if (dist === 0) { + send_code(s, lc, ltree); /* send a literal byte */ + //Tracecv(isgraph(lc), (stderr," '%c' ", lc)); + } else { + /* Here, lc is the match length - MIN_MATCH */ + code = _length_code[lc]; + send_code(s, code + LITERALS + 1, ltree); /* send the length code */ + extra = extra_lbits[code]; + if (extra !== 0) { + lc -= base_length[code]; + send_bits(s, lc, extra); /* send the extra length bits */ + } + dist--; /* dist is now the match distance - 1 */ + code = d_code(dist); + //Assert (code < D_CODES, "bad d_code"); - if (windowBits === 8) { - windowBits = 9; - } - /* until 256-byte window bug fixed */ + send_code(s, code, dtree); /* send the distance code */ + extra = extra_dbits[code]; + if (extra !== 0) { + dist -= base_dist[code]; + send_bits(s, dist, extra); /* send the extra distance bits */ + } + } /* literal or match pair ? */ - const s = new DeflateState(); + /* Check that the overlay between pending_buf and sym_buf is ok: */ + //Assert(s->pending < s->lit_bufsize + sx, "pendingBuf overflow"); - strm.state = s; - s.strm = strm; + } while (sx < s.sym_next); + } - s.wrap = wrap; - s.gzhead = null; - s.w_bits = windowBits; - s.w_size = 1 << s.w_bits; - s.w_mask = s.w_size - 1; + send_code(s, END_BLOCK, ltree); +}; - s.hash_bits = memLevel + 7; - s.hash_size = 1 << s.hash_bits; - s.hash_mask = s.hash_size - 1; - s.hash_shift = ~~((s.hash_bits + MIN_MATCH - 1) / MIN_MATCH); - s.window = new Uint8Array(s.w_size * 2); - s.head = new Uint16Array(s.hash_size); - s.prev = new Uint16Array(s.w_size); +/* =========================================================================== + * Construct one Huffman tree and assigns the code bit strings and lengths. + * Update the total bit length for the current block. + * IN assertion: the field freq is set for all tree elements. + * OUT assertions: the fields len and code are set to the optimal bit length + * and corresponding code. The length opt_len is updated; static_len is + * also updated if stree is not null. The field max_code is set. + */ +const build_tree = (s, desc) => { +// deflate_state *s; +// tree_desc *desc; /* the tree descriptor */ - // Don't need mem init magic for JS. - //s.high_water = 0; /* nothing written to s->window yet */ + const tree = desc.dyn_tree; + const stree = desc.stat_desc.static_tree; + const has_stree = desc.stat_desc.has_stree; + const elems = desc.stat_desc.elems; + let n, m; /* iterate over heap elements */ + let max_code = -1; /* largest code with non zero frequency */ + let node; /* new node being created */ - s.lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */ + /* Construct the initial heap, with least frequent element in + * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. + * heap[0] is not used. + */ + s.heap_len = 0; + s.heap_max = HEAP_SIZE; - s.pending_buf_size = s.lit_bufsize * 4; + for (n = 0; n < elems; n++) { + if (tree[n * 2]/*.Freq*/ !== 0) { + s.heap[++s.heap_len] = max_code = n; + s.depth[n] = 0; - //overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2); - //s->pending_buf = (uchf *) overlay; - s.pending_buf = new Uint8Array(s.pending_buf_size); + } else { + tree[n * 2 + 1]/*.Len*/ = 0; + } + } - // It is offset from `s.pending_buf` (size is `s.lit_bufsize * 2`) - //s->d_buf = overlay + s->lit_bufsize/sizeof(ush); - s.d_buf = 1 * s.lit_bufsize; + /* The pkzip format requires that at least one distance code exists, + * and that at least one bit should be sent even if there is only one + * possible code. So to avoid special checks later on we force at least + * two codes of non zero frequency. + */ + while (s.heap_len < 2) { + node = s.heap[++s.heap_len] = (max_code < 2 ? ++max_code : 0); + tree[node * 2]/*.Freq*/ = 1; + s.depth[node] = 0; + s.opt_len--; - //s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize; - s.l_buf = (1 + 2) * s.lit_bufsize; + if (has_stree) { + s.static_len -= stree[node * 2 + 1]/*.Len*/; + } + /* node is 0 or 1 so it does not have extra bits */ + } + desc.max_code = max_code; - s.level = level; - s.strategy = strategy; - s.method = method; + /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, + * establish sub-heaps of increasing lengths: + */ + for (n = (s.heap_len >> 1/*int /2*/); n >= 1; n--) { pqdownheap(s, tree, n); } - return deflateReset(strm); -}; + /* Construct the Huffman tree by repeatedly combining the least two + * frequent nodes. + */ + node = elems; /* next internal node of the tree */ + do { + //pqremove(s, tree, n); /* n = node of least frequency */ + /*** pqremove ***/ + n = s.heap[1/*SMALLEST*/]; + s.heap[1/*SMALLEST*/] = s.heap[s.heap_len--]; + pqdownheap(s, tree, 1/*SMALLEST*/); + /***/ -const deflateInit = (strm, level) => { + m = s.heap[1/*SMALLEST*/]; /* m = node of next least frequency */ - return deflateInit2(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY); + s.heap[--s.heap_max] = n; /* keep the nodes sorted by frequency */ + s.heap[--s.heap_max] = m; + + /* Create a new node father of n and m */ + tree[node * 2]/*.Freq*/ = tree[n * 2]/*.Freq*/ + tree[m * 2]/*.Freq*/; + s.depth[node] = (s.depth[n] >= s.depth[m] ? s.depth[n] : s.depth[m]) + 1; + tree[n * 2 + 1]/*.Dad*/ = tree[m * 2 + 1]/*.Dad*/ = node; + + /* and insert the new node in the heap */ + s.heap[1/*SMALLEST*/] = node++; + pqdownheap(s, tree, 1/*SMALLEST*/); + + } while (s.heap_len >= 2); + + s.heap[--s.heap_max] = s.heap[1/*SMALLEST*/]; + + /* At this point, the fields freq and dad are set. We can now + * generate the bit lengths. + */ + gen_bitlen(s, desc); + + /* The field len is now set, we can generate the bit codes */ + gen_codes(tree, max_code, s.bl_count); }; -const deflate = (strm, flush) => { +/* =========================================================================== + * Scan a literal or distance tree to determine the frequencies of the codes + * in the bit length tree. + */ +const scan_tree = (s, tree, max_code) => { +// deflate_state *s; +// ct_data *tree; /* the tree to be scanned */ +// int max_code; /* and its largest code of non zero frequency */ - let beg, val; // for gzip header write only + let n; /* iterates over all tree elements */ + let prevlen = -1; /* last emitted length */ + let curlen; /* length of current code */ - if (!strm || !strm.state || - flush > Z_BLOCK || flush < 0) { - return strm ? err(strm, Z_STREAM_ERROR) : Z_STREAM_ERROR; - } + let nextlen = tree[0 * 2 + 1]/*.Len*/; /* length of next code */ - const s = strm.state; + let count = 0; /* repeat count of the current code */ + let max_count = 7; /* max repeat count */ + let min_count = 4; /* min repeat count */ - if (!strm.output || - (!strm.input && strm.avail_in !== 0) || - (s.status === FINISH_STATE && flush !== Z_FINISH)) { - return err(strm, (strm.avail_out === 0) ? Z_BUF_ERROR : Z_STREAM_ERROR); + if (nextlen === 0) { + max_count = 138; + min_count = 3; } + tree[(max_code + 1) * 2 + 1]/*.Len*/ = 0xffff; /* guard */ - s.strm = strm; /* just in case */ - const old_flush = s.last_flush; - s.last_flush = flush; + for (n = 0; n <= max_code; n++) { + curlen = nextlen; + nextlen = tree[(n + 1) * 2 + 1]/*.Len*/; - /* Write the header */ - if (s.status === INIT_STATE) { + if (++count < max_count && curlen === nextlen) { + continue; - if (s.wrap === 2) { // GZIP header - strm.adler = 0; //crc32(0L, Z_NULL, 0); - put_byte(s, 31); - put_byte(s, 139); - put_byte(s, 8); - if (!s.gzhead) { // s->gzhead == Z_NULL - put_byte(s, 0); - put_byte(s, 0); - put_byte(s, 0); - put_byte(s, 0); - put_byte(s, 0); - put_byte(s, s.level === 9 ? 2 : - (s.strategy >= Z_HUFFMAN_ONLY || s.level < 2 ? - 4 : 0)); - put_byte(s, OS_CODE); - s.status = BUSY_STATE; - } - else { - put_byte(s, (s.gzhead.text ? 1 : 0) + - (s.gzhead.hcrc ? 2 : 0) + - (!s.gzhead.extra ? 0 : 4) + - (!s.gzhead.name ? 0 : 8) + - (!s.gzhead.comment ? 0 : 16) - ); - put_byte(s, s.gzhead.time & 0xff); - put_byte(s, (s.gzhead.time >> 8) & 0xff); - put_byte(s, (s.gzhead.time >> 16) & 0xff); - put_byte(s, (s.gzhead.time >> 24) & 0xff); - put_byte(s, s.level === 9 ? 2 : - (s.strategy >= Z_HUFFMAN_ONLY || s.level < 2 ? - 4 : 0)); - put_byte(s, s.gzhead.os & 0xff); - if (s.gzhead.extra && s.gzhead.extra.length) { - put_byte(s, s.gzhead.extra.length & 0xff); - put_byte(s, (s.gzhead.extra.length >> 8) & 0xff); - } - if (s.gzhead.hcrc) { - strm.adler = crc32(strm.adler, s.pending_buf, s.pending, 0); - } - s.gzindex = 0; - s.status = EXTRA_STATE; - } - } - else // DEFLATE header - { - let header = (Z_DEFLATED + ((s.w_bits - 8) << 4)) << 8; - let level_flags = -1; - - if (s.strategy >= Z_HUFFMAN_ONLY || s.level < 2) { - level_flags = 0; - } else if (s.level < 6) { - level_flags = 1; - } else if (s.level === 6) { - level_flags = 2; - } else { - level_flags = 3; - } - header |= (level_flags << 6); - if (s.strstart !== 0) { header |= PRESET_DICT; } - header += 31 - (header % 31); + } else if (count < min_count) { + s.bl_tree[curlen * 2]/*.Freq*/ += count; - s.status = BUSY_STATE; - putShortMSB(s, header); + } else if (curlen !== 0) { - /* Save the adler32 of the preset dictionary: */ - if (s.strstart !== 0) { - putShortMSB(s, strm.adler >>> 16); - putShortMSB(s, strm.adler & 0xffff); - } - strm.adler = 1; // adler32(0L, Z_NULL, 0); - } - } + if (curlen !== prevlen) { s.bl_tree[curlen * 2]/*.Freq*/++; } + s.bl_tree[REP_3_6 * 2]/*.Freq*/++; -//#ifdef GZIP - if (s.status === EXTRA_STATE) { - if (s.gzhead.extra/* != Z_NULL*/) { - beg = s.pending; /* start of bytes to update crc */ + } else if (count <= 10) { + s.bl_tree[REPZ_3_10 * 2]/*.Freq*/++; - while (s.gzindex < (s.gzhead.extra.length & 0xffff)) { - if (s.pending === s.pending_buf_size) { - if (s.gzhead.hcrc && s.pending > beg) { - strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); - } - flush_pending(strm); - beg = s.pending; - if (s.pending === s.pending_buf_size) { - break; - } - } - put_byte(s, s.gzhead.extra[s.gzindex] & 0xff); - s.gzindex++; - } - if (s.gzhead.hcrc && s.pending > beg) { - strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); - } - if (s.gzindex === s.gzhead.extra.length) { - s.gzindex = 0; - s.status = NAME_STATE; - } + } else { + s.bl_tree[REPZ_11_138 * 2]/*.Freq*/++; } - else { - s.status = NAME_STATE; + + count = 0; + prevlen = curlen; + + if (nextlen === 0) { + max_count = 138; + min_count = 3; + + } else if (curlen === nextlen) { + max_count = 6; + min_count = 3; + + } else { + max_count = 7; + min_count = 4; } } - if (s.status === NAME_STATE) { - if (s.gzhead.name/* != Z_NULL*/) { - beg = s.pending; /* start of bytes to update crc */ - //int val; +}; - do { - if (s.pending === s.pending_buf_size) { - if (s.gzhead.hcrc && s.pending > beg) { - strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); - } - flush_pending(strm); - beg = s.pending; - if (s.pending === s.pending_buf_size) { - val = 1; - break; - } - } - // JS specific: little magic to add zero terminator to end of string - if (s.gzindex < s.gzhead.name.length) { - val = s.gzhead.name.charCodeAt(s.gzindex++) & 0xff; - } else { - val = 0; - } - put_byte(s, val); - } while (val !== 0); - if (s.gzhead.hcrc && s.pending > beg) { - strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); - } - if (val === 0) { - s.gzindex = 0; - s.status = COMMENT_STATE; - } - } - else { - s.status = COMMENT_STATE; - } +/* =========================================================================== + * Send a literal or distance tree in compressed form, using the codes in + * bl_tree. + */ +const send_tree = (s, tree, max_code) => { +// deflate_state *s; +// ct_data *tree; /* the tree to be scanned */ +// int max_code; /* and its largest code of non zero frequency */ + + let n; /* iterates over all tree elements */ + let prevlen = -1; /* last emitted length */ + let curlen; /* length of current code */ + + let nextlen = tree[0 * 2 + 1]/*.Len*/; /* length of next code */ + + let count = 0; /* repeat count of the current code */ + let max_count = 7; /* max repeat count */ + let min_count = 4; /* min repeat count */ + + /* tree[max_code+1].Len = -1; */ /* guard already set */ + if (nextlen === 0) { + max_count = 138; + min_count = 3; } - if (s.status === COMMENT_STATE) { - if (s.gzhead.comment/* != Z_NULL*/) { - beg = s.pending; /* start of bytes to update crc */ - //int val; - do { - if (s.pending === s.pending_buf_size) { - if (s.gzhead.hcrc && s.pending > beg) { - strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); - } - flush_pending(strm); - beg = s.pending; - if (s.pending === s.pending_buf_size) { - val = 1; - break; - } - } - // JS specific: little magic to add zero terminator to end of string - if (s.gzindex < s.gzhead.comment.length) { - val = s.gzhead.comment.charCodeAt(s.gzindex++) & 0xff; - } else { - val = 0; - } - put_byte(s, val); - } while (val !== 0); + for (n = 0; n <= max_code; n++) { + curlen = nextlen; + nextlen = tree[(n + 1) * 2 + 1]/*.Len*/; - if (s.gzhead.hcrc && s.pending > beg) { - strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); - } - if (val === 0) { - s.status = HCRC_STATE; + if (++count < max_count && curlen === nextlen) { + continue; + + } else if (count < min_count) { + do { send_code(s, curlen, s.bl_tree); } while (--count !== 0); + + } else if (curlen !== 0) { + if (curlen !== prevlen) { + send_code(s, curlen, s.bl_tree); + count--; } + //Assert(count >= 3 && count <= 6, " 3_6?"); + send_code(s, REP_3_6, s.bl_tree); + send_bits(s, count - 3, 2); + + } else if (count <= 10) { + send_code(s, REPZ_3_10, s.bl_tree); + send_bits(s, count - 3, 3); + + } else { + send_code(s, REPZ_11_138, s.bl_tree); + send_bits(s, count - 11, 7); } - else { - s.status = HCRC_STATE; + + count = 0; + prevlen = curlen; + if (nextlen === 0) { + max_count = 138; + min_count = 3; + + } else if (curlen === nextlen) { + max_count = 6; + min_count = 3; + + } else { + max_count = 7; + min_count = 4; } } - if (s.status === HCRC_STATE) { - if (s.gzhead.hcrc) { - if (s.pending + 2 > s.pending_buf_size) { - flush_pending(strm); - } - if (s.pending + 2 <= s.pending_buf_size) { - put_byte(s, strm.adler & 0xff); - put_byte(s, (strm.adler >> 8) & 0xff); - strm.adler = 0; //crc32(0L, Z_NULL, 0); - s.status = BUSY_STATE; - } - } - else { - s.status = BUSY_STATE; +}; + + +/* =========================================================================== + * Construct the Huffman tree for the bit lengths and return the index in + * bl_order of the last bit length code to send. + */ +const build_bl_tree = (s) => { + + let max_blindex; /* index of last bit length code of non zero freq */ + + /* Determine the bit length frequencies for literal and distance trees */ + scan_tree(s, s.dyn_ltree, s.l_desc.max_code); + scan_tree(s, s.dyn_dtree, s.d_desc.max_code); + + /* Build the bit length tree: */ + build_tree(s, s.bl_desc); + /* opt_len now includes the length of the tree representations, except + * the lengths of the bit lengths codes and the 5+5+4 bits for the counts. + */ + + /* Determine the number of bit length codes to send. The pkzip format + * requires that at least 4 bit length codes be sent. (appnote.txt says + * 3 but the actual value used is 4.) + */ + for (max_blindex = BL_CODES - 1; max_blindex >= 3; max_blindex--) { + if (s.bl_tree[bl_order[max_blindex] * 2 + 1]/*.Len*/ !== 0) { + break; } } -//#endif + /* Update opt_len to include the bit length tree and counts */ + s.opt_len += 3 * (max_blindex + 1) + 5 + 5 + 4; + //Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", + // s->opt_len, s->static_len)); - /* Flush as much pending output as possible */ - if (s.pending !== 0) { - flush_pending(strm); - if (strm.avail_out === 0) { - /* Since avail_out is 0, deflate will be called again with - * more output space, but possibly with both pending and - * avail_in equal to zero. There won't be anything to do, - * but this is not an error situation so make sure we - * return OK instead of BUF_ERROR at next call of deflate: - */ - s.last_flush = -1; - return Z_OK; - } + return max_blindex; +}; - /* Make sure there is something to do and avoid duplicate consecutive - * flushes. For repeated and useless calls with Z_FINISH, we keep - * returning Z_STREAM_END instead of Z_BUF_ERROR. - */ - } else if (strm.avail_in === 0 && rank(flush) <= rank(old_flush) && - flush !== Z_FINISH) { - return err(strm, Z_BUF_ERROR); - } - /* User must not provide more input after the first FINISH: */ - if (s.status === FINISH_STATE && strm.avail_in !== 0) { - return err(strm, Z_BUF_ERROR); +/* =========================================================================== + * Send the header for a block using dynamic Huffman trees: the counts, the + * lengths of the bit length codes, the literal tree and the distance tree. + * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. + */ +const send_all_trees = (s, lcodes, dcodes, blcodes) => { +// deflate_state *s; +// int lcodes, dcodes, blcodes; /* number of codes for each tree */ + + let rank; /* index in bl_order */ + + //Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); + //Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, + // "too many codes"); + //Tracev((stderr, "\nbl counts: ")); + send_bits(s, lcodes - 257, 5); /* not +255 as stated in appnote.txt */ + send_bits(s, dcodes - 1, 5); + send_bits(s, blcodes - 4, 4); /* not -3 as stated in appnote.txt */ + for (rank = 0; rank < blcodes; rank++) { + //Tracev((stderr, "\nbl code %2d ", bl_order[rank])); + send_bits(s, s.bl_tree[bl_order[rank] * 2 + 1]/*.Len*/, 3); } + //Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent)); - /* Start a new block or continue the current one. - */ - if (strm.avail_in !== 0 || s.lookahead !== 0 || - (flush !== Z_NO_FLUSH && s.status !== FINISH_STATE)) { - let bstate = (s.strategy === Z_HUFFMAN_ONLY) ? deflate_huff(s, flush) : - (s.strategy === Z_RLE ? deflate_rle(s, flush) : - configuration_table[s.level].func(s, flush)); + send_tree(s, s.dyn_ltree, lcodes - 1); /* literal tree */ + //Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent)); - if (bstate === BS_FINISH_STARTED || bstate === BS_FINISH_DONE) { - s.status = FINISH_STATE; - } - if (bstate === BS_NEED_MORE || bstate === BS_FINISH_STARTED) { - if (strm.avail_out === 0) { - s.last_flush = -1; - /* avoid BUF_ERROR next call, see above */ - } - return Z_OK; - /* If flush != Z_NO_FLUSH && avail_out == 0, the next call - * of deflate should use the same flush parameter to make sure - * that the flush is complete. So we don't have to output an - * empty block here, this will be done at next call. This also - * ensures that for a very small output buffer, we emit at most - * one empty block. - */ - } - if (bstate === BS_BLOCK_DONE) { - if (flush === Z_PARTIAL_FLUSH) { - _tr_align(s); - } - else if (flush !== Z_BLOCK) { /* FULL_FLUSH or SYNC_FLUSH */ + send_tree(s, s.dyn_dtree, dcodes - 1); /* distance tree */ + //Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent)); +}; - _tr_stored_block(s, 0, 0, false); - /* For a full flush, this empty block will be recognized - * as a special marker by inflate_sync(). - */ - if (flush === Z_FULL_FLUSH) { - /*** CLEAR_HASH(s); ***/ /* forget history */ - zero(s.head); // Fill with NIL (= 0); - if (s.lookahead === 0) { - s.strstart = 0; - s.block_start = 0; - s.insert = 0; - } - } - } - flush_pending(strm); - if (strm.avail_out === 0) { - s.last_flush = -1; /* avoid BUF_ERROR at next call, see above */ - return Z_OK; - } +/* =========================================================================== + * Check if the data type is TEXT or BINARY, using the following algorithm: + * - TEXT if the two conditions below are satisfied: + * a) There are no non-portable control characters belonging to the + * "block list" (0..6, 14..25, 28..31). + * b) There is at least one printable character belonging to the + * "allow list" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255). + * - BINARY otherwise. + * - The following partially-portable control characters form a + * "gray list" that is ignored in this detection algorithm: + * (7 {BEL}, 8 {BS}, 11 {VT}, 12 {FF}, 26 {SUB}, 27 {ESC}). + * IN assertion: the fields Freq of dyn_ltree are set. + */ +const detect_data_type = (s) => { + /* block_mask is the bit mask of block-listed bytes + * set bits 0..6, 14..25, and 28..31 + * 0xf3ffc07f = binary 11110011111111111100000001111111 + */ + let block_mask = 0xf3ffc07f; + let n; + + /* Check for non-textual ("block-listed") bytes. */ + for (n = 0; n <= 31; n++, block_mask >>>= 1) { + if ((block_mask & 1) && (s.dyn_ltree[n * 2]/*.Freq*/ !== 0)) { + return Z_BINARY; } } - //Assert(strm->avail_out > 0, "bug2"); - //if (strm.avail_out <= 0) { throw new Error("bug2");} - - if (flush !== Z_FINISH) { return Z_OK; } - if (s.wrap <= 0) { return Z_STREAM_END; } - /* Write the trailer */ - if (s.wrap === 2) { - put_byte(s, strm.adler & 0xff); - put_byte(s, (strm.adler >> 8) & 0xff); - put_byte(s, (strm.adler >> 16) & 0xff); - put_byte(s, (strm.adler >> 24) & 0xff); - put_byte(s, strm.total_in & 0xff); - put_byte(s, (strm.total_in >> 8) & 0xff); - put_byte(s, (strm.total_in >> 16) & 0xff); - put_byte(s, (strm.total_in >> 24) & 0xff); + /* Check for textual ("allow-listed") bytes. */ + if (s.dyn_ltree[9 * 2]/*.Freq*/ !== 0 || s.dyn_ltree[10 * 2]/*.Freq*/ !== 0 || + s.dyn_ltree[13 * 2]/*.Freq*/ !== 0) { + return Z_TEXT; } - else - { - putShortMSB(s, strm.adler >>> 16); - putShortMSB(s, strm.adler & 0xffff); + for (n = 32; n < LITERALS; n++) { + if (s.dyn_ltree[n * 2]/*.Freq*/ !== 0) { + return Z_TEXT; + } } - flush_pending(strm); - /* If avail_out is zero, the application will call deflate again - * to flush the rest. + /* There are no "block-listed" or "allow-listed" bytes: + * this stream either is empty or has tolerated ("gray-listed") bytes only. */ - if (s.wrap > 0) { s.wrap = -s.wrap; } - /* write the trailer only once! */ - return s.pending !== 0 ? Z_OK : Z_STREAM_END; + return Z_BINARY; }; -const deflateEnd = (strm) => { +let static_init_done = false; - if (!strm/*== Z_NULL*/ || !strm.state/*== Z_NULL*/) { - return Z_STREAM_ERROR; - } +/* =========================================================================== + * Initialize the tree data structures for a new zlib stream. + */ +const _tr_init = (s) => +{ - const status = strm.state.status; - if (status !== INIT_STATE && - status !== EXTRA_STATE && - status !== NAME_STATE && - status !== COMMENT_STATE && - status !== HCRC_STATE && - status !== BUSY_STATE && - status !== FINISH_STATE - ) { - return err(strm, Z_STREAM_ERROR); + if (!static_init_done) { + tr_static_init(); + static_init_done = true; } - strm.state = null; + s.l_desc = new TreeDesc(s.dyn_ltree, static_l_desc); + s.d_desc = new TreeDesc(s.dyn_dtree, static_d_desc); + s.bl_desc = new TreeDesc(s.bl_tree, static_bl_desc); - return status === BUSY_STATE ? err(strm, Z_DATA_ERROR) : Z_OK; + s.bi_buf = 0; + s.bi_valid = 0; + + /* Initialize the first block of the first file: */ + init_block(s); }; -/* ========================================================================= - * Initializes the compression dictionary from the given byte - * sequence without producing any compressed output. +/* =========================================================================== + * Send a stored block */ -const deflateSetDictionary = (strm, dictionary) => { - - let dictLength = dictionary.length; +const _tr_stored_block = (s, buf, stored_len, last) => { +//DeflateState *s; +//charf *buf; /* input block */ +//ulg stored_len; /* length of input block */ +//int last; /* one if this is the last block for a file */ - if (!strm/*== Z_NULL*/ || !strm.state/*== Z_NULL*/) { - return Z_STREAM_ERROR; + send_bits(s, (STORED_BLOCK << 1) + (last ? 1 : 0), 3); /* send block type */ + bi_windup(s); /* align on byte boundary */ + put_short(s, stored_len); + put_short(s, ~stored_len); + if (stored_len) { + s.pending_buf.set(s.window.subarray(buf, buf + stored_len), s.pending); } + s.pending += stored_len; +}; - const s = strm.state; - const wrap = s.wrap; - - if (wrap === 2 || (wrap === 1 && s.status !== INIT_STATE) || s.lookahead) { - return Z_STREAM_ERROR; - } - /* when using zlib wrappers, compute Adler-32 for provided dictionary */ - if (wrap === 1) { - /* adler32(strm->adler, dictionary, dictLength); */ - strm.adler = adler32(strm.adler, dictionary, dictLength, 0); - } +/* =========================================================================== + * Send one empty static block to give enough lookahead for inflate. + * This takes 10 bits, of which 7 may remain in the bit buffer. + */ +const _tr_align = (s) => { + send_bits(s, STATIC_TREES << 1, 3); + send_code(s, END_BLOCK, static_ltree); + bi_flush(s); +}; - s.wrap = 0; /* avoid computing Adler-32 in read_buf */ - /* if dictionary would fill window, just replace the history */ - if (dictLength >= s.w_size) { - if (wrap === 0) { /* already empty otherwise */ - /*** CLEAR_HASH(s); ***/ - zero(s.head); // Fill with NIL (= 0); - s.strstart = 0; - s.block_start = 0; - s.insert = 0; +/* =========================================================================== + * Determine the best encoding for the current block: dynamic trees, static + * trees or store, and write out the encoded block. + */ +const _tr_flush_block = (s, buf, stored_len, last) => { +//DeflateState *s; +//charf *buf; /* input block, or NULL if too old */ +//ulg stored_len; /* length of input block */ +//int last; /* one if this is the last block for a file */ + + let opt_lenb, static_lenb; /* opt_len and static_len in bytes */ + let max_blindex = 0; /* index of last bit length code of non zero freq */ + + /* Build the Huffman trees unless a stored block is forced */ + if (s.level > 0) { + + /* Check if the file is binary or text */ + if (s.strm.data_type === Z_UNKNOWN) { + s.strm.data_type = detect_data_type(s); } - /* use the tail */ - // dictionary = dictionary.slice(dictLength - s.w_size); - let tmpDict = new Uint8Array(s.w_size); - tmpDict.set(dictionary.subarray(dictLength - s.w_size, dictLength), 0); - dictionary = tmpDict; - dictLength = s.w_size; + + /* Construct the literal and distance trees */ + build_tree(s, s.l_desc); + // Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len, + // s->static_len)); + + build_tree(s, s.d_desc); + // Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len, + // s->static_len)); + /* At this point, opt_len and static_len are the total bit lengths of + * the compressed block data, excluding the tree representations. + */ + + /* Build the bit length tree for the above two trees, and get the index + * in bl_order of the last bit length code to send. + */ + max_blindex = build_bl_tree(s); + + /* Determine the best encoding. Compute the block lengths in bytes. */ + opt_lenb = (s.opt_len + 3 + 7) >>> 3; + static_lenb = (s.static_len + 3 + 7) >>> 3; + + // Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ", + // opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, + // s->sym_next / 3)); + + if (static_lenb <= opt_lenb) { opt_lenb = static_lenb; } + + } else { + // Assert(buf != (char*)0, "lost buf"); + opt_lenb = static_lenb = stored_len + 5; /* force a stored block */ } - /* insert dictionary into window and hash */ - const avail = strm.avail_in; - const next = strm.next_in; - const input = strm.input; - strm.avail_in = dictLength; - strm.next_in = 0; - strm.input = dictionary; - fill_window(s); - while (s.lookahead >= MIN_MATCH) { - let str = s.strstart; - let n = s.lookahead - (MIN_MATCH - 1); - do { - /* UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); */ - s.ins_h = HASH(s, s.ins_h, s.window[str + MIN_MATCH - 1]); - s.prev[str & s.w_mask] = s.head[s.ins_h]; + if ((stored_len + 4 <= opt_lenb) && (buf !== -1)) { + /* 4: two words for the lengths */ - s.head[s.ins_h] = str; - str++; - } while (--n); - s.strstart = str; - s.lookahead = MIN_MATCH - 1; - fill_window(s); + /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. + * Otherwise we can't have processed more than WSIZE input bytes since + * the last block flush, because compression would have been + * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to + * transform a block into a stored block. + */ + _tr_stored_block(s, buf, stored_len, last); + + } else if (s.strategy === Z_FIXED || static_lenb === opt_lenb) { + + send_bits(s, (STATIC_TREES << 1) + (last ? 1 : 0), 3); + compress_block(s, static_ltree, static_dtree); + + } else { + send_bits(s, (DYN_TREES << 1) + (last ? 1 : 0), 3); + send_all_trees(s, s.l_desc.max_code + 1, s.d_desc.max_code + 1, max_blindex + 1); + compress_block(s, s.dyn_ltree, s.dyn_dtree); } - s.strstart += s.lookahead; - s.block_start = s.strstart; - s.insert = s.lookahead; - s.lookahead = 0; - s.match_length = s.prev_length = MIN_MATCH - 1; - s.match_available = 0; - strm.next_in = next; - strm.input = input; - strm.avail_in = avail; - s.wrap = wrap; - return Z_OK; + // Assert (s->compressed_len == s->bits_sent, "bad compressed size"); + /* The above check is made mod 2^32, for files larger than 512 MB + * and uLong implemented on 32 bits. + */ + init_block(s); + + if (last) { + bi_windup(s); + } + // Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3, + // s->compressed_len-7*last)); }; +/* =========================================================================== + * Save the match info and tally the frequency counts. Return true if + * the current block must be flushed. + */ +const _tr_tally = (s, dist, lc) => { +// deflate_state *s; +// unsigned dist; /* distance of matched string */ +// unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */ + + s.pending_buf[s.sym_buf + s.sym_next++] = dist; + s.pending_buf[s.sym_buf + s.sym_next++] = dist >> 8; + s.pending_buf[s.sym_buf + s.sym_next++] = lc; + if (dist === 0) { + /* lc is the unmatched char */ + s.dyn_ltree[lc * 2]/*.Freq*/++; + } else { + s.matches++; + /* Here, lc is the match length - MIN_MATCH */ + dist--; /* dist = match distance - 1 */ + //Assert((ush)dist < (ush)MAX_DIST(s) && + // (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && + // (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match"); -module.exports.deflateInit = deflateInit; -module.exports.deflateInit2 = deflateInit2; -module.exports.deflateReset = deflateReset; -module.exports.deflateResetKeep = deflateResetKeep; -module.exports.deflateSetHeader = deflateSetHeader; -module.exports.deflate = deflate; -module.exports.deflateEnd = deflateEnd; -module.exports.deflateSetDictionary = deflateSetDictionary; -module.exports.deflateInfo = 'pako deflate (from Nodeca project)'; + s.dyn_ltree[(_length_code[lc] + LITERALS + 1) * 2]/*.Freq*/++; + s.dyn_dtree[d_code(dist) * 2]/*.Freq*/++; + } -/* Not implemented -module.exports.deflateBound = deflateBound; -module.exports.deflateCopy = deflateCopy; -module.exports.deflateParams = deflateParams; -module.exports.deflatePending = deflatePending; -module.exports.deflatePrime = deflatePrime; -module.exports.deflateTune = deflateTune; -*/ + return (s.sym_next === s.sym_end); +}; -},{"./adler32":70,"./constants":71,"./crc32":72,"./messages":78,"./trees":79}],74:[function(require,module,exports){ +module.exports._tr_init = _tr_init; +module.exports._tr_stored_block = _tr_stored_block; +module.exports._tr_flush_block = _tr_flush_block; +module.exports._tr_tally = _tr_tally; +module.exports._tr_align = _tr_align; + +},{}],80:[function(require,module,exports){ 'use strict'; // (C) 1995-2013 Jean-loup Gailly and Mark Adler @@ -17416,20797 +17685,16194 @@ module.exports.deflateTune = deflateTune; // misrepresented as being the original software. // 3. This notice may not be removed or altered from any source distribution. -function GZheader() { - /* true if compressed data believed to be text */ - this.text = 0; - /* modification time */ - this.time = 0; - /* extra flags (not used when writing a gzip file) */ - this.xflags = 0; - /* operating system */ - this.os = 0; - /* pointer to extra field or Z_NULL if none */ - this.extra = null; - /* extra field length (valid if extra != Z_NULL) */ - this.extra_len = 0; // Actually, we don't need it in JS, - // but leave for few code modifications +function ZStream() { + /* next input byte */ + this.input = null; // JS specific, because we have no pointers + this.next_in = 0; + /* number of bytes available at input */ + this.avail_in = 0; + /* total number of input bytes read so far */ + this.total_in = 0; + /* next output byte should be put there */ + this.output = null; // JS specific, because we have no pointers + this.next_out = 0; + /* remaining free space at output */ + this.avail_out = 0; + /* total number of bytes output so far */ + this.total_out = 0; + /* last error message, NULL if no error */ + this.msg = ''/*Z_NULL*/; + /* not visible by applications */ + this.state = null; + /* best guess about the data type: binary or text */ + this.data_type = 2/*Z_UNKNOWN*/; + /* adler32 value of the uncompressed data */ + this.adler = 0; +} - // - // Setup limits is not necessary because in js we should not preallocate memory - // for inflate use constant limit in 65536 bytes - // +module.exports = ZStream; - /* space at extra (only when reading header) */ - // this.extra_max = 0; - /* pointer to zero-terminated file name or Z_NULL */ - this.name = ''; - /* space at name (only when reading header) */ - // this.name_max = 0; - /* pointer to zero-terminated comment or Z_NULL */ - this.comment = ''; - /* space at comment (only when reading header) */ - // this.comm_max = 0; - /* true if there was or will be a header crc */ - this.hcrc = 0; - /* true when done reading gzip header (not used when writing a gzip file) */ - this.done = false; -} +},{}],81:[function(require,module,exports){ +const uuid = require('./uuid') +const Frontend = require('../frontend') +const { OPTIONS } = require('../frontend/constants') +const { encodeChange, decodeChange } = require('../backend/columnar') +const { isObject } = require('./common') +let backend = require('../backend') // mutable: can be overridden with setDefaultBackend() -module.exports = GZheader; +/** + * Automerge.* API + * The functions in this file constitute the publicly facing Automerge API which combines + * the features of the Frontend (a document interface) and the backend (CRDT operations) + */ -},{}],75:[function(require,module,exports){ -'use strict'; +function init(options) { + if (typeof options === 'string') { + options = {actorId: options} + } else if (typeof options === 'undefined') { + options = {} + } else if (!isObject(options)) { + throw new TypeError(`Unsupported options for init(): ${options}`) + } + return Frontend.init(Object.assign({backend}, options)) +} -// (C) 1995-2013 Jean-loup Gailly and Mark Adler -// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +/** + * Returns a new document object initialized with the given state. + */ +function from(initialState, options) { + const changeOpts = {message: 'Initialization'} + return change(init(options), changeOpts, doc => Object.assign(doc, initialState)) +} -// See state defs from inflate.js -const BAD = 30; /* got a data error -- remain here until reset */ -const TYPE = 12; /* i: waiting for type bits, including last-flag bit */ +function change(doc, options, callback) { + const [newDoc] = Frontend.change(doc, options, callback) + return newDoc +} -/* - Decode literal, length, and distance codes and write out the resulting - literal and match bytes until either not enough input or output is - available, an end-of-block is encountered, or a data error is encountered. - When large enough input and output buffers are supplied to inflate(), for - example, a 16K input buffer and a 64K output buffer, more than 95% of the - inflate execution time is spent in this routine. +function emptyChange(doc, options) { + const [newDoc] = Frontend.emptyChange(doc, options) + return newDoc +} - Entry assumptions: +function clone(doc, options = {}) { + const state = backend.clone(Frontend.getBackendState(doc, 'clone')) + return applyPatch(init(options), backend.getPatch(state), state, [], options) +} - state.mode === LEN - strm.avail_in >= 6 - strm.avail_out >= 258 - start >= strm.avail_out - state.bits < 8 +function free(doc) { + backend.free(Frontend.getBackendState(doc, 'free')) +} - On return, state.mode is one of: +function load(data, options = {}) { + const state = backend.load(data) + return applyPatch(init(options), backend.getPatch(state), state, [data], options) +} - LEN -- ran out of enough output space or enough available input - TYPE -- reached end of block code, inflate() to interpret next block - BAD -- error in block data +function save(doc) { + return backend.save(Frontend.getBackendState(doc, 'save')) +} - Notes: +function merge(localDoc, remoteDoc) { + const localState = Frontend.getBackendState(localDoc, 'merge') + const remoteState = Frontend.getBackendState(remoteDoc, 'merge', 'second') + const changes = backend.getChangesAdded(localState, remoteState) + const [updatedDoc] = applyChanges(localDoc, changes) + return updatedDoc +} - - The maximum input bits used by a length/distance pair is 15 bits for the - length code, 5 bits for the length extra, 15 bits for the distance code, - and 13 bits for the distance extra. This totals 48 bits, or six bytes. - Therefore if strm.avail_in >= 6, then there is enough input to avoid - checking for available input while decoding. +function getChanges(oldDoc, newDoc) { + const oldState = Frontend.getBackendState(oldDoc, 'getChanges') + const newState = Frontend.getBackendState(newDoc, 'getChanges', 'second') + return backend.getChanges(newState, backend.getHeads(oldState)) +} - - The maximum bytes that a single length/distance pair can output is 258 - bytes, which is the maximum length that can be coded. inflate_fast() - requires strm.avail_out >= 258 for each loop to avoid checking for - output space. - */ -module.exports = function inflate_fast(strm, start) { - let _in; /* local strm.input */ - let last; /* have enough input while in < last */ - let _out; /* local strm.output */ - let beg; /* inflate()'s initial strm.output */ - let end; /* while out < end, enough space available */ -//#ifdef INFLATE_STRICT - let dmax; /* maximum distance from zlib header */ -//#endif - let wsize; /* window size or zero if not using window */ - let whave; /* valid bytes in the window */ - let wnext; /* window write index */ - // Use `s_window` instead `window`, avoid conflict with instrumentation tools - let s_window; /* allocated sliding window, if wsize != 0 */ - let hold; /* local strm.hold */ - let bits; /* local strm.bits */ - let lcode; /* local strm.lencode */ - let dcode; /* local strm.distcode */ - let lmask; /* mask for first level of length codes */ - let dmask; /* mask for first level of distance codes */ - let here; /* retrieved table entry */ - let op; /* code bits, operation, extra bits, or */ - /* window position, window bytes to copy */ - let len; /* match length, unused bytes */ - let dist; /* match distance */ - let from; /* where to copy match from */ - let from_source; +function getAllChanges(doc) { + return backend.getAllChanges(Frontend.getBackendState(doc, 'getAllChanges')) +} +function applyPatch(doc, patch, backendState, changes, options) { + const newDoc = Frontend.applyPatch(doc, patch, backendState) + const patchCallback = options.patchCallback || doc[OPTIONS].patchCallback + if (patchCallback) { + patchCallback(patch, doc, newDoc, false, changes) + } + return newDoc +} - let input, output; // JS specific, because we have no pointers +function applyChanges(doc, changes, options = {}) { + const oldState = Frontend.getBackendState(doc, 'applyChanges') + const [newState, patch] = backend.applyChanges(oldState, changes) + return [applyPatch(doc, patch, newState, changes, options), patch] +} - /* copy state to local variables */ - const state = strm.state; - //here = state.here; - _in = strm.next_in; - input = strm.input; - last = _in + (strm.avail_in - 5); - _out = strm.next_out; - output = strm.output; - beg = _out - (start - strm.avail_out); - end = _out + (strm.avail_out - 257); -//#ifdef INFLATE_STRICT - dmax = state.dmax; -//#endif - wsize = state.wsize; - whave = state.whave; - wnext = state.wnext; - s_window = state.window; - hold = state.hold; - bits = state.bits; - lcode = state.lencode; - dcode = state.distcode; - lmask = (1 << state.lenbits) - 1; - dmask = (1 << state.distbits) - 1; +function equals(val1, val2) { + if (!isObject(val1) || !isObject(val2)) return val1 === val2 + const keys1 = Object.keys(val1).sort(), keys2 = Object.keys(val2).sort() + if (keys1.length !== keys2.length) return false + for (let i = 0; i < keys1.length; i++) { + if (keys1[i] !== keys2[i]) return false + if (!equals(val1[keys1[i]], val2[keys2[i]])) return false + } + return true +} +function getHistory(doc) { + const actor = Frontend.getActorId(doc) + const history = getAllChanges(doc) + return history.map((change, index) => ({ + get change () { + return decodeChange(change) + }, + get snapshot () { + const state = backend.loadChanges(backend.init(), history.slice(0, index + 1)) + return Frontend.applyPatch(init(actor), backend.getPatch(state), state) + } + }) + ) +} - /* decode literals and length/distances until end-of-block or not enough - input data or output space */ +function generateSyncMessage(doc, syncState) { + const state = Frontend.getBackendState(doc, 'generateSyncMessage') + return backend.generateSyncMessage(state, syncState) +} - top: - do { - if (bits < 15) { - hold += input[_in++] << bits; - bits += 8; - hold += input[_in++] << bits; - bits += 8; - } +function receiveSyncMessage(doc, oldSyncState, message) { + const oldBackendState = Frontend.getBackendState(doc, 'receiveSyncMessage') + const [backendState, syncState, patch] = backend.receiveSyncMessage(oldBackendState, oldSyncState, message) + if (!patch) return [doc, syncState, patch] - here = lcode[hold & lmask]; + // The patchCallback is passed as argument all changes that are applied. + // We get those from the sync message if a patchCallback is present. + let changes = null + if (doc[OPTIONS].patchCallback) { + changes = backend.decodeSyncMessage(message).changes + } + return [applyPatch(doc, patch, backendState, changes, {}), syncState, patch] +} - dolen: - for (;;) { // Goto emulation - op = here >>> 24/*here.bits*/; - hold >>>= op; - bits -= op; - op = (here >>> 16) & 0xff/*here.op*/; - if (op === 0) { /* literal */ - //Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? - // "inflate: literal '%c'\n" : - // "inflate: literal 0x%02x\n", here.val)); - output[_out++] = here & 0xffff/*here.val*/; - } - else if (op & 16) { /* length base */ - len = here & 0xffff/*here.val*/; - op &= 15; /* number of extra bits */ - if (op) { - if (bits < op) { - hold += input[_in++] << bits; - bits += 8; - } - len += hold & ((1 << op) - 1); - hold >>>= op; - bits -= op; - } - //Tracevv((stderr, "inflate: length %u\n", len)); - if (bits < 15) { - hold += input[_in++] << bits; - bits += 8; - hold += input[_in++] << bits; - bits += 8; - } - here = dcode[hold & dmask]; +function initSyncState() { + return backend.initSyncState() +} - dodist: - for (;;) { // goto emulation - op = here >>> 24/*here.bits*/; - hold >>>= op; - bits -= op; - op = (here >>> 16) & 0xff/*here.op*/; +/** + * Replaces the default backend implementation with a different one. + * This allows you to switch to using the Rust/WebAssembly implementation. + */ +function setDefaultBackend(newBackend) { + backend = newBackend +} - if (op & 16) { /* distance base */ - dist = here & 0xffff/*here.val*/; - op &= 15; /* number of extra bits */ - if (bits < op) { - hold += input[_in++] << bits; - bits += 8; - if (bits < op) { - hold += input[_in++] << bits; - bits += 8; - } - } - dist += hold & ((1 << op) - 1); -//#ifdef INFLATE_STRICT - if (dist > dmax) { - strm.msg = 'invalid distance too far back'; - state.mode = BAD; - break top; - } -//#endif - hold >>>= op; - bits -= op; - //Tracevv((stderr, "inflate: distance %u\n", dist)); - op = _out - beg; /* max distance in output */ - if (dist > op) { /* see if copy from window */ - op = dist - op; /* distance back in window */ - if (op > whave) { - if (state.sane) { - strm.msg = 'invalid distance too far back'; - state.mode = BAD; - break top; - } +module.exports = { + init, from, change, emptyChange, clone, free, + load, save, merge, getChanges, getAllChanges, applyChanges, + encodeChange, decodeChange, equals, getHistory, uuid, + Frontend, setDefaultBackend, generateSyncMessage, receiveSyncMessage, initSyncState, + get Backend() { return backend } +} -// (!) This block is disabled in zlib defaults, -// don't enable it for binary compatibility -//#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR -// if (len <= op - whave) { -// do { -// output[_out++] = 0; -// } while (--len); -// continue top; -// } -// len -= op - whave; -// do { -// output[_out++] = 0; -// } while (--op > whave); -// if (op === 0) { -// from = _out - dist; -// do { -// output[_out++] = output[from++]; -// } while (--len); -// continue top; -// } -//#endif - } - from = 0; // window index - from_source = s_window; - if (wnext === 0) { /* very common case */ - from += wsize - op; - if (op < len) { /* some from window */ - len -= op; - do { - output[_out++] = s_window[from++]; - } while (--op); - from = _out - dist; /* rest from output */ - from_source = output; - } - } - else if (wnext < op) { /* wrap around window */ - from += wsize + wnext - op; - op -= wnext; - if (op < len) { /* some from end of window */ - len -= op; - do { - output[_out++] = s_window[from++]; - } while (--op); - from = 0; - if (wnext < len) { /* some from start of window */ - op = wnext; - len -= op; - do { - output[_out++] = s_window[from++]; - } while (--op); - from = _out - dist; /* rest from output */ - from_source = output; - } - } - } - else { /* contiguous in window */ - from += wnext - op; - if (op < len) { /* some from window */ - len -= op; - do { - output[_out++] = s_window[from++]; - } while (--op); - from = _out - dist; /* rest from output */ - from_source = output; - } - } - while (len > 2) { - output[_out++] = from_source[from++]; - output[_out++] = from_source[from++]; - output[_out++] = from_source[from++]; - len -= 3; - } - if (len) { - output[_out++] = from_source[from++]; - if (len > 1) { - output[_out++] = from_source[from++]; - } - } - } - else { - from = _out - dist; /* copy direct from output */ - do { /* minimum length is three */ - output[_out++] = output[from++]; - output[_out++] = output[from++]; - output[_out++] = output[from++]; - len -= 3; - } while (len > 2); - if (len) { - output[_out++] = output[from++]; - if (len > 1) { - output[_out++] = output[from++]; - } - } - } - } - else if ((op & 64) === 0) { /* 2nd level distance code */ - here = dcode[(here & 0xffff)/*here.val*/ + (hold & ((1 << op) - 1))]; - continue dodist; - } - else { - strm.msg = 'invalid distance code'; - state.mode = BAD; - break top; - } +for (let name of ['getObjectId', 'getObjectById', 'getActorId', + 'setActorId', 'getConflicts', 'getLastLocalChange', + 'Text', 'Table', 'Counter', 'Observable', 'Int', 'Uint', 'Float64']) { + module.exports[name] = Frontend[name] +} - break; // need to emulate goto via "continue" - } - } - else if ((op & 64) === 0) { /* 2nd level length code */ - here = lcode[(here & 0xffff)/*here.val*/ + (hold & ((1 << op) - 1))]; - continue dolen; - } - else if (op & 32) { /* end-of-block */ - //Tracevv((stderr, "inflate: end of block\n")); - state.mode = TYPE; - break top; - } - else { - strm.msg = 'invalid literal/length code'; - state.mode = BAD; - break top; - } +},{"../backend":51,"../backend/columnar":49,"../frontend":59,"../frontend/constants":56,"./common":82,"./uuid":83}],82:[function(require,module,exports){ +function isObject(obj) { + return typeof obj === 'object' && obj !== null +} - break; // need to emulate goto via "continue" - } - } while (_in < last && _out < end); +/** + * Returns a shallow copy of the object `obj`. Faster than `Object.assign({}, obj)`. + * https://jsperf.com/cloning-large-objects/1 + */ +function copyObject(obj) { + if (!isObject(obj)) return {} + let copy = {} + for (let key of Object.keys(obj)) { + copy[key] = obj[key] + } + return copy +} - /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ - len = bits >> 3; - _in -= len; - bits -= len << 3; - hold &= (1 << bits) - 1; +/** + * Takes a string in the form that is used to identify operations (a counter concatenated + * with an actor ID, separated by an `@` sign) and returns an object `{counter, actorId}`. + */ +function parseOpId(opId) { + const match = /^(\d+)@(.*)$/.exec(opId || '') + if (!match) { + throw new RangeError(`Not a valid opId: ${opId}`) + } + return {counter: parseInt(match[1], 10), actorId: match[2]} +} - /* update state and return */ - strm.next_in = _in; - strm.next_out = _out; - strm.avail_in = (_in < last ? 5 + (last - _in) : 5 - (_in - last)); - strm.avail_out = (_out < end ? 257 + (end - _out) : 257 - (_out - end)); - state.hold = hold; - state.bits = bits; - return; -}; +/** + * Returns true if the two byte arrays contain the same data, false if not. + */ +function equalBytes(array1, array2) { + if (!(array1 instanceof Uint8Array) || !(array2 instanceof Uint8Array)) { + throw new TypeError('equalBytes can only compare Uint8Arrays') + } + if (array1.byteLength !== array2.byteLength) return false + for (let i = 0; i < array1.byteLength; i++) { + if (array1[i] !== array2[i]) return false + } + return true +} -},{}],76:[function(require,module,exports){ -'use strict'; +/** + * Creates an array containing the value `null` repeated `length` times. + */ +function createArrayOfNulls(length) { + const array = new Array(length) + for (let i = 0; i < length; i++) array[i] = null + return array +} -// (C) 1995-2013 Jean-loup Gailly and Mark Adler -// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +module.exports = { + isObject, copyObject, parseOpId, equalBytes, createArrayOfNulls +} -const adler32 = require('./adler32'); -const crc32 = require('./crc32'); -const inflate_fast = require('./inffast'); -const inflate_table = require('./inftrees'); +},{}],83:[function(require,module,exports){ +const { v4: uuid } = require('uuid') -const CODES = 0; -const LENS = 1; -const DISTS = 2; +function defaultFactory() { + return uuid().replace(/-/g, '') +} -/* Public constants ==========================================================*/ -/* ===========================================================================*/ +let factory = defaultFactory -const { - Z_FINISH, Z_BLOCK, Z_TREES, - Z_OK, Z_STREAM_END, Z_NEED_DICT, Z_STREAM_ERROR, Z_DATA_ERROR, Z_MEM_ERROR, Z_BUF_ERROR, - Z_DEFLATED -} = require('./constants'); +function makeUuid() { + return factory() +} +makeUuid.setFactory = newFactory => { factory = newFactory } +makeUuid.reset = () => { factory = defaultFactory } -/* STATES ====================================================================*/ -/* ===========================================================================*/ +module.exports = makeUuid +},{"uuid":421}],84:[function(require,module,exports){ +(function (global){(function (){ +'use strict'; -const HEAD = 1; /* i: waiting for magic header */ -const FLAGS = 2; /* i: waiting for method and flags (gzip) */ -const TIME = 3; /* i: waiting for modification time (gzip) */ -const OS = 4; /* i: waiting for extra flags and operating system (gzip) */ -const EXLEN = 5; /* i: waiting for extra length (gzip) */ -const EXTRA = 6; /* i: waiting for extra bytes (gzip) */ -const NAME = 7; /* i: waiting for end of file name (gzip) */ -const COMMENT = 8; /* i: waiting for end of comment (gzip) */ -const HCRC = 9; /* i: waiting for header crc (gzip) */ -const DICTID = 10; /* i: waiting for dictionary check value */ -const DICT = 11; /* waiting for inflateSetDictionary() call */ -const TYPE = 12; /* i: waiting for type bits, including last-flag bit */ -const TYPEDO = 13; /* i: same, but skip check to exit inflate on new block */ -const STORED = 14; /* i: waiting for stored size (length and complement) */ -const COPY_ = 15; /* i/o: same as COPY below, but only first time in */ -const COPY = 16; /* i/o: waiting for input or output to copy stored block */ -const TABLE = 17; /* i: waiting for dynamic block table lengths */ -const LENLENS = 18; /* i: waiting for code length code lengths */ -const CODELENS = 19; /* i: waiting for length/lit and distance code lengths */ -const LEN_ = 20; /* i: same as LEN below, but only first time in */ -const LEN = 21; /* i: waiting for length/lit/eob code */ -const LENEXT = 22; /* i: waiting for length extra bits */ -const DIST = 23; /* i: waiting for distance code */ -const DISTEXT = 24; /* i: waiting for distance extra bits */ -const MATCH = 25; /* o: waiting for output space to copy string */ -const LIT = 26; /* o: waiting for output space to write literal */ -const CHECK = 27; /* i: waiting for 32-bit check value */ -const LENGTH = 28; /* i: waiting for 32-bit length (gzip) */ -const DONE = 29; /* finished check, done -- remain here until reset */ -const BAD = 30; /* got a data error -- remain here until reset */ -const MEM = 31; /* got an inflate() memory error -- remain here until reset */ -const SYNC = 32; /* looking for synchronization bytes to restart inflate() */ +var possibleNames = require('possible-typed-array-names'); -/* ===========================================================================*/ +var g = typeof globalThis === 'undefined' ? global : globalThis; +/** @type {import('.')} */ +module.exports = function availableTypedArrays() { + var /** @type {ReturnType} */ out = []; + for (var i = 0; i < possibleNames.length; i++) { + if (typeof g[possibleNames[i]] === 'function') { + // @ts-expect-error + out[out.length] = possibleNames[i]; + } + } + return out; +}; +}).call(this)}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"possible-typed-array-names":348}],85:[function(require,module,exports){ +'use strict' -const ENOUGH_LENS = 852; -const ENOUGH_DISTS = 592; -//const ENOUGH = (ENOUGH_LENS+ENOUGH_DISTS); +exports.byteLength = byteLength +exports.toByteArray = toByteArray +exports.fromByteArray = fromByteArray -const MAX_WBITS = 15; -/* 32K LZ77 window */ -const DEF_WBITS = MAX_WBITS; +var lookup = [] +var revLookup = [] +var Arr = typeof Uint8Array !== 'undefined' ? Uint8Array : Array +var code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' +for (var i = 0, len = code.length; i < len; ++i) { + lookup[i] = code[i] + revLookup[code.charCodeAt(i)] = i +} -const zswap32 = (q) => { +// Support decoding URL-safe base64 strings, as Node.js does. +// See: https://en.wikipedia.org/wiki/Base64#URL_applications +revLookup['-'.charCodeAt(0)] = 62 +revLookup['_'.charCodeAt(0)] = 63 - return (((q >>> 24) & 0xff) + - ((q >>> 8) & 0xff00) + - ((q & 0xff00) << 8) + - ((q & 0xff) << 24)); -}; +function getLens (b64) { + var len = b64.length + if (len % 4 > 0) { + throw new Error('Invalid string. Length must be a multiple of 4') + } -function InflateState() { - this.mode = 0; /* current inflate mode */ - this.last = false; /* true if processing last block */ - this.wrap = 0; /* bit 0 true for zlib, bit 1 true for gzip */ - this.havedict = false; /* true if dictionary provided */ - this.flags = 0; /* gzip header method and flags (0 if zlib) */ - this.dmax = 0; /* zlib header max distance (INFLATE_STRICT) */ - this.check = 0; /* protected copy of check value */ - this.total = 0; /* protected copy of output count */ - // TODO: may be {} - this.head = null; /* where to save gzip header information */ + // Trim off extra bytes after placeholder bytes are found + // See: https://github.com/beatgammit/base64-js/issues/42 + var validLen = b64.indexOf('=') + if (validLen === -1) validLen = len - /* sliding window */ - this.wbits = 0; /* log base 2 of requested window size */ - this.wsize = 0; /* window size or zero if not using window */ - this.whave = 0; /* valid bytes in the window */ - this.wnext = 0; /* window write index */ - this.window = null; /* allocated sliding window, if needed */ + var placeHoldersLen = validLen === len + ? 0 + : 4 - (validLen % 4) - /* bit accumulator */ - this.hold = 0; /* input bit accumulator */ - this.bits = 0; /* number of bits in "in" */ + return [validLen, placeHoldersLen] +} - /* for string and stored block copying */ - this.length = 0; /* literal or length of data to copy */ - this.offset = 0; /* distance back to copy string from */ +// base64 is 4/3 + up to two characters of the original data +function byteLength (b64) { + var lens = getLens(b64) + var validLen = lens[0] + var placeHoldersLen = lens[1] + return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen +} - /* for table and code decoding */ - this.extra = 0; /* extra bits needed */ +function _byteLength (b64, validLen, placeHoldersLen) { + return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen +} - /* fixed and dynamic code tables */ - this.lencode = null; /* starting table for length/literal codes */ - this.distcode = null; /* starting table for distance codes */ - this.lenbits = 0; /* index bits for lencode */ - this.distbits = 0; /* index bits for distcode */ +function toByteArray (b64) { + var tmp + var lens = getLens(b64) + var validLen = lens[0] + var placeHoldersLen = lens[1] - /* dynamic table building */ - this.ncode = 0; /* number of code length code lengths */ - this.nlen = 0; /* number of length code lengths */ - this.ndist = 0; /* number of distance code lengths */ - this.have = 0; /* number of code lengths in lens[] */ - this.next = null; /* next available space in codes[] */ + var arr = new Arr(_byteLength(b64, validLen, placeHoldersLen)) - this.lens = new Uint16Array(320); /* temporary storage for code lengths */ - this.work = new Uint16Array(288); /* work area for code table building */ + var curByte = 0 - /* - because we don't have pointers in js, we use lencode and distcode directly - as buffers so we don't need codes - */ - //this.codes = new Int32Array(ENOUGH); /* space for code tables */ - this.lendyn = null; /* dynamic table for length/literal codes (JS specific) */ - this.distdyn = null; /* dynamic table for distance codes (JS specific) */ - this.sane = 0; /* if false, allow invalid distance too far */ - this.back = 0; /* bits back of last unprocessed length/lit */ - this.was = 0; /* initial length of match */ -} + // if there are placeholders, only get up to the last complete 4 chars + var len = placeHoldersLen > 0 + ? validLen - 4 + : validLen + var i + for (i = 0; i < len; i += 4) { + tmp = + (revLookup[b64.charCodeAt(i)] << 18) | + (revLookup[b64.charCodeAt(i + 1)] << 12) | + (revLookup[b64.charCodeAt(i + 2)] << 6) | + revLookup[b64.charCodeAt(i + 3)] + arr[curByte++] = (tmp >> 16) & 0xFF + arr[curByte++] = (tmp >> 8) & 0xFF + arr[curByte++] = tmp & 0xFF + } -const inflateResetKeep = (strm) => { + if (placeHoldersLen === 2) { + tmp = + (revLookup[b64.charCodeAt(i)] << 2) | + (revLookup[b64.charCodeAt(i + 1)] >> 4) + arr[curByte++] = tmp & 0xFF + } - if (!strm || !strm.state) { return Z_STREAM_ERROR; } - const state = strm.state; - strm.total_in = strm.total_out = state.total = 0; - strm.msg = ''; /*Z_NULL*/ - if (state.wrap) { /* to support ill-conceived Java test suite */ - strm.adler = state.wrap & 1; + if (placeHoldersLen === 1) { + tmp = + (revLookup[b64.charCodeAt(i)] << 10) | + (revLookup[b64.charCodeAt(i + 1)] << 4) | + (revLookup[b64.charCodeAt(i + 2)] >> 2) + arr[curByte++] = (tmp >> 8) & 0xFF + arr[curByte++] = tmp & 0xFF } - state.mode = HEAD; - state.last = 0; - state.havedict = 0; - state.dmax = 32768; - state.head = null/*Z_NULL*/; - state.hold = 0; - state.bits = 0; - //state.lencode = state.distcode = state.next = state.codes; - state.lencode = state.lendyn = new Int32Array(ENOUGH_LENS); - state.distcode = state.distdyn = new Int32Array(ENOUGH_DISTS); - state.sane = 1; - state.back = -1; - //Tracev((stderr, "inflate: reset\n")); - return Z_OK; -}; + return arr +} +function tripletToBase64 (num) { + return lookup[num >> 18 & 0x3F] + + lookup[num >> 12 & 0x3F] + + lookup[num >> 6 & 0x3F] + + lookup[num & 0x3F] +} -const inflateReset = (strm) => { +function encodeChunk (uint8, start, end) { + var tmp + var output = [] + for (var i = start; i < end; i += 3) { + tmp = + ((uint8[i] << 16) & 0xFF0000) + + ((uint8[i + 1] << 8) & 0xFF00) + + (uint8[i + 2] & 0xFF) + output.push(tripletToBase64(tmp)) + } + return output.join('') +} - if (!strm || !strm.state) { return Z_STREAM_ERROR; } - const state = strm.state; - state.wsize = 0; - state.whave = 0; - state.wnext = 0; - return inflateResetKeep(strm); +function fromByteArray (uint8) { + var tmp + var len = uint8.length + var extraBytes = len % 3 // if we have 1 byte left, pad 2 bytes + var parts = [] + var maxChunkLength = 16383 // must be multiple of 3 -}; + // go through the array every three bytes, we'll deal with trailing stuff later + for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) { + parts.push(encodeChunk(uint8, i, (i + maxChunkLength) > len2 ? len2 : (i + maxChunkLength))) + } + // pad the end with zeros, but make sure to not forget the extra bytes + if (extraBytes === 1) { + tmp = uint8[len - 1] + parts.push( + lookup[tmp >> 2] + + lookup[(tmp << 4) & 0x3F] + + '==' + ) + } else if (extraBytes === 2) { + tmp = (uint8[len - 2] << 8) + uint8[len - 1] + parts.push( + lookup[tmp >> 10] + + lookup[(tmp >> 4) & 0x3F] + + lookup[(tmp << 2) & 0x3F] + + '=' + ) + } -const inflateReset2 = (strm, windowBits) => { - let wrap; + return parts.join('') +} - /* get the state */ - if (!strm || !strm.state) { return Z_STREAM_ERROR; } - const state = strm.state; +},{}],86:[function(require,module,exports){ +(function (module, exports) { + 'use strict'; - /* extract wrap request from windowBits parameter */ - if (windowBits < 0) { - wrap = 0; - windowBits = -windowBits; - } - else { - wrap = (windowBits >> 4) + 1; - if (windowBits < 48) { - windowBits &= 15; - } + // Utils + function assert (val, msg) { + if (!val) throw new Error(msg || 'Assertion failed'); } - /* set number of window bits, free window if different */ - if (windowBits && (windowBits < 8 || windowBits > 15)) { - return Z_STREAM_ERROR; - } - if (state.window !== null && state.wbits !== windowBits) { - state.window = null; + // Could use `inherits` module, but don't want to move from single file + // architecture yet. + function inherits (ctor, superCtor) { + ctor.super_ = superCtor; + var TempCtor = function () {}; + TempCtor.prototype = superCtor.prototype; + ctor.prototype = new TempCtor(); + ctor.prototype.constructor = ctor; } - /* update state and reset the rest of it */ - state.wrap = wrap; - state.wbits = windowBits; - return inflateReset(strm); -}; + // BN + function BN (number, base, endian) { + if (BN.isBN(number)) { + return number; + } -const inflateInit2 = (strm, windowBits) => { + this.negative = 0; + this.words = null; + this.length = 0; - if (!strm) { return Z_STREAM_ERROR; } - //strm.msg = Z_NULL; /* in case we return an error */ + // Reduction context + this.red = null; - const state = new InflateState(); + if (number !== null) { + if (base === 'le' || base === 'be') { + endian = base; + base = 10; + } - //if (state === Z_NULL) return Z_MEM_ERROR; - //Tracev((stderr, "inflate: allocated\n")); - strm.state = state; - state.window = null/*Z_NULL*/; - const ret = inflateReset2(strm, windowBits); - if (ret !== Z_OK) { - strm.state = null/*Z_NULL*/; + this._init(number || 0, base || 10, endian || 'be'); + } + } + if (typeof module === 'object') { + module.exports = BN; + } else { + exports.BN = BN; } - return ret; -}; + BN.BN = BN; + BN.wordSize = 26; -const inflateInit = (strm) => { + var Buffer; + try { + if (typeof window !== 'undefined' && typeof window.Buffer !== 'undefined') { + Buffer = window.Buffer; + } else { + Buffer = require('buffer').Buffer; + } + } catch (e) { + } - return inflateInit2(strm, DEF_WBITS); -}; + BN.isBN = function isBN (num) { + if (num instanceof BN) { + return true; + } + return num !== null && typeof num === 'object' && + num.constructor.wordSize === BN.wordSize && Array.isArray(num.words); + }; -/* - Return state with length and distance decoding tables and index sizes set to - fixed code decoding. Normally this returns fixed tables from inffixed.h. - If BUILDFIXED is defined, then instead this routine builds the tables the - first time it's called, and returns those tables the first time and - thereafter. This reduces the size of the code by about 2K bytes, in - exchange for a little execution time. However, BUILDFIXED should not be - used for threaded applications, since the rewriting of the tables and virgin - may not be thread-safe. - */ -let virgin = true; + BN.max = function max (left, right) { + if (left.cmp(right) > 0) return left; + return right; + }; -let lenfix, distfix; // We have no pointers in JS, so keep tables separate + BN.min = function min (left, right) { + if (left.cmp(right) < 0) return left; + return right; + }; + BN.prototype._init = function init (number, base, endian) { + if (typeof number === 'number') { + return this._initNumber(number, base, endian); + } -const fixedtables = (state) => { + if (typeof number === 'object') { + return this._initArray(number, base, endian); + } - /* build fixed huffman tables if first call (may not be thread safe) */ - if (virgin) { - lenfix = new Int32Array(512); - distfix = new Int32Array(32); + if (base === 'hex') { + base = 16; + } + assert(base === (base | 0) && base >= 2 && base <= 36); - /* literal/length table */ - let sym = 0; - while (sym < 144) { state.lens[sym++] = 8; } - while (sym < 256) { state.lens[sym++] = 9; } - while (sym < 280) { state.lens[sym++] = 7; } - while (sym < 288) { state.lens[sym++] = 8; } + number = number.toString().replace(/\s+/g, ''); + var start = 0; + if (number[0] === '-') { + start++; + this.negative = 1; + } - inflate_table(LENS, state.lens, 0, 288, lenfix, 0, state.work, { bits: 9 }); + if (start < number.length) { + if (base === 16) { + this._parseHex(number, start, endian); + } else { + this._parseBase(number, base, start); + if (endian === 'le') { + this._initArray(this.toArray(), base, endian); + } + } + } + }; - /* distance table */ - sym = 0; - while (sym < 32) { state.lens[sym++] = 5; } + BN.prototype._initNumber = function _initNumber (number, base, endian) { + if (number < 0) { + this.negative = 1; + number = -number; + } + if (number < 0x4000000) { + this.words = [ number & 0x3ffffff ]; + this.length = 1; + } else if (number < 0x10000000000000) { + this.words = [ + number & 0x3ffffff, + (number / 0x4000000) & 0x3ffffff + ]; + this.length = 2; + } else { + assert(number < 0x20000000000000); // 2 ^ 53 (unsafe) + this.words = [ + number & 0x3ffffff, + (number / 0x4000000) & 0x3ffffff, + 1 + ]; + this.length = 3; + } - inflate_table(DISTS, state.lens, 0, 32, distfix, 0, state.work, { bits: 5 }); + if (endian !== 'le') return; - /* do this just once */ - virgin = false; + // Reverse the bytes + this._initArray(this.toArray(), base, endian); + }; + + BN.prototype._initArray = function _initArray (number, base, endian) { + // Perhaps a Uint8Array + assert(typeof number.length === 'number'); + if (number.length <= 0) { + this.words = [ 0 ]; + this.length = 1; + return this; + } + + this.length = Math.ceil(number.length / 3); + this.words = new Array(this.length); + for (var i = 0; i < this.length; i++) { + this.words[i] = 0; + } + + var j, w; + var off = 0; + if (endian === 'be') { + for (i = number.length - 1, j = 0; i >= 0; i -= 3) { + w = number[i] | (number[i - 1] << 8) | (number[i - 2] << 16); + this.words[j] |= (w << off) & 0x3ffffff; + this.words[j + 1] = (w >>> (26 - off)) & 0x3ffffff; + off += 24; + if (off >= 26) { + off -= 26; + j++; + } + } + } else if (endian === 'le') { + for (i = 0, j = 0; i < number.length; i += 3) { + w = number[i] | (number[i + 1] << 8) | (number[i + 2] << 16); + this.words[j] |= (w << off) & 0x3ffffff; + this.words[j + 1] = (w >>> (26 - off)) & 0x3ffffff; + off += 24; + if (off >= 26) { + off -= 26; + j++; + } + } + } + return this.strip(); + }; + + function parseHex4Bits (string, index) { + var c = string.charCodeAt(index); + // 'A' - 'F' + if (c >= 65 && c <= 70) { + return c - 55; + // 'a' - 'f' + } else if (c >= 97 && c <= 102) { + return c - 87; + // '0' - '9' + } else { + return (c - 48) & 0xf; + } } - state.lencode = lenfix; - state.lenbits = 9; - state.distcode = distfix; - state.distbits = 5; -}; + function parseHexByte (string, lowerBound, index) { + var r = parseHex4Bits(string, index); + if (index - 1 >= lowerBound) { + r |= parseHex4Bits(string, index - 1) << 4; + } + return r; + } + BN.prototype._parseHex = function _parseHex (number, start, endian) { + // Create possibly bigger array to ensure that it fits the number + this.length = Math.ceil((number.length - start) / 6); + this.words = new Array(this.length); + for (var i = 0; i < this.length; i++) { + this.words[i] = 0; + } -/* - Update the window with the last wsize (normally 32K) bytes written before - returning. If window does not exist yet, create it. This is only called - when a window is already in use, or when output has been written during this - inflate call, but the end of the deflate stream has not been reached yet. - It is also called to create a window for dictionary data when a dictionary - is loaded. + // 24-bits chunks + var off = 0; + var j = 0; - Providing output buffers larger than 32K to inflate() should provide a speed - advantage, since only the last 32K of output is copied to the sliding window - upon return from inflate(), and since all distances after the first 32K of - output will fall in the output data, making match copies simpler and faster. - The advantage may be dependent on the size of the processor's data caches. - */ -const updatewindow = (strm, src, end, copy) => { + var w; + if (endian === 'be') { + for (i = number.length - 1; i >= start; i -= 2) { + w = parseHexByte(number, start, i) << off; + this.words[j] |= w & 0x3ffffff; + if (off >= 18) { + off -= 18; + j += 1; + this.words[j] |= w >>> 26; + } else { + off += 8; + } + } + } else { + var parseLength = number.length - start; + for (i = parseLength % 2 === 0 ? start + 1 : start; i < number.length; i += 2) { + w = parseHexByte(number, start, i) << off; + this.words[j] |= w & 0x3ffffff; + if (off >= 18) { + off -= 18; + j += 1; + this.words[j] |= w >>> 26; + } else { + off += 8; + } + } + } - let dist; - const state = strm.state; + this.strip(); + }; - /* if it hasn't been done already, allocate space for the window */ - if (state.window === null) { - state.wsize = 1 << state.wbits; - state.wnext = 0; - state.whave = 0; + function parseBase (str, start, end, mul) { + var r = 0; + var len = Math.min(str.length, end); + for (var i = start; i < len; i++) { + var c = str.charCodeAt(i) - 48; - state.window = new Uint8Array(state.wsize); - } + r *= mul; - /* copy state->wsize or less output bytes into the circular window */ - if (copy >= state.wsize) { - state.window.set(src.subarray(end - state.wsize, end), 0); - state.wnext = 0; - state.whave = state.wsize; - } - else { - dist = state.wsize - state.wnext; - if (dist > copy) { - dist = copy; + // 'a' + if (c >= 49) { + r += c - 49 + 0xa; + + // 'A' + } else if (c >= 17) { + r += c - 17 + 0xa; + + // '0' - '9' + } else { + r += c; + } } - //zmemcpy(state->window + state->wnext, end - copy, dist); - state.window.set(src.subarray(end - copy, end - copy + dist), state.wnext); - copy -= dist; - if (copy) { - //zmemcpy(state->window, end - copy, copy); - state.window.set(src.subarray(end - copy, end), 0); - state.wnext = copy; - state.whave = state.wsize; + return r; + } + + BN.prototype._parseBase = function _parseBase (number, base, start) { + // Initialize as zero + this.words = [ 0 ]; + this.length = 1; + + // Find length of limb in base + for (var limbLen = 0, limbPow = 1; limbPow <= 0x3ffffff; limbPow *= base) { + limbLen++; } - else { - state.wnext += dist; - if (state.wnext === state.wsize) { state.wnext = 0; } - if (state.whave < state.wsize) { state.whave += dist; } + limbLen--; + limbPow = (limbPow / base) | 0; + + var total = number.length - start; + var mod = total % limbLen; + var end = Math.min(total, total - mod) + start; + + var word = 0; + for (var i = start; i < end; i += limbLen) { + word = parseBase(number, i, i + limbLen, base); + + this.imuln(limbPow); + if (this.words[0] + word < 0x4000000) { + this.words[0] += word; + } else { + this._iaddn(word); + } } - } - return 0; -}; + if (mod !== 0) { + var pow = 1; + word = parseBase(number, i, number.length, base); -const inflate = (strm, flush) => { + for (i = 0; i < mod; i++) { + pow *= base; + } - let state; - let input, output; // input/output buffers - let next; /* next input INDEX */ - let put; /* next output INDEX */ - let have, left; /* available input and output */ - let hold; /* bit buffer */ - let bits; /* bits in bit buffer */ - let _in, _out; /* save starting available input and output */ - let copy; /* number of stored or match bytes to copy */ - let from; /* where to copy match bytes from */ - let from_source; - let here = 0; /* current decoding table entry */ - let here_bits, here_op, here_val; // paked "here" denormalized (JS specific) - //let last; /* parent table entry */ - let last_bits, last_op, last_val; // paked "last" denormalized (JS specific) - let len; /* length to copy for repeats, bits to drop */ - let ret; /* return code */ - const hbuf = new Uint8Array(4); /* buffer for gzip header crc calculation */ - let opts; + this.imuln(pow); + if (this.words[0] + word < 0x4000000) { + this.words[0] += word; + } else { + this._iaddn(word); + } + } - let n; // temporary variable for NEED_BITS + this.strip(); + }; - const order = /* permutation of code lengths */ - new Uint8Array([ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 ]); + BN.prototype.copy = function copy (dest) { + dest.words = new Array(this.length); + for (var i = 0; i < this.length; i++) { + dest.words[i] = this.words[i]; + } + dest.length = this.length; + dest.negative = this.negative; + dest.red = this.red; + }; + BN.prototype.clone = function clone () { + var r = new BN(null); + this.copy(r); + return r; + }; - if (!strm || !strm.state || !strm.output || - (!strm.input && strm.avail_in !== 0)) { - return Z_STREAM_ERROR; - } + BN.prototype._expand = function _expand (size) { + while (this.length < size) { + this.words[this.length++] = 0; + } + return this; + }; - state = strm.state; - if (state.mode === TYPE) { state.mode = TYPEDO; } /* skip check */ + // Remove leading `0` from `this` + BN.prototype.strip = function strip () { + while (this.length > 1 && this.words[this.length - 1] === 0) { + this.length--; + } + return this._normSign(); + }; + BN.prototype._normSign = function _normSign () { + // -0 = 0 + if (this.length === 1 && this.words[0] === 0) { + this.negative = 0; + } + return this; + }; - //--- LOAD() --- - put = strm.next_out; - output = strm.output; - left = strm.avail_out; - next = strm.next_in; - input = strm.input; - have = strm.avail_in; - hold = state.hold; - bits = state.bits; - //--- + BN.prototype.inspect = function inspect () { + return (this.red ? ''; + }; - _in = have; - _out = left; - ret = Z_OK; + /* - inf_leave: // goto emulation - for (;;) { - switch (state.mode) { - case HEAD: - if (state.wrap === 0) { - state.mode = TYPEDO; - break; - } - //=== NEEDBITS(16); - while (bits < 16) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - if ((state.wrap & 2) && hold === 0x8b1f) { /* gzip header */ - state.check = 0/*crc32(0L, Z_NULL, 0)*/; - //=== CRC2(state.check, hold); - hbuf[0] = hold & 0xff; - hbuf[1] = (hold >>> 8) & 0xff; - state.check = crc32(state.check, hbuf, 2, 0); - //===// + var zeros = []; + var groupSizes = []; + var groupBases = []; - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - state.mode = FLAGS; - break; - } - state.flags = 0; /* expect zlib header */ - if (state.head) { - state.head.done = false; - } - if (!(state.wrap & 1) || /* check if zlib header allowed */ - (((hold & 0xff)/*BITS(8)*/ << 8) + (hold >> 8)) % 31) { - strm.msg = 'incorrect header check'; - state.mode = BAD; - break; - } - if ((hold & 0x0f)/*BITS(4)*/ !== Z_DEFLATED) { - strm.msg = 'unknown compression method'; - state.mode = BAD; - break; - } - //--- DROPBITS(4) ---// - hold >>>= 4; - bits -= 4; - //---// - len = (hold & 0x0f)/*BITS(4)*/ + 8; - if (state.wbits === 0) { - state.wbits = len; - } - else if (len > state.wbits) { - strm.msg = 'invalid window size'; - state.mode = BAD; - break; - } + var s = ''; + var i = -1; + while (++i < BN.wordSize) { + zeros[i] = s; + s += '0'; + } + groupSizes[0] = 0; + groupSizes[1] = 0; + groupBases[0] = 0; + groupBases[1] = 0; + var base = 2 - 1; + while (++base < 36 + 1) { + var groupSize = 0; + var groupBase = 1; + while (groupBase < (1 << BN.wordSize) / base) { + groupBase *= base; + groupSize += 1; + } + groupSizes[base] = groupSize; + groupBases[base] = groupBase; + } - // !!! pako patch. Force use `options.windowBits` if passed. - // Required to always use max window size by default. - state.dmax = 1 << state.wbits; - //state.dmax = 1 << len; + */ - //Tracev((stderr, "inflate: zlib header ok\n")); - strm.adler = state.check = 1/*adler32(0L, Z_NULL, 0)*/; - state.mode = hold & 0x200 ? DICTID : TYPE; - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - break; - case FLAGS: - //=== NEEDBITS(16); */ - while (bits < 16) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - state.flags = hold; - if ((state.flags & 0xff) !== Z_DEFLATED) { - strm.msg = 'unknown compression method'; - state.mode = BAD; - break; - } - if (state.flags & 0xe000) { - strm.msg = 'unknown header flags set'; - state.mode = BAD; - break; - } - if (state.head) { - state.head.text = ((hold >> 8) & 1); - } - if (state.flags & 0x0200) { - //=== CRC2(state.check, hold); - hbuf[0] = hold & 0xff; - hbuf[1] = (hold >>> 8) & 0xff; - state.check = crc32(state.check, hbuf, 2, 0); - //===// - } - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - state.mode = TIME; - /* falls through */ - case TIME: - //=== NEEDBITS(32); */ - while (bits < 32) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - if (state.head) { - state.head.time = hold; - } - if (state.flags & 0x0200) { - //=== CRC4(state.check, hold) - hbuf[0] = hold & 0xff; - hbuf[1] = (hold >>> 8) & 0xff; - hbuf[2] = (hold >>> 16) & 0xff; - hbuf[3] = (hold >>> 24) & 0xff; - state.check = crc32(state.check, hbuf, 4, 0); - //=== - } - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - state.mode = OS; - /* falls through */ - case OS: - //=== NEEDBITS(16); */ - while (bits < 16) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - if (state.head) { - state.head.xflags = (hold & 0xff); - state.head.os = (hold >> 8); - } - if (state.flags & 0x0200) { - //=== CRC2(state.check, hold); - hbuf[0] = hold & 0xff; - hbuf[1] = (hold >>> 8) & 0xff; - state.check = crc32(state.check, hbuf, 2, 0); - //===// - } - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - state.mode = EXLEN; - /* falls through */ - case EXLEN: - if (state.flags & 0x0400) { - //=== NEEDBITS(16); */ - while (bits < 16) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - state.length = hold; - if (state.head) { - state.head.extra_len = hold; - } - if (state.flags & 0x0200) { - //=== CRC2(state.check, hold); - hbuf[0] = hold & 0xff; - hbuf[1] = (hold >>> 8) & 0xff; - state.check = crc32(state.check, hbuf, 2, 0); - //===// - } - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - } - else if (state.head) { - state.head.extra = null/*Z_NULL*/; - } - state.mode = EXTRA; - /* falls through */ - case EXTRA: - if (state.flags & 0x0400) { - copy = state.length; - if (copy > have) { copy = have; } - if (copy) { - if (state.head) { - len = state.head.extra_len - state.length; - if (!state.head.extra) { - // Use untyped array for more convenient processing later - state.head.extra = new Uint8Array(state.head.extra_len); - } - state.head.extra.set( - input.subarray( - next, - // extra field is limited to 65536 bytes - // - no need for additional size check - next + copy - ), - /*len + copy > state.head.extra_max - len ? state.head.extra_max : copy,*/ - len - ); - //zmemcpy(state.head.extra + len, next, - // len + copy > state.head.extra_max ? - // state.head.extra_max - len : copy); - } - if (state.flags & 0x0200) { - state.check = crc32(state.check, input, copy, next); - } - have -= copy; - next += copy; - state.length -= copy; - } - if (state.length) { break inf_leave; } - } - state.length = 0; - state.mode = NAME; - /* falls through */ - case NAME: - if (state.flags & 0x0800) { - if (have === 0) { break inf_leave; } - copy = 0; - do { - // TODO: 2 or 1 bytes? - len = input[next + copy++]; - /* use constant limit because in js we should not preallocate memory */ - if (state.head && len && - (state.length < 65536 /*state.head.name_max*/)) { - state.head.name += String.fromCharCode(len); - } - } while (len && copy < have); + var zeros = [ + '', + '0', + '00', + '000', + '0000', + '00000', + '000000', + '0000000', + '00000000', + '000000000', + '0000000000', + '00000000000', + '000000000000', + '0000000000000', + '00000000000000', + '000000000000000', + '0000000000000000', + '00000000000000000', + '000000000000000000', + '0000000000000000000', + '00000000000000000000', + '000000000000000000000', + '0000000000000000000000', + '00000000000000000000000', + '000000000000000000000000', + '0000000000000000000000000' + ]; - if (state.flags & 0x0200) { - state.check = crc32(state.check, input, copy, next); - } - have -= copy; - next += copy; - if (len) { break inf_leave; } - } - else if (state.head) { - state.head.name = null; - } - state.length = 0; - state.mode = COMMENT; - /* falls through */ - case COMMENT: - if (state.flags & 0x1000) { - if (have === 0) { break inf_leave; } - copy = 0; - do { - len = input[next + copy++]; - /* use constant limit because in js we should not preallocate memory */ - if (state.head && len && - (state.length < 65536 /*state.head.comm_max*/)) { - state.head.comment += String.fromCharCode(len); - } - } while (len && copy < have); - if (state.flags & 0x0200) { - state.check = crc32(state.check, input, copy, next); - } - have -= copy; - next += copy; - if (len) { break inf_leave; } - } - else if (state.head) { - state.head.comment = null; - } - state.mode = HCRC; - /* falls through */ - case HCRC: - if (state.flags & 0x0200) { - //=== NEEDBITS(16); */ - while (bits < 16) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - if (hold !== (state.check & 0xffff)) { - strm.msg = 'header crc mismatch'; - state.mode = BAD; - break; - } - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - } - if (state.head) { - state.head.hcrc = ((state.flags >> 9) & 1); - state.head.done = true; - } - strm.adler = state.check = 0; - state.mode = TYPE; - break; - case DICTID: - //=== NEEDBITS(32); */ - while (bits < 32) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - strm.adler = state.check = zswap32(hold); - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - state.mode = DICT; - /* falls through */ - case DICT: - if (state.havedict === 0) { - //--- RESTORE() --- - strm.next_out = put; - strm.avail_out = left; - strm.next_in = next; - strm.avail_in = have; - state.hold = hold; - state.bits = bits; - //--- - return Z_NEED_DICT; - } - strm.adler = state.check = 1/*adler32(0L, Z_NULL, 0)*/; - state.mode = TYPE; - /* falls through */ - case TYPE: - if (flush === Z_BLOCK || flush === Z_TREES) { break inf_leave; } - /* falls through */ - case TYPEDO: - if (state.last) { - //--- BYTEBITS() ---// - hold >>>= bits & 7; - bits -= bits & 7; - //---// - state.mode = CHECK; - break; - } - //=== NEEDBITS(3); */ - while (bits < 3) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - state.last = (hold & 0x01)/*BITS(1)*/; - //--- DROPBITS(1) ---// - hold >>>= 1; - bits -= 1; - //---// + var groupSizes = [ + 0, 0, + 25, 16, 12, 11, 10, 9, 8, + 8, 7, 7, 7, 7, 6, 6, + 6, 6, 6, 6, 6, 5, 5, + 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5 + ]; - switch ((hold & 0x03)/*BITS(2)*/) { - case 0: /* stored block */ - //Tracev((stderr, "inflate: stored block%s\n", - // state.last ? " (last)" : "")); - state.mode = STORED; - break; - case 1: /* fixed block */ - fixedtables(state); - //Tracev((stderr, "inflate: fixed codes block%s\n", - // state.last ? " (last)" : "")); - state.mode = LEN_; /* decode codes */ - if (flush === Z_TREES) { - //--- DROPBITS(2) ---// - hold >>>= 2; - bits -= 2; - //---// - break inf_leave; - } - break; - case 2: /* dynamic block */ - //Tracev((stderr, "inflate: dynamic codes block%s\n", - // state.last ? " (last)" : "")); - state.mode = TABLE; - break; - case 3: - strm.msg = 'invalid block type'; - state.mode = BAD; - } - //--- DROPBITS(2) ---// - hold >>>= 2; - bits -= 2; - //---// - break; - case STORED: - //--- BYTEBITS() ---// /* go to byte boundary */ - hold >>>= bits & 7; - bits -= bits & 7; - //---// - //=== NEEDBITS(32); */ - while (bits < 32) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; + var groupBases = [ + 0, 0, + 33554432, 43046721, 16777216, 48828125, 60466176, 40353607, 16777216, + 43046721, 10000000, 19487171, 35831808, 62748517, 7529536, 11390625, + 16777216, 24137569, 34012224, 47045881, 64000000, 4084101, 5153632, + 6436343, 7962624, 9765625, 11881376, 14348907, 17210368, 20511149, + 24300000, 28629151, 33554432, 39135393, 45435424, 52521875, 60466176 + ]; + + BN.prototype.toString = function toString (base, padding) { + base = base || 10; + padding = padding | 0 || 1; + + var out; + if (base === 16 || base === 'hex') { + out = ''; + var off = 0; + var carry = 0; + for (var i = 0; i < this.length; i++) { + var w = this.words[i]; + var word = (((w << off) | carry) & 0xffffff).toString(16); + carry = (w >>> (24 - off)) & 0xffffff; + if (carry !== 0 || i !== this.length - 1) { + out = zeros[6 - word.length] + word + out; + } else { + out = word + out; } - //===// - if ((hold & 0xffff) !== ((hold >>> 16) ^ 0xffff)) { - strm.msg = 'invalid stored block lengths'; - state.mode = BAD; - break; + off += 2; + if (off >= 26) { + off -= 26; + i--; } - state.length = hold & 0xffff; - //Tracev((stderr, "inflate: stored length %u\n", - // state.length)); - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - state.mode = COPY_; - if (flush === Z_TREES) { break inf_leave; } - /* falls through */ - case COPY_: - state.mode = COPY; - /* falls through */ - case COPY: - copy = state.length; - if (copy) { - if (copy > have) { copy = have; } - if (copy > left) { copy = left; } - if (copy === 0) { break inf_leave; } - //--- zmemcpy(put, next, copy); --- - output.set(input.subarray(next, next + copy), put); - //---// - have -= copy; - next += copy; - left -= copy; - put += copy; - state.length -= copy; - break; + } + if (carry !== 0) { + out = carry.toString(16) + out; + } + while (out.length % padding !== 0) { + out = '0' + out; + } + if (this.negative !== 0) { + out = '-' + out; + } + return out; + } + + if (base === (base | 0) && base >= 2 && base <= 36) { + // var groupSize = Math.floor(BN.wordSize * Math.LN2 / Math.log(base)); + var groupSize = groupSizes[base]; + // var groupBase = Math.pow(base, groupSize); + var groupBase = groupBases[base]; + out = ''; + var c = this.clone(); + c.negative = 0; + while (!c.isZero()) { + var r = c.modn(groupBase).toString(base); + c = c.idivn(groupBase); + + if (!c.isZero()) { + out = zeros[groupSize - r.length] + r + out; + } else { + out = r + out; } - //Tracev((stderr, "inflate: stored end\n")); - state.mode = TYPE; - break; - case TABLE: - //=== NEEDBITS(14); */ - while (bits < 14) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - state.nlen = (hold & 0x1f)/*BITS(5)*/ + 257; - //--- DROPBITS(5) ---// - hold >>>= 5; - bits -= 5; - //---// - state.ndist = (hold & 0x1f)/*BITS(5)*/ + 1; - //--- DROPBITS(5) ---// - hold >>>= 5; - bits -= 5; - //---// - state.ncode = (hold & 0x0f)/*BITS(4)*/ + 4; - //--- DROPBITS(4) ---// - hold >>>= 4; - bits -= 4; - //---// -//#ifndef PKZIP_BUG_WORKAROUND - if (state.nlen > 286 || state.ndist > 30) { - strm.msg = 'too many length or distance symbols'; - state.mode = BAD; - break; - } -//#endif - //Tracev((stderr, "inflate: table sizes ok\n")); - state.have = 0; - state.mode = LENLENS; - /* falls through */ - case LENLENS: - while (state.have < state.ncode) { - //=== NEEDBITS(3); - while (bits < 3) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - state.lens[order[state.have++]] = (hold & 0x07);//BITS(3); - //--- DROPBITS(3) ---// - hold >>>= 3; - bits -= 3; - //---// - } - while (state.have < 19) { - state.lens[order[state.have++]] = 0; - } - // We have separate tables & no pointers. 2 commented lines below not needed. - //state.next = state.codes; - //state.lencode = state.next; - // Switch to use dynamic table - state.lencode = state.lendyn; - state.lenbits = 7; + } + if (this.isZero()) { + out = '0' + out; + } + while (out.length % padding !== 0) { + out = '0' + out; + } + if (this.negative !== 0) { + out = '-' + out; + } + return out; + } - opts = { bits: state.lenbits }; - ret = inflate_table(CODES, state.lens, 0, 19, state.lencode, 0, state.work, opts); - state.lenbits = opts.bits; + assert(false, 'Base should be between 2 and 36'); + }; - if (ret) { - strm.msg = 'invalid code lengths set'; - state.mode = BAD; - break; - } - //Tracev((stderr, "inflate: code lengths ok\n")); - state.have = 0; - state.mode = CODELENS; - /* falls through */ - case CODELENS: - while (state.have < state.nlen + state.ndist) { - for (;;) { - here = state.lencode[hold & ((1 << state.lenbits) - 1)];/*BITS(state.lenbits)*/ - here_bits = here >>> 24; - here_op = (here >>> 16) & 0xff; - here_val = here & 0xffff; + BN.prototype.toNumber = function toNumber () { + var ret = this.words[0]; + if (this.length === 2) { + ret += this.words[1] * 0x4000000; + } else if (this.length === 3 && this.words[2] === 0x01) { + // NOTE: at this stage it is known that the top bit is set + ret += 0x10000000000000 + (this.words[1] * 0x4000000); + } else if (this.length > 2) { + assert(false, 'Number can only safely store up to 53 bits'); + } + return (this.negative !== 0) ? -ret : ret; + }; - if ((here_bits) <= bits) { break; } - //--- PULLBYTE() ---// - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - //---// - } - if (here_val < 16) { - //--- DROPBITS(here.bits) ---// - hold >>>= here_bits; - bits -= here_bits; - //---// - state.lens[state.have++] = here_val; - } - else { - if (here_val === 16) { - //=== NEEDBITS(here.bits + 2); - n = here_bits + 2; - while (bits < n) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - //--- DROPBITS(here.bits) ---// - hold >>>= here_bits; - bits -= here_bits; - //---// - if (state.have === 0) { - strm.msg = 'invalid bit length repeat'; - state.mode = BAD; - break; - } - len = state.lens[state.have - 1]; - copy = 3 + (hold & 0x03);//BITS(2); - //--- DROPBITS(2) ---// - hold >>>= 2; - bits -= 2; - //---// - } - else if (here_val === 17) { - //=== NEEDBITS(here.bits + 3); - n = here_bits + 3; - while (bits < n) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - //--- DROPBITS(here.bits) ---// - hold >>>= here_bits; - bits -= here_bits; - //---// - len = 0; - copy = 3 + (hold & 0x07);//BITS(3); - //--- DROPBITS(3) ---// - hold >>>= 3; - bits -= 3; - //---// - } - else { - //=== NEEDBITS(here.bits + 7); - n = here_bits + 7; - while (bits < n) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - //--- DROPBITS(here.bits) ---// - hold >>>= here_bits; - bits -= here_bits; - //---// - len = 0; - copy = 11 + (hold & 0x7f);//BITS(7); - //--- DROPBITS(7) ---// - hold >>>= 7; - bits -= 7; - //---// - } - if (state.have + copy > state.nlen + state.ndist) { - strm.msg = 'invalid bit length repeat'; - state.mode = BAD; - break; - } - while (copy--) { - state.lens[state.have++] = len; - } - } - } + BN.prototype.toJSON = function toJSON () { + return this.toString(16); + }; - /* handle error breaks in while */ - if (state.mode === BAD) { break; } + BN.prototype.toBuffer = function toBuffer (endian, length) { + assert(typeof Buffer !== 'undefined'); + return this.toArrayLike(Buffer, endian, length); + }; - /* check for end-of-block code (better have one) */ - if (state.lens[256] === 0) { - strm.msg = 'invalid code -- missing end-of-block'; - state.mode = BAD; - break; - } + BN.prototype.toArray = function toArray (endian, length) { + return this.toArrayLike(Array, endian, length); + }; - /* build code tables -- note: do not change the lenbits or distbits - values here (9 and 6) without reading the comments in inftrees.h - concerning the ENOUGH constants, which depend on those values */ - state.lenbits = 9; + BN.prototype.toArrayLike = function toArrayLike (ArrayType, endian, length) { + var byteLength = this.byteLength(); + var reqLength = length || Math.max(1, byteLength); + assert(byteLength <= reqLength, 'byte array longer than desired length'); + assert(reqLength > 0, 'Requested array length <= 0'); - opts = { bits: state.lenbits }; - ret = inflate_table(LENS, state.lens, 0, state.nlen, state.lencode, 0, state.work, opts); - // We have separate tables & no pointers. 2 commented lines below not needed. - // state.next_index = opts.table_index; - state.lenbits = opts.bits; - // state.lencode = state.next; + this.strip(); + var littleEndian = endian === 'le'; + var res = new ArrayType(reqLength); - if (ret) { - strm.msg = 'invalid literal/lengths set'; - state.mode = BAD; - break; - } + var b, i; + var q = this.clone(); + if (!littleEndian) { + // Assume big-endian + for (i = 0; i < reqLength - byteLength; i++) { + res[i] = 0; + } - state.distbits = 6; - //state.distcode.copy(state.codes); - // Switch to use dynamic table - state.distcode = state.distdyn; - opts = { bits: state.distbits }; - ret = inflate_table(DISTS, state.lens, state.nlen, state.ndist, state.distcode, 0, state.work, opts); - // We have separate tables & no pointers. 2 commented lines below not needed. - // state.next_index = opts.table_index; - state.distbits = opts.bits; - // state.distcode = state.next; + for (i = 0; !q.isZero(); i++) { + b = q.andln(0xff); + q.iushrn(8); - if (ret) { - strm.msg = 'invalid distances set'; - state.mode = BAD; - break; - } - //Tracev((stderr, 'inflate: codes ok\n')); - state.mode = LEN_; - if (flush === Z_TREES) { break inf_leave; } - /* falls through */ - case LEN_: - state.mode = LEN; - /* falls through */ - case LEN: - if (have >= 6 && left >= 258) { - //--- RESTORE() --- - strm.next_out = put; - strm.avail_out = left; - strm.next_in = next; - strm.avail_in = have; - state.hold = hold; - state.bits = bits; - //--- - inflate_fast(strm, _out); - //--- LOAD() --- - put = strm.next_out; - output = strm.output; - left = strm.avail_out; - next = strm.next_in; - input = strm.input; - have = strm.avail_in; - hold = state.hold; - bits = state.bits; - //--- + res[reqLength - i - 1] = b; + } + } else { + for (i = 0; !q.isZero(); i++) { + b = q.andln(0xff); + q.iushrn(8); - if (state.mode === TYPE) { - state.back = -1; - } - break; - } - state.back = 0; - for (;;) { - here = state.lencode[hold & ((1 << state.lenbits) - 1)]; /*BITS(state.lenbits)*/ - here_bits = here >>> 24; - here_op = (here >>> 16) & 0xff; - here_val = here & 0xffff; + res[i] = b; + } - if (here_bits <= bits) { break; } - //--- PULLBYTE() ---// - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - //---// - } - if (here_op && (here_op & 0xf0) === 0) { - last_bits = here_bits; - last_op = here_op; - last_val = here_val; - for (;;) { - here = state.lencode[last_val + - ((hold & ((1 << (last_bits + last_op)) - 1))/*BITS(last.bits + last.op)*/ >> last_bits)]; - here_bits = here >>> 24; - here_op = (here >>> 16) & 0xff; - here_val = here & 0xffff; + for (; i < reqLength; i++) { + res[i] = 0; + } + } - if ((last_bits + here_bits) <= bits) { break; } - //--- PULLBYTE() ---// - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - //---// - } - //--- DROPBITS(last.bits) ---// - hold >>>= last_bits; - bits -= last_bits; - //---// - state.back += last_bits; - } - //--- DROPBITS(here.bits) ---// - hold >>>= here_bits; - bits -= here_bits; - //---// - state.back += here_bits; - state.length = here_val; - if (here_op === 0) { - //Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? - // "inflate: literal '%c'\n" : - // "inflate: literal 0x%02x\n", here.val)); - state.mode = LIT; - break; - } - if (here_op & 32) { - //Tracevv((stderr, "inflate: end of block\n")); - state.back = -1; - state.mode = TYPE; - break; - } - if (here_op & 64) { - strm.msg = 'invalid literal/length code'; - state.mode = BAD; - break; - } - state.extra = here_op & 15; - state.mode = LENEXT; - /* falls through */ - case LENEXT: - if (state.extra) { - //=== NEEDBITS(state.extra); - n = state.extra; - while (bits < n) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - state.length += hold & ((1 << state.extra) - 1)/*BITS(state.extra)*/; - //--- DROPBITS(state.extra) ---// - hold >>>= state.extra; - bits -= state.extra; - //---// - state.back += state.extra; - } - //Tracevv((stderr, "inflate: length %u\n", state.length)); - state.was = state.length; - state.mode = DIST; - /* falls through */ - case DIST: - for (;;) { - here = state.distcode[hold & ((1 << state.distbits) - 1)];/*BITS(state.distbits)*/ - here_bits = here >>> 24; - here_op = (here >>> 16) & 0xff; - here_val = here & 0xffff; + return res; + }; - if ((here_bits) <= bits) { break; } - //--- PULLBYTE() ---// - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - //---// - } - if ((here_op & 0xf0) === 0) { - last_bits = here_bits; - last_op = here_op; - last_val = here_val; - for (;;) { - here = state.distcode[last_val + - ((hold & ((1 << (last_bits + last_op)) - 1))/*BITS(last.bits + last.op)*/ >> last_bits)]; - here_bits = here >>> 24; - here_op = (here >>> 16) & 0xff; - here_val = here & 0xffff; + if (Math.clz32) { + BN.prototype._countBits = function _countBits (w) { + return 32 - Math.clz32(w); + }; + } else { + BN.prototype._countBits = function _countBits (w) { + var t = w; + var r = 0; + if (t >= 0x1000) { + r += 13; + t >>>= 13; + } + if (t >= 0x40) { + r += 7; + t >>>= 7; + } + if (t >= 0x8) { + r += 4; + t >>>= 4; + } + if (t >= 0x02) { + r += 2; + t >>>= 2; + } + return r + t; + }; + } - if ((last_bits + here_bits) <= bits) { break; } - //--- PULLBYTE() ---// - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - //---// - } - //--- DROPBITS(last.bits) ---// - hold >>>= last_bits; - bits -= last_bits; - //---// - state.back += last_bits; - } - //--- DROPBITS(here.bits) ---// - hold >>>= here_bits; - bits -= here_bits; - //---// - state.back += here_bits; - if (here_op & 64) { - strm.msg = 'invalid distance code'; - state.mode = BAD; - break; - } - state.offset = here_val; - state.extra = (here_op) & 15; - state.mode = DISTEXT; - /* falls through */ - case DISTEXT: - if (state.extra) { - //=== NEEDBITS(state.extra); - n = state.extra; - while (bits < n) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - state.offset += hold & ((1 << state.extra) - 1)/*BITS(state.extra)*/; - //--- DROPBITS(state.extra) ---// - hold >>>= state.extra; - bits -= state.extra; - //---// - state.back += state.extra; - } -//#ifdef INFLATE_STRICT - if (state.offset > state.dmax) { - strm.msg = 'invalid distance too far back'; - state.mode = BAD; - break; - } -//#endif - //Tracevv((stderr, "inflate: distance %u\n", state.offset)); - state.mode = MATCH; - /* falls through */ - case MATCH: - if (left === 0) { break inf_leave; } - copy = _out - left; - if (state.offset > copy) { /* copy from window */ - copy = state.offset - copy; - if (copy > state.whave) { - if (state.sane) { - strm.msg = 'invalid distance too far back'; - state.mode = BAD; - break; - } -// (!) This block is disabled in zlib defaults, -// don't enable it for binary compatibility -//#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR -// Trace((stderr, "inflate.c too far\n")); -// copy -= state.whave; -// if (copy > state.length) { copy = state.length; } -// if (copy > left) { copy = left; } -// left -= copy; -// state.length -= copy; -// do { -// output[put++] = 0; -// } while (--copy); -// if (state.length === 0) { state.mode = LEN; } -// break; -//#endif - } - if (copy > state.wnext) { - copy -= state.wnext; - from = state.wsize - copy; - } - else { - from = state.wnext - copy; - } - if (copy > state.length) { copy = state.length; } - from_source = state.window; - } - else { /* copy from output */ - from_source = output; - from = put - state.offset; - copy = state.length; - } - if (copy > left) { copy = left; } - left -= copy; - state.length -= copy; - do { - output[put++] = from_source[from++]; - } while (--copy); - if (state.length === 0) { state.mode = LEN; } - break; - case LIT: - if (left === 0) { break inf_leave; } - output[put++] = state.length; - left--; - state.mode = LEN; - break; - case CHECK: - if (state.wrap) { - //=== NEEDBITS(32); - while (bits < 32) { - if (have === 0) { break inf_leave; } - have--; - // Use '|' instead of '+' to make sure that result is signed - hold |= input[next++] << bits; - bits += 8; - } - //===// - _out -= left; - strm.total_out += _out; - state.total += _out; - if (_out) { - strm.adler = state.check = - /*UPDATE(state.check, put - _out, _out);*/ - (state.flags ? crc32(state.check, output, _out, put - _out) : adler32(state.check, output, _out, put - _out)); + BN.prototype._zeroBits = function _zeroBits (w) { + // Short-cut + if (w === 0) return 26; - } - _out = left; - // NB: crc32 stored as signed 32-bit int, zswap32 returns signed too - if ((state.flags ? hold : zswap32(hold)) !== state.check) { - strm.msg = 'incorrect data check'; - state.mode = BAD; - break; - } - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - //Tracev((stderr, "inflate: check matches trailer\n")); - } - state.mode = LENGTH; - /* falls through */ - case LENGTH: - if (state.wrap && state.flags) { - //=== NEEDBITS(32); - while (bits < 32) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - if (hold !== (state.total & 0xffffffff)) { - strm.msg = 'incorrect length check'; - state.mode = BAD; - break; - } - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - //Tracev((stderr, "inflate: length matches trailer\n")); - } - state.mode = DONE; - /* falls through */ - case DONE: - ret = Z_STREAM_END; - break inf_leave; - case BAD: - ret = Z_DATA_ERROR; - break inf_leave; - case MEM: - return Z_MEM_ERROR; - case SYNC: - /* falls through */ - default: - return Z_STREAM_ERROR; + var t = w; + var r = 0; + if ((t & 0x1fff) === 0) { + r += 13; + t >>>= 13; } - } + if ((t & 0x7f) === 0) { + r += 7; + t >>>= 7; + } + if ((t & 0xf) === 0) { + r += 4; + t >>>= 4; + } + if ((t & 0x3) === 0) { + r += 2; + t >>>= 2; + } + if ((t & 0x1) === 0) { + r++; + } + return r; + }; - // inf_leave <- here is real place for "goto inf_leave", emulated via "break inf_leave" + // Return number of used bits in a BN + BN.prototype.bitLength = function bitLength () { + var w = this.words[this.length - 1]; + var hi = this._countBits(w); + return (this.length - 1) * 26 + hi; + }; - /* - Return from inflate(), updating the total counts and the check value. - If there was no progress during the inflate() call, return a buffer - error. Call updatewindow() to create and/or update the window state. - Note: a memory error from inflate() is non-recoverable. - */ + function toBitArray (num) { + var w = new Array(num.bitLength()); - //--- RESTORE() --- - strm.next_out = put; - strm.avail_out = left; - strm.next_in = next; - strm.avail_in = have; - state.hold = hold; - state.bits = bits; - //--- + for (var bit = 0; bit < w.length; bit++) { + var off = (bit / 26) | 0; + var wbit = bit % 26; - if (state.wsize || (_out !== strm.avail_out && state.mode < BAD && - (state.mode < CHECK || flush !== Z_FINISH))) { - if (updatewindow(strm, strm.output, strm.next_out, _out - strm.avail_out)) { - state.mode = MEM; - return Z_MEM_ERROR; + w[bit] = (num.words[off] & (1 << wbit)) >>> wbit; } - } - _in -= strm.avail_in; - _out -= strm.avail_out; - strm.total_in += _in; - strm.total_out += _out; - state.total += _out; - if (state.wrap && _out) { - strm.adler = state.check = /*UPDATE(state.check, strm.next_out - _out, _out);*/ - (state.flags ? crc32(state.check, output, _out, strm.next_out - _out) : adler32(state.check, output, _out, strm.next_out - _out)); - } - strm.data_type = state.bits + (state.last ? 64 : 0) + - (state.mode === TYPE ? 128 : 0) + - (state.mode === LEN_ || state.mode === COPY_ ? 256 : 0); - if (((_in === 0 && _out === 0) || flush === Z_FINISH) && ret === Z_OK) { - ret = Z_BUF_ERROR; - } - return ret; -}; - - -const inflateEnd = (strm) => { - if (!strm || !strm.state /*|| strm->zfree == (free_func)0*/) { - return Z_STREAM_ERROR; + return w; } - let state = strm.state; - if (state.window) { - state.window = null; - } - strm.state = null; - return Z_OK; -}; + // Number of trailing zero bits + BN.prototype.zeroBits = function zeroBits () { + if (this.isZero()) return 0; + var r = 0; + for (var i = 0; i < this.length; i++) { + var b = this._zeroBits(this.words[i]); + r += b; + if (b !== 26) break; + } + return r; + }; -const inflateGetHeader = (strm, head) => { + BN.prototype.byteLength = function byteLength () { + return Math.ceil(this.bitLength() / 8); + }; - /* check state */ - if (!strm || !strm.state) { return Z_STREAM_ERROR; } - const state = strm.state; - if ((state.wrap & 2) === 0) { return Z_STREAM_ERROR; } + BN.prototype.toTwos = function toTwos (width) { + if (this.negative !== 0) { + return this.abs().inotn(width).iaddn(1); + } + return this.clone(); + }; - /* save header structure */ - state.head = head; - head.done = false; - return Z_OK; -}; + BN.prototype.fromTwos = function fromTwos (width) { + if (this.testn(width - 1)) { + return this.notn(width).iaddn(1).ineg(); + } + return this.clone(); + }; + BN.prototype.isNeg = function isNeg () { + return this.negative !== 0; + }; -const inflateSetDictionary = (strm, dictionary) => { - const dictLength = dictionary.length; + // Return negative clone of `this` + BN.prototype.neg = function neg () { + return this.clone().ineg(); + }; - let state; - let dictid; - let ret; + BN.prototype.ineg = function ineg () { + if (!this.isZero()) { + this.negative ^= 1; + } - /* check state */ - if (!strm /* == Z_NULL */ || !strm.state /* == Z_NULL */) { return Z_STREAM_ERROR; } - state = strm.state; + return this; + }; - if (state.wrap !== 0 && state.mode !== DICT) { - return Z_STREAM_ERROR; - } + // Or `num` with `this` in-place + BN.prototype.iuor = function iuor (num) { + while (this.length < num.length) { + this.words[this.length++] = 0; + } - /* check for correct dictionary identifier */ - if (state.mode === DICT) { - dictid = 1; /* adler32(0, null, 0)*/ - /* dictid = adler32(dictid, dictionary, dictLength); */ - dictid = adler32(dictid, dictionary, dictLength, 0); - if (dictid !== state.check) { - return Z_DATA_ERROR; + for (var i = 0; i < num.length; i++) { + this.words[i] = this.words[i] | num.words[i]; } - } - /* copy dictionary to window using updatewindow(), which will amend the - existing dictionary if appropriate */ - ret = updatewindow(strm, dictionary, dictLength, dictLength); - if (ret) { - state.mode = MEM; - return Z_MEM_ERROR; - } - state.havedict = 1; - // Tracev((stderr, "inflate: dictionary set\n")); - return Z_OK; -}; + return this.strip(); + }; -module.exports.inflateReset = inflateReset; -module.exports.inflateReset2 = inflateReset2; -module.exports.inflateResetKeep = inflateResetKeep; -module.exports.inflateInit = inflateInit; -module.exports.inflateInit2 = inflateInit2; -module.exports.inflate = inflate; -module.exports.inflateEnd = inflateEnd; -module.exports.inflateGetHeader = inflateGetHeader; -module.exports.inflateSetDictionary = inflateSetDictionary; -module.exports.inflateInfo = 'pako inflate (from Nodeca project)'; + BN.prototype.ior = function ior (num) { + assert((this.negative | num.negative) === 0); + return this.iuor(num); + }; -/* Not implemented -module.exports.inflateCopy = inflateCopy; -module.exports.inflateGetDictionary = inflateGetDictionary; -module.exports.inflateMark = inflateMark; -module.exports.inflatePrime = inflatePrime; -module.exports.inflateSync = inflateSync; -module.exports.inflateSyncPoint = inflateSyncPoint; -module.exports.inflateUndermine = inflateUndermine; -*/ + // Or `num` with `this` + BN.prototype.or = function or (num) { + if (this.length > num.length) return this.clone().ior(num); + return num.clone().ior(this); + }; -},{"./adler32":70,"./constants":71,"./crc32":72,"./inffast":75,"./inftrees":77}],77:[function(require,module,exports){ -'use strict'; + BN.prototype.uor = function uor (num) { + if (this.length > num.length) return this.clone().iuor(num); + return num.clone().iuor(this); + }; -// (C) 1995-2013 Jean-loup Gailly and Mark Adler -// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. + // And `num` with `this` in-place + BN.prototype.iuand = function iuand (num) { + // b = min-length(num, this) + var b; + if (this.length > num.length) { + b = num; + } else { + b = this; + } -const MAXBITS = 15; -const ENOUGH_LENS = 852; -const ENOUGH_DISTS = 592; -//const ENOUGH = (ENOUGH_LENS+ENOUGH_DISTS); + for (var i = 0; i < b.length; i++) { + this.words[i] = this.words[i] & num.words[i]; + } -const CODES = 0; -const LENS = 1; -const DISTS = 2; + this.length = b.length; -const lbase = new Uint16Array([ /* Length codes 257..285 base */ - 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, - 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0 -]); + return this.strip(); + }; -const lext = new Uint8Array([ /* Length codes 257..285 extra */ - 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, - 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 72, 78 -]); + BN.prototype.iand = function iand (num) { + assert((this.negative | num.negative) === 0); + return this.iuand(num); + }; -const dbase = new Uint16Array([ /* Distance codes 0..29 base */ - 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, - 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, - 8193, 12289, 16385, 24577, 0, 0 -]); + // And `num` with `this` + BN.prototype.and = function and (num) { + if (this.length > num.length) return this.clone().iand(num); + return num.clone().iand(this); + }; -const dext = new Uint8Array([ /* Distance codes 0..29 extra */ - 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, - 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, - 28, 28, 29, 29, 64, 64 -]); + BN.prototype.uand = function uand (num) { + if (this.length > num.length) return this.clone().iuand(num); + return num.clone().iuand(this); + }; -const inflate_table = (type, lens, lens_index, codes, table, table_index, work, opts) => -{ - const bits = opts.bits; - //here = opts.here; /* table entry for duplication */ + // Xor `num` with `this` in-place + BN.prototype.iuxor = function iuxor (num) { + // a.length > b.length + var a; + var b; + if (this.length > num.length) { + a = this; + b = num; + } else { + a = num; + b = this; + } - let len = 0; /* a code's length in bits */ - let sym = 0; /* index of code symbols */ - let min = 0, max = 0; /* minimum and maximum code lengths */ - let root = 0; /* number of index bits for root table */ - let curr = 0; /* number of index bits for current table */ - let drop = 0; /* code bits to drop for sub-table */ - let left = 0; /* number of prefix codes available */ - let used = 0; /* code entries in table used */ - let huff = 0; /* Huffman code */ - let incr; /* for incrementing code, index */ - let fill; /* index for replicating entries */ - let low; /* low bits for current root entry */ - let mask; /* mask for low root bits */ - let next; /* next available space in table */ - let base = null; /* base value table to use */ - let base_index = 0; -// let shoextra; /* extra bits table to use */ - let end; /* use base and extra for symbol > end */ - const count = new Uint16Array(MAXBITS + 1); //[MAXBITS+1]; /* number of codes of each length */ - const offs = new Uint16Array(MAXBITS + 1); //[MAXBITS+1]; /* offsets in table for each length */ - let extra = null; - let extra_index = 0; + for (var i = 0; i < b.length; i++) { + this.words[i] = a.words[i] ^ b.words[i]; + } - let here_bits, here_op, here_val; + if (this !== a) { + for (; i < a.length; i++) { + this.words[i] = a.words[i]; + } + } - /* - Process a set of code lengths to create a canonical Huffman code. The - code lengths are lens[0..codes-1]. Each length corresponds to the - symbols 0..codes-1. The Huffman code is generated by first sorting the - symbols by length from short to long, and retaining the symbol order - for codes with equal lengths. Then the code starts with all zero bits - for the first code of the shortest length, and the codes are integer - increments for the same length, and zeros are appended as the length - increases. For the deflate format, these bits are stored backwards - from their more natural integer increment ordering, and so when the - decoding tables are built in the large loop below, the integer codes - are incremented backwards. + this.length = a.length; - This routine assumes, but does not check, that all of the entries in - lens[] are in the range 0..MAXBITS. The caller must assure this. - 1..MAXBITS is interpreted as that code length. zero means that that - symbol does not occur in this code. + return this.strip(); + }; - The codes are sorted by computing a count of codes for each length, - creating from that a table of starting indices for each length in the - sorted table, and then entering the symbols in order in the sorted - table. The sorted table is work[], with that space being provided by - the caller. + BN.prototype.ixor = function ixor (num) { + assert((this.negative | num.negative) === 0); + return this.iuxor(num); + }; - The length counts are used for other purposes as well, i.e. finding - the minimum and maximum length codes, determining if there are any - codes at all, checking for a valid set of lengths, and looking ahead - at length counts to determine sub-table sizes when building the - decoding tables. - */ + // Xor `num` with `this` + BN.prototype.xor = function xor (num) { + if (this.length > num.length) return this.clone().ixor(num); + return num.clone().ixor(this); + }; - /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */ - for (len = 0; len <= MAXBITS; len++) { - count[len] = 0; - } - for (sym = 0; sym < codes; sym++) { - count[lens[lens_index + sym]]++; - } + BN.prototype.uxor = function uxor (num) { + if (this.length > num.length) return this.clone().iuxor(num); + return num.clone().iuxor(this); + }; - /* bound code lengths, force root to be within code lengths */ - root = bits; - for (max = MAXBITS; max >= 1; max--) { - if (count[max] !== 0) { break; } - } - if (root > max) { - root = max; - } - if (max === 0) { /* no symbols to code at all */ - //table.op[opts.table_index] = 64; //here.op = (var char)64; /* invalid code marker */ - //table.bits[opts.table_index] = 1; //here.bits = (var char)1; - //table.val[opts.table_index++] = 0; //here.val = (var short)0; - table[table_index++] = (1 << 24) | (64 << 16) | 0; + // Not ``this`` with ``width`` bitwidth + BN.prototype.inotn = function inotn (width) { + assert(typeof width === 'number' && width >= 0); + var bytesNeeded = Math.ceil(width / 26) | 0; + var bitsLeft = width % 26; - //table.op[opts.table_index] = 64; - //table.bits[opts.table_index] = 1; - //table.val[opts.table_index++] = 0; - table[table_index++] = (1 << 24) | (64 << 16) | 0; + // Extend the buffer with leading zeroes + this._expand(bytesNeeded); - opts.bits = 1; - return 0; /* no symbols, but wait for decoding to report error */ - } - for (min = 1; min < max; min++) { - if (count[min] !== 0) { break; } - } - if (root < min) { - root = min; - } - - /* check for an over-subscribed or incomplete set of lengths */ - left = 1; - for (len = 1; len <= MAXBITS; len++) { - left <<= 1; - left -= count[len]; - if (left < 0) { - return -1; - } /* over-subscribed */ - } - if (left > 0 && (type === CODES || max !== 1)) { - return -1; /* incomplete set */ - } - - /* generate offsets into symbol table for each length for sorting */ - offs[1] = 0; - for (len = 1; len < MAXBITS; len++) { - offs[len + 1] = offs[len] + count[len]; - } + if (bitsLeft > 0) { + bytesNeeded--; + } - /* sort symbols by length, by symbol order within each length */ - for (sym = 0; sym < codes; sym++) { - if (lens[lens_index + sym] !== 0) { - work[offs[lens[lens_index + sym]]++] = sym; + // Handle complete words + for (var i = 0; i < bytesNeeded; i++) { + this.words[i] = ~this.words[i] & 0x3ffffff; } - } - /* - Create and fill in decoding tables. In this loop, the table being - filled is at next and has curr index bits. The code being used is huff - with length len. That code is converted to an index by dropping drop - bits off of the bottom. For codes where len is less than drop + curr, - those top drop + curr - len bits are incremented through all values to - fill the table with replicated entries. + // Handle the residue + if (bitsLeft > 0) { + this.words[i] = ~this.words[i] & (0x3ffffff >> (26 - bitsLeft)); + } - root is the number of index bits for the root table. When len exceeds - root, sub-tables are created pointed to by the root entry with an index - of the low root bits of huff. This is saved in low to check for when a - new sub-table should be started. drop is zero when the root table is - being filled, and drop is root when sub-tables are being filled. + // And remove leading zeroes + return this.strip(); + }; - When a new sub-table is needed, it is necessary to look ahead in the - code lengths to determine what size sub-table is needed. The length - counts are used for this, and so count[] is decremented as codes are - entered in the tables. + BN.prototype.notn = function notn (width) { + return this.clone().inotn(width); + }; - used keeps track of how many table entries have been allocated from the - provided *table space. It is checked for LENS and DIST tables against - the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in - the initial root table size constants. See the comments in inftrees.h - for more information. + // Set `bit` of `this` + BN.prototype.setn = function setn (bit, val) { + assert(typeof bit === 'number' && bit >= 0); - sym increments through all symbols, and the loop terminates when - all codes of length max, i.e. all codes, have been processed. This - routine permits incomplete codes, so another loop after this one fills - in the rest of the decoding tables with invalid code markers. - */ + var off = (bit / 26) | 0; + var wbit = bit % 26; - /* set up for code type */ - // poor man optimization - use if-else instead of switch, - // to avoid deopts in old v8 - if (type === CODES) { - base = extra = work; /* dummy value--not used */ - end = 19; + this._expand(off + 1); - } else if (type === LENS) { - base = lbase; - base_index -= 257; - extra = lext; - extra_index -= 257; - end = 256; + if (val) { + this.words[off] = this.words[off] | (1 << wbit); + } else { + this.words[off] = this.words[off] & ~(1 << wbit); + } - } else { /* DISTS */ - base = dbase; - extra = dext; - end = -1; - } + return this.strip(); + }; - /* initialize opts for loop */ - huff = 0; /* starting code */ - sym = 0; /* starting code symbol */ - len = min; /* starting code length */ - next = table_index; /* current table to fill in */ - curr = root; /* current table index bits */ - drop = 0; /* current bits to drop from code for index */ - low = -1; /* trigger new sub-table when len > root */ - used = 1 << root; /* use root table entries */ - mask = used - 1; /* mask for comparing low */ + // Add `num` to `this` in-place + BN.prototype.iadd = function iadd (num) { + var r; - /* check available table space */ - if ((type === LENS && used > ENOUGH_LENS) || - (type === DISTS && used > ENOUGH_DISTS)) { - return 1; - } + // negative + positive + if (this.negative !== 0 && num.negative === 0) { + this.negative = 0; + r = this.isub(num); + this.negative ^= 1; + return this._normSign(); - /* process all codes and make table entries */ - for (;;) { - /* create table entry */ - here_bits = len - drop; - if (work[sym] < end) { - here_op = 0; - here_val = work[sym]; - } - else if (work[sym] > end) { - here_op = extra[extra_index + work[sym]]; - here_val = base[base_index + work[sym]]; - } - else { - here_op = 32 + 64; /* end of block */ - here_val = 0; + // positive + negative + } else if (this.negative === 0 && num.negative !== 0) { + num.negative = 0; + r = this.isub(num); + num.negative = 1; + return r._normSign(); } - /* replicate for those indices with low len bits equal to huff */ - incr = 1 << (len - drop); - fill = 1 << curr; - min = fill; /* save offset to next table */ - do { - fill -= incr; - table[next + (huff >> drop) + fill] = (here_bits << 24) | (here_op << 16) | here_val |0; - } while (fill !== 0); - - /* backwards increment the len-bit code huff */ - incr = 1 << (len - 1); - while (huff & incr) { - incr >>= 1; - } - if (incr !== 0) { - huff &= incr - 1; - huff += incr; + // a.length > b.length + var a, b; + if (this.length > num.length) { + a = this; + b = num; } else { - huff = 0; + a = num; + b = this; } - /* go to next symbol, update count, len */ - sym++; - if (--count[len] === 0) { - if (len === max) { break; } - len = lens[lens_index + work[sym]]; + var carry = 0; + for (var i = 0; i < b.length; i++) { + r = (a.words[i] | 0) + (b.words[i] | 0) + carry; + this.words[i] = r & 0x3ffffff; + carry = r >>> 26; + } + for (; carry !== 0 && i < a.length; i++) { + r = (a.words[i] | 0) + carry; + this.words[i] = r & 0x3ffffff; + carry = r >>> 26; } - /* create new sub-table if needed */ - if (len > root && (huff & mask) !== low) { - /* if first time, transition to sub-tables */ - if (drop === 0) { - drop = root; - } - - /* increment past last table */ - next += min; /* here min is 1 << curr */ - - /* determine length of next table */ - curr = len - drop; - left = 1 << curr; - while (curr + drop < max) { - left -= count[curr + drop]; - if (left <= 0) { break; } - curr++; - left <<= 1; - } - - /* check for enough space */ - used += 1 << curr; - if ((type === LENS && used > ENOUGH_LENS) || - (type === DISTS && used > ENOUGH_DISTS)) { - return 1; + this.length = a.length; + if (carry !== 0) { + this.words[this.length] = carry; + this.length++; + // Copy the rest of the words + } else if (a !== this) { + for (; i < a.length; i++) { + this.words[i] = a.words[i]; } - - /* point entry in root table to sub-table */ - low = huff & mask; - /*table.op[low] = curr; - table.bits[low] = root; - table.val[low] = next - opts.table_index;*/ - table[low] = (root << 24) | (curr << 16) | (next - table_index) |0; } - } - - /* fill in remaining table entry if code is incomplete (guaranteed to have - at most one remaining entry, since if the code is incomplete, the - maximum code length that was allowed to get this far is one bit) */ - if (huff !== 0) { - //table.op[next + huff] = 64; /* invalid code marker */ - //table.bits[next + huff] = len - drop; - //table.val[next + huff] = 0; - table[next + huff] = ((len - drop) << 24) | (64 << 16) |0; - } - - /* set return parameters */ - //opts.table_index += used; - opts.bits = root; - return 0; -}; + return this; + }; -module.exports = inflate_table; - -},{}],78:[function(require,module,exports){ -'use strict'; - -// (C) 1995-2013 Jean-loup Gailly and Mark Adler -// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. + // Add `num` to `this` + BN.prototype.add = function add (num) { + var res; + if (num.negative !== 0 && this.negative === 0) { + num.negative = 0; + res = this.sub(num); + num.negative ^= 1; + return res; + } else if (num.negative === 0 && this.negative !== 0) { + this.negative = 0; + res = num.sub(this); + this.negative = 1; + return res; + } -module.exports = { - 2: 'need dictionary', /* Z_NEED_DICT 2 */ - 1: 'stream end', /* Z_STREAM_END 1 */ - 0: '', /* Z_OK 0 */ - '-1': 'file error', /* Z_ERRNO (-1) */ - '-2': 'stream error', /* Z_STREAM_ERROR (-2) */ - '-3': 'data error', /* Z_DATA_ERROR (-3) */ - '-4': 'insufficient memory', /* Z_MEM_ERROR (-4) */ - '-5': 'buffer error', /* Z_BUF_ERROR (-5) */ - '-6': 'incompatible version' /* Z_VERSION_ERROR (-6) */ -}; + if (this.length > num.length) return this.clone().iadd(num); -},{}],79:[function(require,module,exports){ -'use strict'; + return num.clone().iadd(this); + }; -// (C) 1995-2013 Jean-loup Gailly and Mark Adler -// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. + // Subtract `num` from `this` in-place + BN.prototype.isub = function isub (num) { + // this - (-num) = this + num + if (num.negative !== 0) { + num.negative = 0; + var r = this.iadd(num); + num.negative = 1; + return r._normSign(); -/* eslint-disable space-unary-ops */ + // -this - num = -(this + num) + } else if (this.negative !== 0) { + this.negative = 0; + this.iadd(num); + this.negative = 1; + return this._normSign(); + } -/* Public constants ==========================================================*/ -/* ===========================================================================*/ + // At this point both numbers are positive + var cmp = this.cmp(num); + // Optimization - zeroify + if (cmp === 0) { + this.negative = 0; + this.length = 1; + this.words[0] = 0; + return this; + } -//const Z_FILTERED = 1; -//const Z_HUFFMAN_ONLY = 2; -//const Z_RLE = 3; -const Z_FIXED = 4; -//const Z_DEFAULT_STRATEGY = 0; + // a > b + var a, b; + if (cmp > 0) { + a = this; + b = num; + } else { + a = num; + b = this; + } -/* Possible values of the data_type field (though see inflate()) */ -const Z_BINARY = 0; -const Z_TEXT = 1; -//const Z_ASCII = 1; // = Z_TEXT -const Z_UNKNOWN = 2; + var carry = 0; + for (var i = 0; i < b.length; i++) { + r = (a.words[i] | 0) - (b.words[i] | 0) + carry; + carry = r >> 26; + this.words[i] = r & 0x3ffffff; + } + for (; carry !== 0 && i < a.length; i++) { + r = (a.words[i] | 0) + carry; + carry = r >> 26; + this.words[i] = r & 0x3ffffff; + } -/*============================================================================*/ + // Copy rest of the words + if (carry === 0 && i < a.length && a !== this) { + for (; i < a.length; i++) { + this.words[i] = a.words[i]; + } + } + this.length = Math.max(this.length, i); -function zero(buf) { let len = buf.length; while (--len >= 0) { buf[len] = 0; } } + if (a !== this) { + this.negative = 1; + } -// From zutil.h + return this.strip(); + }; -const STORED_BLOCK = 0; -const STATIC_TREES = 1; -const DYN_TREES = 2; -/* The three kinds of block type */ + // Subtract `num` from `this` + BN.prototype.sub = function sub (num) { + return this.clone().isub(num); + }; -const MIN_MATCH = 3; -const MAX_MATCH = 258; -/* The minimum and maximum match lengths */ + function smallMulTo (self, num, out) { + out.negative = num.negative ^ self.negative; + var len = (self.length + num.length) | 0; + out.length = len; + len = (len - 1) | 0; -// From deflate.h -/* =========================================================================== - * Internal compression state. - */ + // Peel one iteration (compiler can't do it, because of code complexity) + var a = self.words[0] | 0; + var b = num.words[0] | 0; + var r = a * b; -const LENGTH_CODES = 29; -/* number of length codes, not counting the special END_BLOCK code */ + var lo = r & 0x3ffffff; + var carry = (r / 0x4000000) | 0; + out.words[0] = lo; -const LITERALS = 256; -/* number of literal bytes 0..255 */ + for (var k = 1; k < len; k++) { + // Sum all words with the same `i + j = k` and accumulate `ncarry`, + // note that ncarry could be >= 0x3ffffff + var ncarry = carry >>> 26; + var rword = carry & 0x3ffffff; + var maxJ = Math.min(k, num.length - 1); + for (var j = Math.max(0, k - self.length + 1); j <= maxJ; j++) { + var i = (k - j) | 0; + a = self.words[i] | 0; + b = num.words[j] | 0; + r = a * b + rword; + ncarry += (r / 0x4000000) | 0; + rword = r & 0x3ffffff; + } + out.words[k] = rword | 0; + carry = ncarry | 0; + } + if (carry !== 0) { + out.words[k] = carry | 0; + } else { + out.length--; + } -const L_CODES = LITERALS + 1 + LENGTH_CODES; -/* number of Literal or Length codes, including the END_BLOCK code */ + return out.strip(); + } -const D_CODES = 30; -/* number of distance codes */ + // TODO(indutny): it may be reasonable to omit it for users who don't need + // to work with 256-bit numbers, otherwise it gives 20% improvement for 256-bit + // multiplication (like elliptic secp256k1). + var comb10MulTo = function comb10MulTo (self, num, out) { + var a = self.words; + var b = num.words; + var o = out.words; + var c = 0; + var lo; + var mid; + var hi; + var a0 = a[0] | 0; + var al0 = a0 & 0x1fff; + var ah0 = a0 >>> 13; + var a1 = a[1] | 0; + var al1 = a1 & 0x1fff; + var ah1 = a1 >>> 13; + var a2 = a[2] | 0; + var al2 = a2 & 0x1fff; + var ah2 = a2 >>> 13; + var a3 = a[3] | 0; + var al3 = a3 & 0x1fff; + var ah3 = a3 >>> 13; + var a4 = a[4] | 0; + var al4 = a4 & 0x1fff; + var ah4 = a4 >>> 13; + var a5 = a[5] | 0; + var al5 = a5 & 0x1fff; + var ah5 = a5 >>> 13; + var a6 = a[6] | 0; + var al6 = a6 & 0x1fff; + var ah6 = a6 >>> 13; + var a7 = a[7] | 0; + var al7 = a7 & 0x1fff; + var ah7 = a7 >>> 13; + var a8 = a[8] | 0; + var al8 = a8 & 0x1fff; + var ah8 = a8 >>> 13; + var a9 = a[9] | 0; + var al9 = a9 & 0x1fff; + var ah9 = a9 >>> 13; + var b0 = b[0] | 0; + var bl0 = b0 & 0x1fff; + var bh0 = b0 >>> 13; + var b1 = b[1] | 0; + var bl1 = b1 & 0x1fff; + var bh1 = b1 >>> 13; + var b2 = b[2] | 0; + var bl2 = b2 & 0x1fff; + var bh2 = b2 >>> 13; + var b3 = b[3] | 0; + var bl3 = b3 & 0x1fff; + var bh3 = b3 >>> 13; + var b4 = b[4] | 0; + var bl4 = b4 & 0x1fff; + var bh4 = b4 >>> 13; + var b5 = b[5] | 0; + var bl5 = b5 & 0x1fff; + var bh5 = b5 >>> 13; + var b6 = b[6] | 0; + var bl6 = b6 & 0x1fff; + var bh6 = b6 >>> 13; + var b7 = b[7] | 0; + var bl7 = b7 & 0x1fff; + var bh7 = b7 >>> 13; + var b8 = b[8] | 0; + var bl8 = b8 & 0x1fff; + var bh8 = b8 >>> 13; + var b9 = b[9] | 0; + var bl9 = b9 & 0x1fff; + var bh9 = b9 >>> 13; -const BL_CODES = 19; -/* number of codes used to transfer the bit lengths */ + out.negative = self.negative ^ num.negative; + out.length = 19; + /* k = 0 */ + lo = Math.imul(al0, bl0); + mid = Math.imul(al0, bh0); + mid = (mid + Math.imul(ah0, bl0)) | 0; + hi = Math.imul(ah0, bh0); + var w0 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w0 >>> 26)) | 0; + w0 &= 0x3ffffff; + /* k = 1 */ + lo = Math.imul(al1, bl0); + mid = Math.imul(al1, bh0); + mid = (mid + Math.imul(ah1, bl0)) | 0; + hi = Math.imul(ah1, bh0); + lo = (lo + Math.imul(al0, bl1)) | 0; + mid = (mid + Math.imul(al0, bh1)) | 0; + mid = (mid + Math.imul(ah0, bl1)) | 0; + hi = (hi + Math.imul(ah0, bh1)) | 0; + var w1 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w1 >>> 26)) | 0; + w1 &= 0x3ffffff; + /* k = 2 */ + lo = Math.imul(al2, bl0); + mid = Math.imul(al2, bh0); + mid = (mid + Math.imul(ah2, bl0)) | 0; + hi = Math.imul(ah2, bh0); + lo = (lo + Math.imul(al1, bl1)) | 0; + mid = (mid + Math.imul(al1, bh1)) | 0; + mid = (mid + Math.imul(ah1, bl1)) | 0; + hi = (hi + Math.imul(ah1, bh1)) | 0; + lo = (lo + Math.imul(al0, bl2)) | 0; + mid = (mid + Math.imul(al0, bh2)) | 0; + mid = (mid + Math.imul(ah0, bl2)) | 0; + hi = (hi + Math.imul(ah0, bh2)) | 0; + var w2 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w2 >>> 26)) | 0; + w2 &= 0x3ffffff; + /* k = 3 */ + lo = Math.imul(al3, bl0); + mid = Math.imul(al3, bh0); + mid = (mid + Math.imul(ah3, bl0)) | 0; + hi = Math.imul(ah3, bh0); + lo = (lo + Math.imul(al2, bl1)) | 0; + mid = (mid + Math.imul(al2, bh1)) | 0; + mid = (mid + Math.imul(ah2, bl1)) | 0; + hi = (hi + Math.imul(ah2, bh1)) | 0; + lo = (lo + Math.imul(al1, bl2)) | 0; + mid = (mid + Math.imul(al1, bh2)) | 0; + mid = (mid + Math.imul(ah1, bl2)) | 0; + hi = (hi + Math.imul(ah1, bh2)) | 0; + lo = (lo + Math.imul(al0, bl3)) | 0; + mid = (mid + Math.imul(al0, bh3)) | 0; + mid = (mid + Math.imul(ah0, bl3)) | 0; + hi = (hi + Math.imul(ah0, bh3)) | 0; + var w3 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w3 >>> 26)) | 0; + w3 &= 0x3ffffff; + /* k = 4 */ + lo = Math.imul(al4, bl0); + mid = Math.imul(al4, bh0); + mid = (mid + Math.imul(ah4, bl0)) | 0; + hi = Math.imul(ah4, bh0); + lo = (lo + Math.imul(al3, bl1)) | 0; + mid = (mid + Math.imul(al3, bh1)) | 0; + mid = (mid + Math.imul(ah3, bl1)) | 0; + hi = (hi + Math.imul(ah3, bh1)) | 0; + lo = (lo + Math.imul(al2, bl2)) | 0; + mid = (mid + Math.imul(al2, bh2)) | 0; + mid = (mid + Math.imul(ah2, bl2)) | 0; + hi = (hi + Math.imul(ah2, bh2)) | 0; + lo = (lo + Math.imul(al1, bl3)) | 0; + mid = (mid + Math.imul(al1, bh3)) | 0; + mid = (mid + Math.imul(ah1, bl3)) | 0; + hi = (hi + Math.imul(ah1, bh3)) | 0; + lo = (lo + Math.imul(al0, bl4)) | 0; + mid = (mid + Math.imul(al0, bh4)) | 0; + mid = (mid + Math.imul(ah0, bl4)) | 0; + hi = (hi + Math.imul(ah0, bh4)) | 0; + var w4 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w4 >>> 26)) | 0; + w4 &= 0x3ffffff; + /* k = 5 */ + lo = Math.imul(al5, bl0); + mid = Math.imul(al5, bh0); + mid = (mid + Math.imul(ah5, bl0)) | 0; + hi = Math.imul(ah5, bh0); + lo = (lo + Math.imul(al4, bl1)) | 0; + mid = (mid + Math.imul(al4, bh1)) | 0; + mid = (mid + Math.imul(ah4, bl1)) | 0; + hi = (hi + Math.imul(ah4, bh1)) | 0; + lo = (lo + Math.imul(al3, bl2)) | 0; + mid = (mid + Math.imul(al3, bh2)) | 0; + mid = (mid + Math.imul(ah3, bl2)) | 0; + hi = (hi + Math.imul(ah3, bh2)) | 0; + lo = (lo + Math.imul(al2, bl3)) | 0; + mid = (mid + Math.imul(al2, bh3)) | 0; + mid = (mid + Math.imul(ah2, bl3)) | 0; + hi = (hi + Math.imul(ah2, bh3)) | 0; + lo = (lo + Math.imul(al1, bl4)) | 0; + mid = (mid + Math.imul(al1, bh4)) | 0; + mid = (mid + Math.imul(ah1, bl4)) | 0; + hi = (hi + Math.imul(ah1, bh4)) | 0; + lo = (lo + Math.imul(al0, bl5)) | 0; + mid = (mid + Math.imul(al0, bh5)) | 0; + mid = (mid + Math.imul(ah0, bl5)) | 0; + hi = (hi + Math.imul(ah0, bh5)) | 0; + var w5 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w5 >>> 26)) | 0; + w5 &= 0x3ffffff; + /* k = 6 */ + lo = Math.imul(al6, bl0); + mid = Math.imul(al6, bh0); + mid = (mid + Math.imul(ah6, bl0)) | 0; + hi = Math.imul(ah6, bh0); + lo = (lo + Math.imul(al5, bl1)) | 0; + mid = (mid + Math.imul(al5, bh1)) | 0; + mid = (mid + Math.imul(ah5, bl1)) | 0; + hi = (hi + Math.imul(ah5, bh1)) | 0; + lo = (lo + Math.imul(al4, bl2)) | 0; + mid = (mid + Math.imul(al4, bh2)) | 0; + mid = (mid + Math.imul(ah4, bl2)) | 0; + hi = (hi + Math.imul(ah4, bh2)) | 0; + lo = (lo + Math.imul(al3, bl3)) | 0; + mid = (mid + Math.imul(al3, bh3)) | 0; + mid = (mid + Math.imul(ah3, bl3)) | 0; + hi = (hi + Math.imul(ah3, bh3)) | 0; + lo = (lo + Math.imul(al2, bl4)) | 0; + mid = (mid + Math.imul(al2, bh4)) | 0; + mid = (mid + Math.imul(ah2, bl4)) | 0; + hi = (hi + Math.imul(ah2, bh4)) | 0; + lo = (lo + Math.imul(al1, bl5)) | 0; + mid = (mid + Math.imul(al1, bh5)) | 0; + mid = (mid + Math.imul(ah1, bl5)) | 0; + hi = (hi + Math.imul(ah1, bh5)) | 0; + lo = (lo + Math.imul(al0, bl6)) | 0; + mid = (mid + Math.imul(al0, bh6)) | 0; + mid = (mid + Math.imul(ah0, bl6)) | 0; + hi = (hi + Math.imul(ah0, bh6)) | 0; + var w6 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w6 >>> 26)) | 0; + w6 &= 0x3ffffff; + /* k = 7 */ + lo = Math.imul(al7, bl0); + mid = Math.imul(al7, bh0); + mid = (mid + Math.imul(ah7, bl0)) | 0; + hi = Math.imul(ah7, bh0); + lo = (lo + Math.imul(al6, bl1)) | 0; + mid = (mid + Math.imul(al6, bh1)) | 0; + mid = (mid + Math.imul(ah6, bl1)) | 0; + hi = (hi + Math.imul(ah6, bh1)) | 0; + lo = (lo + Math.imul(al5, bl2)) | 0; + mid = (mid + Math.imul(al5, bh2)) | 0; + mid = (mid + Math.imul(ah5, bl2)) | 0; + hi = (hi + Math.imul(ah5, bh2)) | 0; + lo = (lo + Math.imul(al4, bl3)) | 0; + mid = (mid + Math.imul(al4, bh3)) | 0; + mid = (mid + Math.imul(ah4, bl3)) | 0; + hi = (hi + Math.imul(ah4, bh3)) | 0; + lo = (lo + Math.imul(al3, bl4)) | 0; + mid = (mid + Math.imul(al3, bh4)) | 0; + mid = (mid + Math.imul(ah3, bl4)) | 0; + hi = (hi + Math.imul(ah3, bh4)) | 0; + lo = (lo + Math.imul(al2, bl5)) | 0; + mid = (mid + Math.imul(al2, bh5)) | 0; + mid = (mid + Math.imul(ah2, bl5)) | 0; + hi = (hi + Math.imul(ah2, bh5)) | 0; + lo = (lo + Math.imul(al1, bl6)) | 0; + mid = (mid + Math.imul(al1, bh6)) | 0; + mid = (mid + Math.imul(ah1, bl6)) | 0; + hi = (hi + Math.imul(ah1, bh6)) | 0; + lo = (lo + Math.imul(al0, bl7)) | 0; + mid = (mid + Math.imul(al0, bh7)) | 0; + mid = (mid + Math.imul(ah0, bl7)) | 0; + hi = (hi + Math.imul(ah0, bh7)) | 0; + var w7 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w7 >>> 26)) | 0; + w7 &= 0x3ffffff; + /* k = 8 */ + lo = Math.imul(al8, bl0); + mid = Math.imul(al8, bh0); + mid = (mid + Math.imul(ah8, bl0)) | 0; + hi = Math.imul(ah8, bh0); + lo = (lo + Math.imul(al7, bl1)) | 0; + mid = (mid + Math.imul(al7, bh1)) | 0; + mid = (mid + Math.imul(ah7, bl1)) | 0; + hi = (hi + Math.imul(ah7, bh1)) | 0; + lo = (lo + Math.imul(al6, bl2)) | 0; + mid = (mid + Math.imul(al6, bh2)) | 0; + mid = (mid + Math.imul(ah6, bl2)) | 0; + hi = (hi + Math.imul(ah6, bh2)) | 0; + lo = (lo + Math.imul(al5, bl3)) | 0; + mid = (mid + Math.imul(al5, bh3)) | 0; + mid = (mid + Math.imul(ah5, bl3)) | 0; + hi = (hi + Math.imul(ah5, bh3)) | 0; + lo = (lo + Math.imul(al4, bl4)) | 0; + mid = (mid + Math.imul(al4, bh4)) | 0; + mid = (mid + Math.imul(ah4, bl4)) | 0; + hi = (hi + Math.imul(ah4, bh4)) | 0; + lo = (lo + Math.imul(al3, bl5)) | 0; + mid = (mid + Math.imul(al3, bh5)) | 0; + mid = (mid + Math.imul(ah3, bl5)) | 0; + hi = (hi + Math.imul(ah3, bh5)) | 0; + lo = (lo + Math.imul(al2, bl6)) | 0; + mid = (mid + Math.imul(al2, bh6)) | 0; + mid = (mid + Math.imul(ah2, bl6)) | 0; + hi = (hi + Math.imul(ah2, bh6)) | 0; + lo = (lo + Math.imul(al1, bl7)) | 0; + mid = (mid + Math.imul(al1, bh7)) | 0; + mid = (mid + Math.imul(ah1, bl7)) | 0; + hi = (hi + Math.imul(ah1, bh7)) | 0; + lo = (lo + Math.imul(al0, bl8)) | 0; + mid = (mid + Math.imul(al0, bh8)) | 0; + mid = (mid + Math.imul(ah0, bl8)) | 0; + hi = (hi + Math.imul(ah0, bh8)) | 0; + var w8 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w8 >>> 26)) | 0; + w8 &= 0x3ffffff; + /* k = 9 */ + lo = Math.imul(al9, bl0); + mid = Math.imul(al9, bh0); + mid = (mid + Math.imul(ah9, bl0)) | 0; + hi = Math.imul(ah9, bh0); + lo = (lo + Math.imul(al8, bl1)) | 0; + mid = (mid + Math.imul(al8, bh1)) | 0; + mid = (mid + Math.imul(ah8, bl1)) | 0; + hi = (hi + Math.imul(ah8, bh1)) | 0; + lo = (lo + Math.imul(al7, bl2)) | 0; + mid = (mid + Math.imul(al7, bh2)) | 0; + mid = (mid + Math.imul(ah7, bl2)) | 0; + hi = (hi + Math.imul(ah7, bh2)) | 0; + lo = (lo + Math.imul(al6, bl3)) | 0; + mid = (mid + Math.imul(al6, bh3)) | 0; + mid = (mid + Math.imul(ah6, bl3)) | 0; + hi = (hi + Math.imul(ah6, bh3)) | 0; + lo = (lo + Math.imul(al5, bl4)) | 0; + mid = (mid + Math.imul(al5, bh4)) | 0; + mid = (mid + Math.imul(ah5, bl4)) | 0; + hi = (hi + Math.imul(ah5, bh4)) | 0; + lo = (lo + Math.imul(al4, bl5)) | 0; + mid = (mid + Math.imul(al4, bh5)) | 0; + mid = (mid + Math.imul(ah4, bl5)) | 0; + hi = (hi + Math.imul(ah4, bh5)) | 0; + lo = (lo + Math.imul(al3, bl6)) | 0; + mid = (mid + Math.imul(al3, bh6)) | 0; + mid = (mid + Math.imul(ah3, bl6)) | 0; + hi = (hi + Math.imul(ah3, bh6)) | 0; + lo = (lo + Math.imul(al2, bl7)) | 0; + mid = (mid + Math.imul(al2, bh7)) | 0; + mid = (mid + Math.imul(ah2, bl7)) | 0; + hi = (hi + Math.imul(ah2, bh7)) | 0; + lo = (lo + Math.imul(al1, bl8)) | 0; + mid = (mid + Math.imul(al1, bh8)) | 0; + mid = (mid + Math.imul(ah1, bl8)) | 0; + hi = (hi + Math.imul(ah1, bh8)) | 0; + lo = (lo + Math.imul(al0, bl9)) | 0; + mid = (mid + Math.imul(al0, bh9)) | 0; + mid = (mid + Math.imul(ah0, bl9)) | 0; + hi = (hi + Math.imul(ah0, bh9)) | 0; + var w9 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w9 >>> 26)) | 0; + w9 &= 0x3ffffff; + /* k = 10 */ + lo = Math.imul(al9, bl1); + mid = Math.imul(al9, bh1); + mid = (mid + Math.imul(ah9, bl1)) | 0; + hi = Math.imul(ah9, bh1); + lo = (lo + Math.imul(al8, bl2)) | 0; + mid = (mid + Math.imul(al8, bh2)) | 0; + mid = (mid + Math.imul(ah8, bl2)) | 0; + hi = (hi + Math.imul(ah8, bh2)) | 0; + lo = (lo + Math.imul(al7, bl3)) | 0; + mid = (mid + Math.imul(al7, bh3)) | 0; + mid = (mid + Math.imul(ah7, bl3)) | 0; + hi = (hi + Math.imul(ah7, bh3)) | 0; + lo = (lo + Math.imul(al6, bl4)) | 0; + mid = (mid + Math.imul(al6, bh4)) | 0; + mid = (mid + Math.imul(ah6, bl4)) | 0; + hi = (hi + Math.imul(ah6, bh4)) | 0; + lo = (lo + Math.imul(al5, bl5)) | 0; + mid = (mid + Math.imul(al5, bh5)) | 0; + mid = (mid + Math.imul(ah5, bl5)) | 0; + hi = (hi + Math.imul(ah5, bh5)) | 0; + lo = (lo + Math.imul(al4, bl6)) | 0; + mid = (mid + Math.imul(al4, bh6)) | 0; + mid = (mid + Math.imul(ah4, bl6)) | 0; + hi = (hi + Math.imul(ah4, bh6)) | 0; + lo = (lo + Math.imul(al3, bl7)) | 0; + mid = (mid + Math.imul(al3, bh7)) | 0; + mid = (mid + Math.imul(ah3, bl7)) | 0; + hi = (hi + Math.imul(ah3, bh7)) | 0; + lo = (lo + Math.imul(al2, bl8)) | 0; + mid = (mid + Math.imul(al2, bh8)) | 0; + mid = (mid + Math.imul(ah2, bl8)) | 0; + hi = (hi + Math.imul(ah2, bh8)) | 0; + lo = (lo + Math.imul(al1, bl9)) | 0; + mid = (mid + Math.imul(al1, bh9)) | 0; + mid = (mid + Math.imul(ah1, bl9)) | 0; + hi = (hi + Math.imul(ah1, bh9)) | 0; + var w10 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w10 >>> 26)) | 0; + w10 &= 0x3ffffff; + /* k = 11 */ + lo = Math.imul(al9, bl2); + mid = Math.imul(al9, bh2); + mid = (mid + Math.imul(ah9, bl2)) | 0; + hi = Math.imul(ah9, bh2); + lo = (lo + Math.imul(al8, bl3)) | 0; + mid = (mid + Math.imul(al8, bh3)) | 0; + mid = (mid + Math.imul(ah8, bl3)) | 0; + hi = (hi + Math.imul(ah8, bh3)) | 0; + lo = (lo + Math.imul(al7, bl4)) | 0; + mid = (mid + Math.imul(al7, bh4)) | 0; + mid = (mid + Math.imul(ah7, bl4)) | 0; + hi = (hi + Math.imul(ah7, bh4)) | 0; + lo = (lo + Math.imul(al6, bl5)) | 0; + mid = (mid + Math.imul(al6, bh5)) | 0; + mid = (mid + Math.imul(ah6, bl5)) | 0; + hi = (hi + Math.imul(ah6, bh5)) | 0; + lo = (lo + Math.imul(al5, bl6)) | 0; + mid = (mid + Math.imul(al5, bh6)) | 0; + mid = (mid + Math.imul(ah5, bl6)) | 0; + hi = (hi + Math.imul(ah5, bh6)) | 0; + lo = (lo + Math.imul(al4, bl7)) | 0; + mid = (mid + Math.imul(al4, bh7)) | 0; + mid = (mid + Math.imul(ah4, bl7)) | 0; + hi = (hi + Math.imul(ah4, bh7)) | 0; + lo = (lo + Math.imul(al3, bl8)) | 0; + mid = (mid + Math.imul(al3, bh8)) | 0; + mid = (mid + Math.imul(ah3, bl8)) | 0; + hi = (hi + Math.imul(ah3, bh8)) | 0; + lo = (lo + Math.imul(al2, bl9)) | 0; + mid = (mid + Math.imul(al2, bh9)) | 0; + mid = (mid + Math.imul(ah2, bl9)) | 0; + hi = (hi + Math.imul(ah2, bh9)) | 0; + var w11 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w11 >>> 26)) | 0; + w11 &= 0x3ffffff; + /* k = 12 */ + lo = Math.imul(al9, bl3); + mid = Math.imul(al9, bh3); + mid = (mid + Math.imul(ah9, bl3)) | 0; + hi = Math.imul(ah9, bh3); + lo = (lo + Math.imul(al8, bl4)) | 0; + mid = (mid + Math.imul(al8, bh4)) | 0; + mid = (mid + Math.imul(ah8, bl4)) | 0; + hi = (hi + Math.imul(ah8, bh4)) | 0; + lo = (lo + Math.imul(al7, bl5)) | 0; + mid = (mid + Math.imul(al7, bh5)) | 0; + mid = (mid + Math.imul(ah7, bl5)) | 0; + hi = (hi + Math.imul(ah7, bh5)) | 0; + lo = (lo + Math.imul(al6, bl6)) | 0; + mid = (mid + Math.imul(al6, bh6)) | 0; + mid = (mid + Math.imul(ah6, bl6)) | 0; + hi = (hi + Math.imul(ah6, bh6)) | 0; + lo = (lo + Math.imul(al5, bl7)) | 0; + mid = (mid + Math.imul(al5, bh7)) | 0; + mid = (mid + Math.imul(ah5, bl7)) | 0; + hi = (hi + Math.imul(ah5, bh7)) | 0; + lo = (lo + Math.imul(al4, bl8)) | 0; + mid = (mid + Math.imul(al4, bh8)) | 0; + mid = (mid + Math.imul(ah4, bl8)) | 0; + hi = (hi + Math.imul(ah4, bh8)) | 0; + lo = (lo + Math.imul(al3, bl9)) | 0; + mid = (mid + Math.imul(al3, bh9)) | 0; + mid = (mid + Math.imul(ah3, bl9)) | 0; + hi = (hi + Math.imul(ah3, bh9)) | 0; + var w12 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w12 >>> 26)) | 0; + w12 &= 0x3ffffff; + /* k = 13 */ + lo = Math.imul(al9, bl4); + mid = Math.imul(al9, bh4); + mid = (mid + Math.imul(ah9, bl4)) | 0; + hi = Math.imul(ah9, bh4); + lo = (lo + Math.imul(al8, bl5)) | 0; + mid = (mid + Math.imul(al8, bh5)) | 0; + mid = (mid + Math.imul(ah8, bl5)) | 0; + hi = (hi + Math.imul(ah8, bh5)) | 0; + lo = (lo + Math.imul(al7, bl6)) | 0; + mid = (mid + Math.imul(al7, bh6)) | 0; + mid = (mid + Math.imul(ah7, bl6)) | 0; + hi = (hi + Math.imul(ah7, bh6)) | 0; + lo = (lo + Math.imul(al6, bl7)) | 0; + mid = (mid + Math.imul(al6, bh7)) | 0; + mid = (mid + Math.imul(ah6, bl7)) | 0; + hi = (hi + Math.imul(ah6, bh7)) | 0; + lo = (lo + Math.imul(al5, bl8)) | 0; + mid = (mid + Math.imul(al5, bh8)) | 0; + mid = (mid + Math.imul(ah5, bl8)) | 0; + hi = (hi + Math.imul(ah5, bh8)) | 0; + lo = (lo + Math.imul(al4, bl9)) | 0; + mid = (mid + Math.imul(al4, bh9)) | 0; + mid = (mid + Math.imul(ah4, bl9)) | 0; + hi = (hi + Math.imul(ah4, bh9)) | 0; + var w13 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w13 >>> 26)) | 0; + w13 &= 0x3ffffff; + /* k = 14 */ + lo = Math.imul(al9, bl5); + mid = Math.imul(al9, bh5); + mid = (mid + Math.imul(ah9, bl5)) | 0; + hi = Math.imul(ah9, bh5); + lo = (lo + Math.imul(al8, bl6)) | 0; + mid = (mid + Math.imul(al8, bh6)) | 0; + mid = (mid + Math.imul(ah8, bl6)) | 0; + hi = (hi + Math.imul(ah8, bh6)) | 0; + lo = (lo + Math.imul(al7, bl7)) | 0; + mid = (mid + Math.imul(al7, bh7)) | 0; + mid = (mid + Math.imul(ah7, bl7)) | 0; + hi = (hi + Math.imul(ah7, bh7)) | 0; + lo = (lo + Math.imul(al6, bl8)) | 0; + mid = (mid + Math.imul(al6, bh8)) | 0; + mid = (mid + Math.imul(ah6, bl8)) | 0; + hi = (hi + Math.imul(ah6, bh8)) | 0; + lo = (lo + Math.imul(al5, bl9)) | 0; + mid = (mid + Math.imul(al5, bh9)) | 0; + mid = (mid + Math.imul(ah5, bl9)) | 0; + hi = (hi + Math.imul(ah5, bh9)) | 0; + var w14 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w14 >>> 26)) | 0; + w14 &= 0x3ffffff; + /* k = 15 */ + lo = Math.imul(al9, bl6); + mid = Math.imul(al9, bh6); + mid = (mid + Math.imul(ah9, bl6)) | 0; + hi = Math.imul(ah9, bh6); + lo = (lo + Math.imul(al8, bl7)) | 0; + mid = (mid + Math.imul(al8, bh7)) | 0; + mid = (mid + Math.imul(ah8, bl7)) | 0; + hi = (hi + Math.imul(ah8, bh7)) | 0; + lo = (lo + Math.imul(al7, bl8)) | 0; + mid = (mid + Math.imul(al7, bh8)) | 0; + mid = (mid + Math.imul(ah7, bl8)) | 0; + hi = (hi + Math.imul(ah7, bh8)) | 0; + lo = (lo + Math.imul(al6, bl9)) | 0; + mid = (mid + Math.imul(al6, bh9)) | 0; + mid = (mid + Math.imul(ah6, bl9)) | 0; + hi = (hi + Math.imul(ah6, bh9)) | 0; + var w15 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w15 >>> 26)) | 0; + w15 &= 0x3ffffff; + /* k = 16 */ + lo = Math.imul(al9, bl7); + mid = Math.imul(al9, bh7); + mid = (mid + Math.imul(ah9, bl7)) | 0; + hi = Math.imul(ah9, bh7); + lo = (lo + Math.imul(al8, bl8)) | 0; + mid = (mid + Math.imul(al8, bh8)) | 0; + mid = (mid + Math.imul(ah8, bl8)) | 0; + hi = (hi + Math.imul(ah8, bh8)) | 0; + lo = (lo + Math.imul(al7, bl9)) | 0; + mid = (mid + Math.imul(al7, bh9)) | 0; + mid = (mid + Math.imul(ah7, bl9)) | 0; + hi = (hi + Math.imul(ah7, bh9)) | 0; + var w16 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w16 >>> 26)) | 0; + w16 &= 0x3ffffff; + /* k = 17 */ + lo = Math.imul(al9, bl8); + mid = Math.imul(al9, bh8); + mid = (mid + Math.imul(ah9, bl8)) | 0; + hi = Math.imul(ah9, bh8); + lo = (lo + Math.imul(al8, bl9)) | 0; + mid = (mid + Math.imul(al8, bh9)) | 0; + mid = (mid + Math.imul(ah8, bl9)) | 0; + hi = (hi + Math.imul(ah8, bh9)) | 0; + var w17 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w17 >>> 26)) | 0; + w17 &= 0x3ffffff; + /* k = 18 */ + lo = Math.imul(al9, bl9); + mid = Math.imul(al9, bh9); + mid = (mid + Math.imul(ah9, bl9)) | 0; + hi = Math.imul(ah9, bh9); + var w18 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w18 >>> 26)) | 0; + w18 &= 0x3ffffff; + o[0] = w0; + o[1] = w1; + o[2] = w2; + o[3] = w3; + o[4] = w4; + o[5] = w5; + o[6] = w6; + o[7] = w7; + o[8] = w8; + o[9] = w9; + o[10] = w10; + o[11] = w11; + o[12] = w12; + o[13] = w13; + o[14] = w14; + o[15] = w15; + o[16] = w16; + o[17] = w17; + o[18] = w18; + if (c !== 0) { + o[19] = c; + out.length++; + } + return out; + }; -const HEAP_SIZE = 2 * L_CODES + 1; -/* maximum heap size */ + // Polyfill comb + if (!Math.imul) { + comb10MulTo = smallMulTo; + } -const MAX_BITS = 15; -/* All codes must not exceed MAX_BITS bits */ - -const Buf_size = 16; -/* size of bit buffer in bi_buf */ + function bigMulTo (self, num, out) { + out.negative = num.negative ^ self.negative; + out.length = self.length + num.length; + var carry = 0; + var hncarry = 0; + for (var k = 0; k < out.length - 1; k++) { + // Sum all words with the same `i + j = k` and accumulate `ncarry`, + // note that ncarry could be >= 0x3ffffff + var ncarry = hncarry; + hncarry = 0; + var rword = carry & 0x3ffffff; + var maxJ = Math.min(k, num.length - 1); + for (var j = Math.max(0, k - self.length + 1); j <= maxJ; j++) { + var i = k - j; + var a = self.words[i] | 0; + var b = num.words[j] | 0; + var r = a * b; -/* =========================================================================== - * Constants - */ + var lo = r & 0x3ffffff; + ncarry = (ncarry + ((r / 0x4000000) | 0)) | 0; + lo = (lo + rword) | 0; + rword = lo & 0x3ffffff; + ncarry = (ncarry + (lo >>> 26)) | 0; -const MAX_BL_BITS = 7; -/* Bit length codes must not exceed MAX_BL_BITS bits */ + hncarry += ncarry >>> 26; + ncarry &= 0x3ffffff; + } + out.words[k] = rword; + carry = ncarry; + ncarry = hncarry; + } + if (carry !== 0) { + out.words[k] = carry; + } else { + out.length--; + } -const END_BLOCK = 256; -/* end of block literal code */ + return out.strip(); + } -const REP_3_6 = 16; -/* repeat previous bit length 3-6 times (2 bits of repeat count) */ + function jumboMulTo (self, num, out) { + var fftm = new FFTM(); + return fftm.mulp(self, num, out); + } -const REPZ_3_10 = 17; -/* repeat a zero length 3-10 times (3 bits of repeat count) */ + BN.prototype.mulTo = function mulTo (num, out) { + var res; + var len = this.length + num.length; + if (this.length === 10 && num.length === 10) { + res = comb10MulTo(this, num, out); + } else if (len < 63) { + res = smallMulTo(this, num, out); + } else if (len < 1024) { + res = bigMulTo(this, num, out); + } else { + res = jumboMulTo(this, num, out); + } -const REPZ_11_138 = 18; -/* repeat a zero length 11-138 times (7 bits of repeat count) */ + return res; + }; -/* eslint-disable comma-spacing,array-bracket-spacing */ -const extra_lbits = /* extra bits for each length code */ - new Uint8Array([0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0]); + // Cooley-Tukey algorithm for FFT + // slightly revisited to rely on looping instead of recursion -const extra_dbits = /* extra bits for each distance code */ - new Uint8Array([0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13]); + function FFTM (x, y) { + this.x = x; + this.y = y; + } -const extra_blbits = /* extra bits for each bit length code */ - new Uint8Array([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7]); + FFTM.prototype.makeRBT = function makeRBT (N) { + var t = new Array(N); + var l = BN.prototype._countBits(N) - 1; + for (var i = 0; i < N; i++) { + t[i] = this.revBin(i, l, N); + } -const bl_order = - new Uint8Array([16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15]); -/* eslint-enable comma-spacing,array-bracket-spacing */ + return t; + }; -/* The lengths of the bit length codes are sent in order of decreasing - * probability, to avoid transmitting the lengths for unused bit length codes. - */ + // Returns binary-reversed representation of `x` + FFTM.prototype.revBin = function revBin (x, l, N) { + if (x === 0 || x === N - 1) return x; -/* =========================================================================== - * Local data. These are initialized only once. - */ + var rb = 0; + for (var i = 0; i < l; i++) { + rb |= (x & 1) << (l - i - 1); + x >>= 1; + } -// We pre-fill arrays with 0 to avoid uninitialized gaps + return rb; + }; -const DIST_CODE_LEN = 512; /* see definition of array dist_code below */ + // Performs "tweedling" phase, therefore 'emulating' + // behaviour of the recursive algorithm + FFTM.prototype.permute = function permute (rbt, rws, iws, rtws, itws, N) { + for (var i = 0; i < N; i++) { + rtws[i] = rws[rbt[i]]; + itws[i] = iws[rbt[i]]; + } + }; -// !!!! Use flat array instead of structure, Freq = i*2, Len = i*2+1 -const static_ltree = new Array((L_CODES + 2) * 2); -zero(static_ltree); -/* The static literal tree. Since the bit lengths are imposed, there is no - * need for the L_CODES extra codes used during heap construction. However - * The codes 286 and 287 are needed to build a canonical tree (see _tr_init - * below). - */ + FFTM.prototype.transform = function transform (rws, iws, rtws, itws, N, rbt) { + this.permute(rbt, rws, iws, rtws, itws, N); -const static_dtree = new Array(D_CODES * 2); -zero(static_dtree); -/* The static distance tree. (Actually a trivial tree since all codes use - * 5 bits.) - */ + for (var s = 1; s < N; s <<= 1) { + var l = s << 1; -const _dist_code = new Array(DIST_CODE_LEN); -zero(_dist_code); -/* Distance codes. The first 256 values correspond to the distances - * 3 .. 258, the last 256 values correspond to the top 8 bits of - * the 15 bit distances. - */ + var rtwdf = Math.cos(2 * Math.PI / l); + var itwdf = Math.sin(2 * Math.PI / l); -const _length_code = new Array(MAX_MATCH - MIN_MATCH + 1); -zero(_length_code); -/* length code for each normalized match length (0 == MIN_MATCH) */ + for (var p = 0; p < N; p += l) { + var rtwdf_ = rtwdf; + var itwdf_ = itwdf; -const base_length = new Array(LENGTH_CODES); -zero(base_length); -/* First normalized length for each code (0 = MIN_MATCH) */ + for (var j = 0; j < s; j++) { + var re = rtws[p + j]; + var ie = itws[p + j]; -const base_dist = new Array(D_CODES); -zero(base_dist); -/* First normalized distance for each code (0 = distance of 1) */ + var ro = rtws[p + j + s]; + var io = itws[p + j + s]; + var rx = rtwdf_ * ro - itwdf_ * io; -function StaticTreeDesc(static_tree, extra_bits, extra_base, elems, max_length) { + io = rtwdf_ * io + itwdf_ * ro; + ro = rx; - this.static_tree = static_tree; /* static tree or NULL */ - this.extra_bits = extra_bits; /* extra bits for each code or NULL */ - this.extra_base = extra_base; /* base index for extra_bits */ - this.elems = elems; /* max number of elements in the tree */ - this.max_length = max_length; /* max bit length for the codes */ + rtws[p + j] = re + ro; + itws[p + j] = ie + io; - // show if `static_tree` has data or dummy - needed for monomorphic objects - this.has_stree = static_tree && static_tree.length; -} + rtws[p + j + s] = re - ro; + itws[p + j + s] = ie - io; + /* jshint maxdepth : false */ + if (j !== l) { + rx = rtwdf * rtwdf_ - itwdf * itwdf_; -let static_l_desc; -let static_d_desc; -let static_bl_desc; + itwdf_ = rtwdf * itwdf_ + itwdf * rtwdf_; + rtwdf_ = rx; + } + } + } + } + }; + FFTM.prototype.guessLen13b = function guessLen13b (n, m) { + var N = Math.max(m, n) | 1; + var odd = N & 1; + var i = 0; + for (N = N / 2 | 0; N; N = N >>> 1) { + i++; + } -function TreeDesc(dyn_tree, stat_desc) { - this.dyn_tree = dyn_tree; /* the dynamic tree */ - this.max_code = 0; /* largest code with non zero frequency */ - this.stat_desc = stat_desc; /* the corresponding static tree */ -} + return 1 << i + 1 + odd; + }; + FFTM.prototype.conjugate = function conjugate (rws, iws, N) { + if (N <= 1) return; + for (var i = 0; i < N / 2; i++) { + var t = rws[i]; -const d_code = (dist) => { + rws[i] = rws[N - i - 1]; + rws[N - i - 1] = t; - return dist < 256 ? _dist_code[dist] : _dist_code[256 + (dist >>> 7)]; -}; + t = iws[i]; + iws[i] = -iws[N - i - 1]; + iws[N - i - 1] = -t; + } + }; -/* =========================================================================== - * Output a short LSB first on the stream. - * IN assertion: there is enough room in pendingBuf. - */ -const put_short = (s, w) => { -// put_byte(s, (uch)((w) & 0xff)); -// put_byte(s, (uch)((ush)(w) >> 8)); - s.pending_buf[s.pending++] = (w) & 0xff; - s.pending_buf[s.pending++] = (w >>> 8) & 0xff; -}; + FFTM.prototype.normalize13b = function normalize13b (ws, N) { + var carry = 0; + for (var i = 0; i < N / 2; i++) { + var w = Math.round(ws[2 * i + 1] / N) * 0x2000 + + Math.round(ws[2 * i] / N) + + carry; + ws[i] = w & 0x3ffffff; -/* =========================================================================== - * Send a value on a given number of bits. - * IN assertion: length <= 16 and value fits in length bits. - */ -const send_bits = (s, value, length) => { + if (w < 0x4000000) { + carry = 0; + } else { + carry = w / 0x4000000 | 0; + } + } - if (s.bi_valid > (Buf_size - length)) { - s.bi_buf |= (value << s.bi_valid) & 0xffff; - put_short(s, s.bi_buf); - s.bi_buf = value >> (Buf_size - s.bi_valid); - s.bi_valid += length - Buf_size; - } else { - s.bi_buf |= (value << s.bi_valid) & 0xffff; - s.bi_valid += length; - } -}; + return ws; + }; + FFTM.prototype.convert13b = function convert13b (ws, len, rws, N) { + var carry = 0; + for (var i = 0; i < len; i++) { + carry = carry + (ws[i] | 0); -const send_code = (s, c, tree) => { + rws[2 * i] = carry & 0x1fff; carry = carry >>> 13; + rws[2 * i + 1] = carry & 0x1fff; carry = carry >>> 13; + } - send_bits(s, tree[c * 2]/*.Code*/, tree[c * 2 + 1]/*.Len*/); -}; + // Pad with zeroes + for (i = 2 * len; i < N; ++i) { + rws[i] = 0; + } + assert(carry === 0); + assert((carry & ~0x1fff) === 0); + }; -/* =========================================================================== - * Reverse the first len bits of a code, using straightforward code (a faster - * method would use a table) - * IN assertion: 1 <= len <= 15 - */ -const bi_reverse = (code, len) => { + FFTM.prototype.stub = function stub (N) { + var ph = new Array(N); + for (var i = 0; i < N; i++) { + ph[i] = 0; + } - let res = 0; - do { - res |= code & 1; - code >>>= 1; - res <<= 1; - } while (--len > 0); - return res >>> 1; -}; + return ph; + }; + FFTM.prototype.mulp = function mulp (x, y, out) { + var N = 2 * this.guessLen13b(x.length, y.length); -/* =========================================================================== - * Flush the bit buffer, keeping at most 7 bits in it. - */ -const bi_flush = (s) => { + var rbt = this.makeRBT(N); - if (s.bi_valid === 16) { - put_short(s, s.bi_buf); - s.bi_buf = 0; - s.bi_valid = 0; + var _ = this.stub(N); - } else if (s.bi_valid >= 8) { - s.pending_buf[s.pending++] = s.bi_buf & 0xff; - s.bi_buf >>= 8; - s.bi_valid -= 8; - } -}; + var rws = new Array(N); + var rwst = new Array(N); + var iwst = new Array(N); + var nrws = new Array(N); + var nrwst = new Array(N); + var niwst = new Array(N); -/* =========================================================================== - * Compute the optimal bit lengths for a tree and update the total bit length - * for the current block. - * IN assertion: the fields freq and dad are set, heap[heap_max] and - * above are the tree nodes sorted by increasing frequency. - * OUT assertions: the field len is set to the optimal bit length, the - * array bl_count contains the frequencies for each bit length. - * The length opt_len is updated; static_len is also updated if stree is - * not null. - */ -const gen_bitlen = (s, desc) => -// deflate_state *s; -// tree_desc *desc; /* the tree descriptor */ -{ - const tree = desc.dyn_tree; - const max_code = desc.max_code; - const stree = desc.stat_desc.static_tree; - const has_stree = desc.stat_desc.has_stree; - const extra = desc.stat_desc.extra_bits; - const base = desc.stat_desc.extra_base; - const max_length = desc.stat_desc.max_length; - let h; /* heap index */ - let n, m; /* iterate over the tree elements */ - let bits; /* bit length */ - let xbits; /* extra bits */ - let f; /* frequency */ - let overflow = 0; /* number of elements with bit length too large */ + var rmws = out.words; + rmws.length = N; - for (bits = 0; bits <= MAX_BITS; bits++) { - s.bl_count[bits] = 0; - } + this.convert13b(x.words, x.length, rws, N); + this.convert13b(y.words, y.length, nrws, N); - /* In a first pass, compute the optimal bit lengths (which may - * overflow in the case of the bit length tree). - */ - tree[s.heap[s.heap_max] * 2 + 1]/*.Len*/ = 0; /* root of the heap */ + this.transform(rws, _, rwst, iwst, N, rbt); + this.transform(nrws, _, nrwst, niwst, N, rbt); - for (h = s.heap_max + 1; h < HEAP_SIZE; h++) { - n = s.heap[h]; - bits = tree[tree[n * 2 + 1]/*.Dad*/ * 2 + 1]/*.Len*/ + 1; - if (bits > max_length) { - bits = max_length; - overflow++; + for (var i = 0; i < N; i++) { + var rx = rwst[i] * nrwst[i] - iwst[i] * niwst[i]; + iwst[i] = rwst[i] * niwst[i] + iwst[i] * nrwst[i]; + rwst[i] = rx; } - tree[n * 2 + 1]/*.Len*/ = bits; - /* We overwrite tree[n].Dad which is no longer needed */ - if (n > max_code) { continue; } /* not a leaf node */ + this.conjugate(rwst, iwst, N); + this.transform(rwst, iwst, rmws, _, N, rbt); + this.conjugate(rmws, _, N); + this.normalize13b(rmws, N); - s.bl_count[bits]++; - xbits = 0; - if (n >= base) { - xbits = extra[n - base]; - } - f = tree[n * 2]/*.Freq*/; - s.opt_len += f * (bits + xbits); - if (has_stree) { - s.static_len += f * (stree[n * 2 + 1]/*.Len*/ + xbits); - } - } - if (overflow === 0) { return; } + out.negative = x.negative ^ y.negative; + out.length = x.length + y.length; + return out.strip(); + }; - // Trace((stderr,"\nbit length overflow\n")); - /* This happens for example on obj2 and pic of the Calgary corpus */ + // Multiply `this` by `num` + BN.prototype.mul = function mul (num) { + var out = new BN(null); + out.words = new Array(this.length + num.length); + return this.mulTo(num, out); + }; - /* Find the first bit length which could increase: */ - do { - bits = max_length - 1; - while (s.bl_count[bits] === 0) { bits--; } - s.bl_count[bits]--; /* move one leaf down the tree */ - s.bl_count[bits + 1] += 2; /* move one overflow item as its brother */ - s.bl_count[max_length]--; - /* The brother of the overflow item also moves one step up, - * but this does not affect bl_count[max_length] - */ - overflow -= 2; - } while (overflow > 0); + // Multiply employing FFT + BN.prototype.mulf = function mulf (num) { + var out = new BN(null); + out.words = new Array(this.length + num.length); + return jumboMulTo(this, num, out); + }; - /* Now recompute all bit lengths, scanning in increasing frequency. - * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all - * lengths instead of fixing only the wrong ones. This idea is taken - * from 'ar' written by Haruhiko Okumura.) - */ - for (bits = max_length; bits !== 0; bits--) { - n = s.bl_count[bits]; - while (n !== 0) { - m = s.heap[--h]; - if (m > max_code) { continue; } - if (tree[m * 2 + 1]/*.Len*/ !== bits) { - // Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); - s.opt_len += (bits - tree[m * 2 + 1]/*.Len*/) * tree[m * 2]/*.Freq*/; - tree[m * 2 + 1]/*.Len*/ = bits; - } - n--; - } - } -}; + // In-place Multiplication + BN.prototype.imul = function imul (num) { + return this.clone().mulTo(num, this); + }; + BN.prototype.imuln = function imuln (num) { + assert(typeof num === 'number'); + assert(num < 0x4000000); -/* =========================================================================== - * Generate the codes for a given tree and bit counts (which need not be - * optimal). - * IN assertion: the array bl_count contains the bit length statistics for - * the given tree and the field len is set for all tree elements. - * OUT assertion: the field code is set for all tree elements of non - * zero code length. - */ -const gen_codes = (tree, max_code, bl_count) => -// ct_data *tree; /* the tree to decorate */ -// int max_code; /* largest code with non zero frequency */ -// ushf *bl_count; /* number of codes at each bit length */ -{ - const next_code = new Array(MAX_BITS + 1); /* next code value for each bit length */ - let code = 0; /* running code value */ - let bits; /* bit index */ - let n; /* code index */ + // Carry + var carry = 0; + for (var i = 0; i < this.length; i++) { + var w = (this.words[i] | 0) * num; + var lo = (w & 0x3ffffff) + (carry & 0x3ffffff); + carry >>= 26; + carry += (w / 0x4000000) | 0; + // NOTE: lo is 27bit maximum + carry += lo >>> 26; + this.words[i] = lo & 0x3ffffff; + } - /* The distribution counts are first used to generate the code values - * without bit reversal. - */ - for (bits = 1; bits <= MAX_BITS; bits++) { - next_code[bits] = code = (code + bl_count[bits - 1]) << 1; - } - /* Check that the bit counts in bl_count are consistent. The last code - * must be all ones. - */ - //Assert (code + bl_count[MAX_BITS]-1 == (1< { + // `this` * `this` in-place + BN.prototype.isqr = function isqr () { + return this.imul(this.clone()); + }; - let n; /* iterates over tree elements */ - let bits; /* bit counter */ - let length; /* length value */ - let code; /* code value */ - let dist; /* distance index */ - const bl_count = new Array(MAX_BITS + 1); - /* number of codes at each bit length for an optimal tree */ - - // do check in _tr_init() - //if (static_init_done) return; - - /* For some embedded targets, global variables are not initialized: */ -/*#ifdef NO_INIT_GLOBAL_POINTERS - static_l_desc.static_tree = static_ltree; - static_l_desc.extra_bits = extra_lbits; - static_d_desc.static_tree = static_dtree; - static_d_desc.extra_bits = extra_dbits; - static_bl_desc.extra_bits = extra_blbits; -#endif*/ - - /* Initialize the mapping length (0..255) -> length code (0..28) */ - length = 0; - for (code = 0; code < LENGTH_CODES - 1; code++) { - base_length[code] = length; - for (n = 0; n < (1 << extra_lbits[code]); n++) { - _length_code[length++] = code; - } - } - //Assert (length == 256, "tr_static_init: length != 256"); - /* Note that the length 255 (match length 258) can be represented - * in two different ways: code 284 + 5 bits or code 285, so we - * overwrite length_code[255] to use the best encoding: - */ - _length_code[length - 1] = code; + // Math.pow(`this`, `num`) + BN.prototype.pow = function pow (num) { + var w = toBitArray(num); + if (w.length === 0) return new BN(1); - /* Initialize the mapping dist (0..32K) -> dist code (0..29) */ - dist = 0; - for (code = 0; code < 16; code++) { - base_dist[code] = dist; - for (n = 0; n < (1 << extra_dbits[code]); n++) { - _dist_code[dist++] = code; - } - } - //Assert (dist == 256, "tr_static_init: dist != 256"); - dist >>= 7; /* from now on, all distances are divided by 128 */ - for (; code < D_CODES; code++) { - base_dist[code] = dist << 7; - for (n = 0; n < (1 << (extra_dbits[code] - 7)); n++) { - _dist_code[256 + dist++] = code; + // Skip leading zeroes + var res = this; + for (var i = 0; i < w.length; i++, res = res.sqr()) { + if (w[i] !== 0) break; } - } - //Assert (dist == 256, "tr_static_init: 256+dist != 512"); - /* Construct the codes of the static literal tree */ - for (bits = 0; bits <= MAX_BITS; bits++) { - bl_count[bits] = 0; - } + if (++i < w.length) { + for (var q = res.sqr(); i < w.length; i++, q = q.sqr()) { + if (w[i] === 0) continue; - n = 0; - while (n <= 143) { - static_ltree[n * 2 + 1]/*.Len*/ = 8; - n++; - bl_count[8]++; - } - while (n <= 255) { - static_ltree[n * 2 + 1]/*.Len*/ = 9; - n++; - bl_count[9]++; - } - while (n <= 279) { - static_ltree[n * 2 + 1]/*.Len*/ = 7; - n++; - bl_count[7]++; - } - while (n <= 287) { - static_ltree[n * 2 + 1]/*.Len*/ = 8; - n++; - bl_count[8]++; - } - /* Codes 286 and 287 do not exist, but we must include them in the - * tree construction to get a canonical Huffman tree (longest code - * all ones) - */ - gen_codes(static_ltree, L_CODES + 1, bl_count); + res = res.mul(q); + } + } - /* The static distance tree is trivial: */ - for (n = 0; n < D_CODES; n++) { - static_dtree[n * 2 + 1]/*.Len*/ = 5; - static_dtree[n * 2]/*.Code*/ = bi_reverse(n, 5); - } + return res; + }; - // Now data ready and we can init static trees - static_l_desc = new StaticTreeDesc(static_ltree, extra_lbits, LITERALS + 1, L_CODES, MAX_BITS); - static_d_desc = new StaticTreeDesc(static_dtree, extra_dbits, 0, D_CODES, MAX_BITS); - static_bl_desc = new StaticTreeDesc(new Array(0), extra_blbits, 0, BL_CODES, MAX_BL_BITS); + // Shift-left in-place + BN.prototype.iushln = function iushln (bits) { + assert(typeof bits === 'number' && bits >= 0); + var r = bits % 26; + var s = (bits - r) / 26; + var carryMask = (0x3ffffff >>> (26 - r)) << (26 - r); + var i; - //static_init_done = true; -}; + if (r !== 0) { + var carry = 0; + for (i = 0; i < this.length; i++) { + var newCarry = this.words[i] & carryMask; + var c = ((this.words[i] | 0) - newCarry) << r; + this.words[i] = c | carry; + carry = newCarry >>> (26 - r); + } -/* =========================================================================== - * Initialize a new block. - */ -const init_block = (s) => { + if (carry) { + this.words[i] = carry; + this.length++; + } + } - let n; /* iterates over tree elements */ + if (s !== 0) { + for (i = this.length - 1; i >= 0; i--) { + this.words[i + s] = this.words[i]; + } - /* Initialize the trees. */ - for (n = 0; n < L_CODES; n++) { s.dyn_ltree[n * 2]/*.Freq*/ = 0; } - for (n = 0; n < D_CODES; n++) { s.dyn_dtree[n * 2]/*.Freq*/ = 0; } - for (n = 0; n < BL_CODES; n++) { s.bl_tree[n * 2]/*.Freq*/ = 0; } + for (i = 0; i < s; i++) { + this.words[i] = 0; + } - s.dyn_ltree[END_BLOCK * 2]/*.Freq*/ = 1; - s.opt_len = s.static_len = 0; - s.last_lit = s.matches = 0; -}; + this.length += s; + } + return this.strip(); + }; -/* =========================================================================== - * Flush the bit buffer and align the output on a byte boundary - */ -const bi_windup = (s) => -{ - if (s.bi_valid > 8) { - put_short(s, s.bi_buf); - } else if (s.bi_valid > 0) { - //put_byte(s, (Byte)s->bi_buf); - s.pending_buf[s.pending++] = s.bi_buf; - } - s.bi_buf = 0; - s.bi_valid = 0; -}; + BN.prototype.ishln = function ishln (bits) { + // TODO(indutny): implement me + assert(this.negative === 0); + return this.iushln(bits); + }; -/* =========================================================================== - * Copy a stored block, storing first the length and its - * one's complement if requested. - */ -const copy_block = (s, buf, len, header) => -//DeflateState *s; -//charf *buf; /* the input data */ -//unsigned len; /* its length */ -//int header; /* true if block header must be written */ -{ - bi_windup(s); /* align on byte boundary */ + // Shift-right in-place + // NOTE: `hint` is a lowest bit before trailing zeroes + // NOTE: if `extended` is present - it will be filled with destroyed bits + BN.prototype.iushrn = function iushrn (bits, hint, extended) { + assert(typeof bits === 'number' && bits >= 0); + var h; + if (hint) { + h = (hint - (hint % 26)) / 26; + } else { + h = 0; + } - if (header) { - put_short(s, len); - put_short(s, ~len); - } -// while (len--) { -// put_byte(s, *buf++); -// } - s.pending_buf.set(s.window.subarray(buf, buf + len), s.pending); - s.pending += len; -}; + var r = bits % 26; + var s = Math.min((bits - r) / 26, this.length); + var mask = 0x3ffffff ^ ((0x3ffffff >>> r) << r); + var maskedWords = extended; -/* =========================================================================== - * Compares to subtrees, using the tree depth as tie breaker when - * the subtrees have equal frequency. This minimizes the worst case length. - */ -const smaller = (tree, n, m, depth) => { + h -= s; + h = Math.max(0, h); - const _n2 = n * 2; - const _m2 = m * 2; - return (tree[_n2]/*.Freq*/ < tree[_m2]/*.Freq*/ || - (tree[_n2]/*.Freq*/ === tree[_m2]/*.Freq*/ && depth[n] <= depth[m])); -}; + // Extended mode, copy masked part + if (maskedWords) { + for (var i = 0; i < s; i++) { + maskedWords.words[i] = this.words[i]; + } + maskedWords.length = s; + } -/* =========================================================================== - * Restore the heap property by moving down the tree starting at node k, - * exchanging a node with the smallest of its two sons if necessary, stopping - * when the heap property is re-established (each father smaller than its - * two sons). - */ -const pqdownheap = (s, tree, k) => -// deflate_state *s; -// ct_data *tree; /* the tree to restore */ -// int k; /* node to move down */ -{ - const v = s.heap[k]; - let j = k << 1; /* left son of k */ - while (j <= s.heap_len) { - /* Set j to the smallest of the two sons: */ - if (j < s.heap_len && - smaller(tree, s.heap[j + 1], s.heap[j], s.depth)) { - j++; + if (s === 0) { + // No-op, we should not move anything at all + } else if (this.length > s) { + this.length -= s; + for (i = 0; i < this.length; i++) { + this.words[i] = this.words[i + s]; + } + } else { + this.words[0] = 0; + this.length = 1; } - /* Exit if v is smaller than both sons */ - if (smaller(tree, v, s.heap[j], s.depth)) { break; } - /* Exchange v with the smallest son */ - s.heap[k] = s.heap[j]; - k = j; + var carry = 0; + for (i = this.length - 1; i >= 0 && (carry !== 0 || i >= h); i--) { + var word = this.words[i] | 0; + this.words[i] = (carry << (26 - r)) | (word >>> r); + carry = word & mask; + } - /* And continue down the tree, setting j to the left son of k */ - j <<= 1; - } - s.heap[k] = v; -}; + // Push carried bits as a mask + if (maskedWords && carry !== 0) { + maskedWords.words[maskedWords.length++] = carry; + } + if (this.length === 0) { + this.words[0] = 0; + this.length = 1; + } -// inlined manually -// const SMALLEST = 1; + return this.strip(); + }; -/* =========================================================================== - * Send the block data compressed using the given Huffman trees - */ -const compress_block = (s, ltree, dtree) => -// deflate_state *s; -// const ct_data *ltree; /* literal tree */ -// const ct_data *dtree; /* distance tree */ -{ - let dist; /* distance of matched string */ - let lc; /* match length or unmatched char (if dist == 0) */ - let lx = 0; /* running index in l_buf */ - let code; /* the code to send */ - let extra; /* number of extra bits to send */ + BN.prototype.ishrn = function ishrn (bits, hint, extended) { + // TODO(indutny): implement me + assert(this.negative === 0); + return this.iushrn(bits, hint, extended); + }; - if (s.last_lit !== 0) { - do { - dist = (s.pending_buf[s.d_buf + lx * 2] << 8) | (s.pending_buf[s.d_buf + lx * 2 + 1]); - lc = s.pending_buf[s.l_buf + lx]; - lx++; + // Shift-left + BN.prototype.shln = function shln (bits) { + return this.clone().ishln(bits); + }; - if (dist === 0) { - send_code(s, lc, ltree); /* send a literal byte */ - //Tracecv(isgraph(lc), (stderr," '%c' ", lc)); - } else { - /* Here, lc is the match length - MIN_MATCH */ - code = _length_code[lc]; - send_code(s, code + LITERALS + 1, ltree); /* send the length code */ - extra = extra_lbits[code]; - if (extra !== 0) { - lc -= base_length[code]; - send_bits(s, lc, extra); /* send the extra length bits */ - } - dist--; /* dist is now the match distance - 1 */ - code = d_code(dist); - //Assert (code < D_CODES, "bad d_code"); + BN.prototype.ushln = function ushln (bits) { + return this.clone().iushln(bits); + }; - send_code(s, code, dtree); /* send the distance code */ - extra = extra_dbits[code]; - if (extra !== 0) { - dist -= base_dist[code]; - send_bits(s, dist, extra); /* send the extra distance bits */ - } - } /* literal or match pair ? */ + // Shift-right + BN.prototype.shrn = function shrn (bits) { + return this.clone().ishrn(bits); + }; - /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */ - //Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx, - // "pendingBuf overflow"); + BN.prototype.ushrn = function ushrn (bits) { + return this.clone().iushrn(bits); + }; - } while (lx < s.last_lit); - } + // Test if n bit is set + BN.prototype.testn = function testn (bit) { + assert(typeof bit === 'number' && bit >= 0); + var r = bit % 26; + var s = (bit - r) / 26; + var q = 1 << r; - send_code(s, END_BLOCK, ltree); -}; + // Fast case: bit is much higher than all existing words + if (this.length <= s) return false; + // Check bit and return + var w = this.words[s]; -/* =========================================================================== - * Construct one Huffman tree and assigns the code bit strings and lengths. - * Update the total bit length for the current block. - * IN assertion: the field freq is set for all tree elements. - * OUT assertions: the fields len and code are set to the optimal bit length - * and corresponding code. The length opt_len is updated; static_len is - * also updated if stree is not null. The field max_code is set. - */ -const build_tree = (s, desc) => -// deflate_state *s; -// tree_desc *desc; /* the tree descriptor */ -{ - const tree = desc.dyn_tree; - const stree = desc.stat_desc.static_tree; - const has_stree = desc.stat_desc.has_stree; - const elems = desc.stat_desc.elems; - let n, m; /* iterate over heap elements */ - let max_code = -1; /* largest code with non zero frequency */ - let node; /* new node being created */ + return !!(w & q); + }; - /* Construct the initial heap, with least frequent element in - * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. - * heap[0] is not used. - */ - s.heap_len = 0; - s.heap_max = HEAP_SIZE; + // Return only lowers bits of number (in-place) + BN.prototype.imaskn = function imaskn (bits) { + assert(typeof bits === 'number' && bits >= 0); + var r = bits % 26; + var s = (bits - r) / 26; - for (n = 0; n < elems; n++) { - if (tree[n * 2]/*.Freq*/ !== 0) { - s.heap[++s.heap_len] = max_code = n; - s.depth[n] = 0; + assert(this.negative === 0, 'imaskn works only with positive numbers'); - } else { - tree[n * 2 + 1]/*.Len*/ = 0; + if (this.length <= s) { + return this; } - } - /* The pkzip format requires that at least one distance code exists, - * and that at least one bit should be sent even if there is only one - * possible code. So to avoid special checks later on we force at least - * two codes of non zero frequency. - */ - while (s.heap_len < 2) { - node = s.heap[++s.heap_len] = (max_code < 2 ? ++max_code : 0); - tree[node * 2]/*.Freq*/ = 1; - s.depth[node] = 0; - s.opt_len--; + if (r !== 0) { + s++; + } + this.length = Math.min(s, this.length); - if (has_stree) { - s.static_len -= stree[node * 2 + 1]/*.Len*/; + if (r !== 0) { + var mask = 0x3ffffff ^ ((0x3ffffff >>> r) << r); + this.words[this.length - 1] &= mask; } - /* node is 0 or 1 so it does not have extra bits */ - } - desc.max_code = max_code; - /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, - * establish sub-heaps of increasing lengths: - */ - for (n = (s.heap_len >> 1/*int /2*/); n >= 1; n--) { pqdownheap(s, tree, n); } + return this.strip(); + }; - /* Construct the Huffman tree by repeatedly combining the least two - * frequent nodes. - */ - node = elems; /* next internal node of the tree */ - do { - //pqremove(s, tree, n); /* n = node of least frequency */ - /*** pqremove ***/ - n = s.heap[1/*SMALLEST*/]; - s.heap[1/*SMALLEST*/] = s.heap[s.heap_len--]; - pqdownheap(s, tree, 1/*SMALLEST*/); - /***/ + // Return only lowers bits of number + BN.prototype.maskn = function maskn (bits) { + return this.clone().imaskn(bits); + }; - m = s.heap[1/*SMALLEST*/]; /* m = node of next least frequency */ + // Add plain number `num` to `this` + BN.prototype.iaddn = function iaddn (num) { + assert(typeof num === 'number'); + assert(num < 0x4000000); + if (num < 0) return this.isubn(-num); - s.heap[--s.heap_max] = n; /* keep the nodes sorted by frequency */ - s.heap[--s.heap_max] = m; + // Possible sign change + if (this.negative !== 0) { + if (this.length === 1 && (this.words[0] | 0) < num) { + this.words[0] = num - (this.words[0] | 0); + this.negative = 0; + return this; + } - /* Create a new node father of n and m */ - tree[node * 2]/*.Freq*/ = tree[n * 2]/*.Freq*/ + tree[m * 2]/*.Freq*/; - s.depth[node] = (s.depth[n] >= s.depth[m] ? s.depth[n] : s.depth[m]) + 1; - tree[n * 2 + 1]/*.Dad*/ = tree[m * 2 + 1]/*.Dad*/ = node; + this.negative = 0; + this.isubn(num); + this.negative = 1; + return this; + } - /* and insert the new node in the heap */ - s.heap[1/*SMALLEST*/] = node++; - pqdownheap(s, tree, 1/*SMALLEST*/); + // Add without checks + return this._iaddn(num); + }; - } while (s.heap_len >= 2); + BN.prototype._iaddn = function _iaddn (num) { + this.words[0] += num; - s.heap[--s.heap_max] = s.heap[1/*SMALLEST*/]; + // Carry + for (var i = 0; i < this.length && this.words[i] >= 0x4000000; i++) { + this.words[i] -= 0x4000000; + if (i === this.length - 1) { + this.words[i + 1] = 1; + } else { + this.words[i + 1]++; + } + } + this.length = Math.max(this.length, i + 1); - /* At this point, the fields freq and dad are set. We can now - * generate the bit lengths. - */ - gen_bitlen(s, desc); + return this; + }; - /* The field len is now set, we can generate the bit codes */ - gen_codes(tree, max_code, s.bl_count); -}; + // Subtract plain number `num` from `this` + BN.prototype.isubn = function isubn (num) { + assert(typeof num === 'number'); + assert(num < 0x4000000); + if (num < 0) return this.iaddn(-num); + if (this.negative !== 0) { + this.negative = 0; + this.iaddn(num); + this.negative = 1; + return this; + } -/* =========================================================================== - * Scan a literal or distance tree to determine the frequencies of the codes - * in the bit length tree. - */ -const scan_tree = (s, tree, max_code) => -// deflate_state *s; -// ct_data *tree; /* the tree to be scanned */ -// int max_code; /* and its largest code of non zero frequency */ -{ - let n; /* iterates over all tree elements */ - let prevlen = -1; /* last emitted length */ - let curlen; /* length of current code */ + this.words[0] -= num; - let nextlen = tree[0 * 2 + 1]/*.Len*/; /* length of next code */ + if (this.length === 1 && this.words[0] < 0) { + this.words[0] = -this.words[0]; + this.negative = 1; + } else { + // Carry + for (var i = 0; i < this.length && this.words[i] < 0; i++) { + this.words[i] += 0x4000000; + this.words[i + 1] -= 1; + } + } - let count = 0; /* repeat count of the current code */ - let max_count = 7; /* max repeat count */ - let min_count = 4; /* min repeat count */ + return this.strip(); + }; - if (nextlen === 0) { - max_count = 138; - min_count = 3; - } - tree[(max_code + 1) * 2 + 1]/*.Len*/ = 0xffff; /* guard */ + BN.prototype.addn = function addn (num) { + return this.clone().iaddn(num); + }; - for (n = 0; n <= max_code; n++) { - curlen = nextlen; - nextlen = tree[(n + 1) * 2 + 1]/*.Len*/; + BN.prototype.subn = function subn (num) { + return this.clone().isubn(num); + }; - if (++count < max_count && curlen === nextlen) { - continue; + BN.prototype.iabs = function iabs () { + this.negative = 0; - } else if (count < min_count) { - s.bl_tree[curlen * 2]/*.Freq*/ += count; + return this; + }; - } else if (curlen !== 0) { + BN.prototype.abs = function abs () { + return this.clone().iabs(); + }; - if (curlen !== prevlen) { s.bl_tree[curlen * 2]/*.Freq*/++; } - s.bl_tree[REP_3_6 * 2]/*.Freq*/++; + BN.prototype._ishlnsubmul = function _ishlnsubmul (num, mul, shift) { + var len = num.length + shift; + var i; - } else if (count <= 10) { - s.bl_tree[REPZ_3_10 * 2]/*.Freq*/++; + this._expand(len); - } else { - s.bl_tree[REPZ_11_138 * 2]/*.Freq*/++; + var w; + var carry = 0; + for (i = 0; i < num.length; i++) { + w = (this.words[i + shift] | 0) + carry; + var right = (num.words[i] | 0) * mul; + w -= right & 0x3ffffff; + carry = (w >> 26) - ((right / 0x4000000) | 0); + this.words[i + shift] = w & 0x3ffffff; + } + for (; i < this.length - shift; i++) { + w = (this.words[i + shift] | 0) + carry; + carry = w >> 26; + this.words[i + shift] = w & 0x3ffffff; } - count = 0; - prevlen = curlen; - - if (nextlen === 0) { - max_count = 138; - min_count = 3; - - } else if (curlen === nextlen) { - max_count = 6; - min_count = 3; + if (carry === 0) return this.strip(); - } else { - max_count = 7; - min_count = 4; + // Subtraction overflow + assert(carry === -1); + carry = 0; + for (i = 0; i < this.length; i++) { + w = -(this.words[i] | 0) + carry; + carry = w >> 26; + this.words[i] = w & 0x3ffffff; } - } -}; + this.negative = 1; + return this.strip(); + }; -/* =========================================================================== - * Send a literal or distance tree in compressed form, using the codes in - * bl_tree. - */ -const send_tree = (s, tree, max_code) => -// deflate_state *s; -// ct_data *tree; /* the tree to be scanned */ -// int max_code; /* and its largest code of non zero frequency */ -{ - let n; /* iterates over all tree elements */ - let prevlen = -1; /* last emitted length */ - let curlen; /* length of current code */ + BN.prototype._wordDiv = function _wordDiv (num, mode) { + var shift = this.length - num.length; - let nextlen = tree[0 * 2 + 1]/*.Len*/; /* length of next code */ + var a = this.clone(); + var b = num; - let count = 0; /* repeat count of the current code */ - let max_count = 7; /* max repeat count */ - let min_count = 4; /* min repeat count */ + // Normalize + var bhi = b.words[b.length - 1] | 0; + var bhiBits = this._countBits(bhi); + shift = 26 - bhiBits; + if (shift !== 0) { + b = b.ushln(shift); + a.iushln(shift); + bhi = b.words[b.length - 1] | 0; + } - /* tree[max_code+1].Len = -1; */ /* guard already set */ - if (nextlen === 0) { - max_count = 138; - min_count = 3; - } + // Initialize quotient + var m = a.length - b.length; + var q; - for (n = 0; n <= max_code; n++) { - curlen = nextlen; - nextlen = tree[(n + 1) * 2 + 1]/*.Len*/; + if (mode !== 'mod') { + q = new BN(null); + q.length = m + 1; + q.words = new Array(q.length); + for (var i = 0; i < q.length; i++) { + q.words[i] = 0; + } + } - if (++count < max_count && curlen === nextlen) { - continue; + var diff = a.clone()._ishlnsubmul(b, 1, m); + if (diff.negative === 0) { + a = diff; + if (q) { + q.words[m] = 1; + } + } - } else if (count < min_count) { - do { send_code(s, curlen, s.bl_tree); } while (--count !== 0); + for (var j = m - 1; j >= 0; j--) { + var qj = (a.words[b.length + j] | 0) * 0x4000000 + + (a.words[b.length + j - 1] | 0); - } else if (curlen !== 0) { - if (curlen !== prevlen) { - send_code(s, curlen, s.bl_tree); - count--; - } - //Assert(count >= 3 && count <= 6, " 3_6?"); - send_code(s, REP_3_6, s.bl_tree); - send_bits(s, count - 3, 2); + // NOTE: (qj / bhi) is (0x3ffffff * 0x4000000 + 0x3ffffff) / 0x2000000 max + // (0x7ffffff) + qj = Math.min((qj / bhi) | 0, 0x3ffffff); - } else if (count <= 10) { - send_code(s, REPZ_3_10, s.bl_tree); - send_bits(s, count - 3, 3); + a._ishlnsubmul(b, qj, j); + while (a.negative !== 0) { + qj--; + a.negative = 0; + a._ishlnsubmul(b, 1, j); + if (!a.isZero()) { + a.negative ^= 1; + } + } + if (q) { + q.words[j] = qj; + } + } + if (q) { + q.strip(); + } + a.strip(); - } else { - send_code(s, REPZ_11_138, s.bl_tree); - send_bits(s, count - 11, 7); + // Denormalize + if (mode !== 'div' && shift !== 0) { + a.iushrn(shift); } - count = 0; - prevlen = curlen; - if (nextlen === 0) { - max_count = 138; - min_count = 3; + return { + div: q || null, + mod: a + }; + }; - } else if (curlen === nextlen) { - max_count = 6; - min_count = 3; + // NOTE: 1) `mode` can be set to `mod` to request mod only, + // to `div` to request div only, or be absent to + // request both div & mod + // 2) `positive` is true if unsigned mod is requested + BN.prototype.divmod = function divmod (num, mode, positive) { + assert(!num.isZero()); - } else { - max_count = 7; - min_count = 4; + if (this.isZero()) { + return { + div: new BN(0), + mod: new BN(0) + }; } - } -}; - - -/* =========================================================================== - * Construct the Huffman tree for the bit lengths and return the index in - * bl_order of the last bit length code to send. - */ -const build_bl_tree = (s) => { - let max_blindex; /* index of last bit length code of non zero freq */ + var div, mod, res; + if (this.negative !== 0 && num.negative === 0) { + res = this.neg().divmod(num, mode); - /* Determine the bit length frequencies for literal and distance trees */ - scan_tree(s, s.dyn_ltree, s.l_desc.max_code); - scan_tree(s, s.dyn_dtree, s.d_desc.max_code); + if (mode !== 'mod') { + div = res.div.neg(); + } - /* Build the bit length tree: */ - build_tree(s, s.bl_desc); - /* opt_len now includes the length of the tree representations, except - * the lengths of the bit lengths codes and the 5+5+4 bits for the counts. - */ + if (mode !== 'div') { + mod = res.mod.neg(); + if (positive && mod.negative !== 0) { + mod.iadd(num); + } + } - /* Determine the number of bit length codes to send. The pkzip format - * requires that at least 4 bit length codes be sent. (appnote.txt says - * 3 but the actual value used is 4.) - */ - for (max_blindex = BL_CODES - 1; max_blindex >= 3; max_blindex--) { - if (s.bl_tree[bl_order[max_blindex] * 2 + 1]/*.Len*/ !== 0) { - break; + return { + div: div, + mod: mod + }; } - } - /* Update opt_len to include the bit length tree and counts */ - s.opt_len += 3 * (max_blindex + 1) + 5 + 5 + 4; - //Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", - // s->opt_len, s->static_len)); - - return max_blindex; -}; + if (this.negative === 0 && num.negative !== 0) { + res = this.divmod(num.neg(), mode); -/* =========================================================================== - * Send the header for a block using dynamic Huffman trees: the counts, the - * lengths of the bit length codes, the literal tree and the distance tree. - * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. - */ -const send_all_trees = (s, lcodes, dcodes, blcodes) => -// deflate_state *s; -// int lcodes, dcodes, blcodes; /* number of codes for each tree */ -{ - let rank; /* index in bl_order */ + if (mode !== 'mod') { + div = res.div.neg(); + } - //Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); - //Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, - // "too many codes"); - //Tracev((stderr, "\nbl counts: ")); - send_bits(s, lcodes - 257, 5); /* not +255 as stated in appnote.txt */ - send_bits(s, dcodes - 1, 5); - send_bits(s, blcodes - 4, 4); /* not -3 as stated in appnote.txt */ - for (rank = 0; rank < blcodes; rank++) { - //Tracev((stderr, "\nbl code %2d ", bl_order[rank])); - send_bits(s, s.bl_tree[bl_order[rank] * 2 + 1]/*.Len*/, 3); - } - //Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent)); + return { + div: div, + mod: res.mod + }; + } - send_tree(s, s.dyn_ltree, lcodes - 1); /* literal tree */ - //Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent)); + if ((this.negative & num.negative) !== 0) { + res = this.neg().divmod(num.neg(), mode); - send_tree(s, s.dyn_dtree, dcodes - 1); /* distance tree */ - //Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent)); -}; + if (mode !== 'div') { + mod = res.mod.neg(); + if (positive && mod.negative !== 0) { + mod.isub(num); + } + } + return { + div: res.div, + mod: mod + }; + } -/* =========================================================================== - * Check if the data type is TEXT or BINARY, using the following algorithm: - * - TEXT if the two conditions below are satisfied: - * a) There are no non-portable control characters belonging to the - * "black list" (0..6, 14..25, 28..31). - * b) There is at least one printable character belonging to the - * "white list" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255). - * - BINARY otherwise. - * - The following partially-portable control characters form a - * "gray list" that is ignored in this detection algorithm: - * (7 {BEL}, 8 {BS}, 11 {VT}, 12 {FF}, 26 {SUB}, 27 {ESC}). - * IN assertion: the fields Freq of dyn_ltree are set. - */ -const detect_data_type = (s) => { - /* black_mask is the bit mask of black-listed bytes - * set bits 0..6, 14..25, and 28..31 - * 0xf3ffc07f = binary 11110011111111111100000001111111 - */ - let black_mask = 0xf3ffc07f; - let n; + // Both numbers are positive at this point - /* Check for non-textual ("black-listed") bytes. */ - for (n = 0; n <= 31; n++, black_mask >>>= 1) { - if ((black_mask & 1) && (s.dyn_ltree[n * 2]/*.Freq*/ !== 0)) { - return Z_BINARY; + // Strip both numbers to approximate shift value + if (num.length > this.length || this.cmp(num) < 0) { + return { + div: new BN(0), + mod: this + }; } - } - /* Check for textual ("white-listed") bytes. */ - if (s.dyn_ltree[9 * 2]/*.Freq*/ !== 0 || s.dyn_ltree[10 * 2]/*.Freq*/ !== 0 || - s.dyn_ltree[13 * 2]/*.Freq*/ !== 0) { - return Z_TEXT; - } - for (n = 32; n < LITERALS; n++) { - if (s.dyn_ltree[n * 2]/*.Freq*/ !== 0) { - return Z_TEXT; - } - } + // Very short reduction + if (num.length === 1) { + if (mode === 'div') { + return { + div: this.divn(num.words[0]), + mod: null + }; + } - /* There are no "black-listed" or "white-listed" bytes: - * this stream either is empty or has tolerated ("gray-listed") bytes only. - */ - return Z_BINARY; -}; + if (mode === 'mod') { + return { + div: null, + mod: new BN(this.modn(num.words[0])) + }; + } + return { + div: this.divn(num.words[0]), + mod: new BN(this.modn(num.words[0])) + }; + } -let static_init_done = false; + return this._wordDiv(num, mode); + }; -/* =========================================================================== - * Initialize the tree data structures for a new zlib stream. - */ -const _tr_init = (s) => -{ + // Find `this` / `num` + BN.prototype.div = function div (num) { + return this.divmod(num, 'div', false).div; + }; - if (!static_init_done) { - tr_static_init(); - static_init_done = true; - } + // Find `this` % `num` + BN.prototype.mod = function mod (num) { + return this.divmod(num, 'mod', false).mod; + }; - s.l_desc = new TreeDesc(s.dyn_ltree, static_l_desc); - s.d_desc = new TreeDesc(s.dyn_dtree, static_d_desc); - s.bl_desc = new TreeDesc(s.bl_tree, static_bl_desc); + BN.prototype.umod = function umod (num) { + return this.divmod(num, 'mod', true).mod; + }; - s.bi_buf = 0; - s.bi_valid = 0; + // Find Round(`this` / `num`) + BN.prototype.divRound = function divRound (num) { + var dm = this.divmod(num); - /* Initialize the first block of the first file: */ - init_block(s); -}; + // Fast case - exact division + if (dm.mod.isZero()) return dm.div; + var mod = dm.div.negative !== 0 ? dm.mod.isub(num) : dm.mod; -/* =========================================================================== - * Send a stored block - */ -const _tr_stored_block = (s, buf, stored_len, last) => -//DeflateState *s; -//charf *buf; /* input block */ -//ulg stored_len; /* length of input block */ -//int last; /* one if this is the last block for a file */ -{ - send_bits(s, (STORED_BLOCK << 1) + (last ? 1 : 0), 3); /* send block type */ - copy_block(s, buf, stored_len, true); /* with header */ -}; + var half = num.ushrn(1); + var r2 = num.andln(1); + var cmp = mod.cmp(half); + // Round down + if (cmp < 0 || r2 === 1 && cmp === 0) return dm.div; -/* =========================================================================== - * Send one empty static block to give enough lookahead for inflate. - * This takes 10 bits, of which 7 may remain in the bit buffer. - */ -const _tr_align = (s) => { - send_bits(s, STATIC_TREES << 1, 3); - send_code(s, END_BLOCK, static_ltree); - bi_flush(s); -}; + // Round up + return dm.div.negative !== 0 ? dm.div.isubn(1) : dm.div.iaddn(1); + }; + + BN.prototype.modn = function modn (num) { + assert(num <= 0x3ffffff); + var p = (1 << 26) % num; + var acc = 0; + for (var i = this.length - 1; i >= 0; i--) { + acc = (p * acc + (this.words[i] | 0)) % num; + } -/* =========================================================================== - * Determine the best encoding for the current block: dynamic trees, static - * trees or store, and output the encoded block to the zip file. - */ -const _tr_flush_block = (s, buf, stored_len, last) => -//DeflateState *s; -//charf *buf; /* input block, or NULL if too old */ -//ulg stored_len; /* length of input block */ -//int last; /* one if this is the last block for a file */ -{ - let opt_lenb, static_lenb; /* opt_len and static_len in bytes */ - let max_blindex = 0; /* index of last bit length code of non zero freq */ + return acc; + }; - /* Build the Huffman trees unless a stored block is forced */ - if (s.level > 0) { + // In-place division by number + BN.prototype.idivn = function idivn (num) { + assert(num <= 0x3ffffff); - /* Check if the file is binary or text */ - if (s.strm.data_type === Z_UNKNOWN) { - s.strm.data_type = detect_data_type(s); + var carry = 0; + for (var i = this.length - 1; i >= 0; i--) { + var w = (this.words[i] | 0) + carry * 0x4000000; + this.words[i] = (w / num) | 0; + carry = w % num; } - /* Construct the literal and distance trees */ - build_tree(s, s.l_desc); - // Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len, - // s->static_len)); + return this.strip(); + }; - build_tree(s, s.d_desc); - // Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len, - // s->static_len)); - /* At this point, opt_len and static_len are the total bit lengths of - * the compressed block data, excluding the tree representations. - */ + BN.prototype.divn = function divn (num) { + return this.clone().idivn(num); + }; - /* Build the bit length tree for the above two trees, and get the index - * in bl_order of the last bit length code to send. - */ - max_blindex = build_bl_tree(s); + BN.prototype.egcd = function egcd (p) { + assert(p.negative === 0); + assert(!p.isZero()); - /* Determine the best encoding. Compute the block lengths in bytes. */ - opt_lenb = (s.opt_len + 3 + 7) >>> 3; - static_lenb = (s.static_len + 3 + 7) >>> 3; + var x = this; + var y = p.clone(); - // Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ", - // opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, - // s->last_lit)); + if (x.negative !== 0) { + x = x.umod(p); + } else { + x = x.clone(); + } - if (static_lenb <= opt_lenb) { opt_lenb = static_lenb; } + // A * x + B * y = x + var A = new BN(1); + var B = new BN(0); - } else { - // Assert(buf != (char*)0, "lost buf"); - opt_lenb = static_lenb = stored_len + 5; /* force a stored block */ - } + // C * x + D * y = y + var C = new BN(0); + var D = new BN(1); - if ((stored_len + 4 <= opt_lenb) && (buf !== -1)) { - /* 4: two words for the lengths */ + var g = 0; - /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. - * Otherwise we can't have processed more than WSIZE input bytes since - * the last block flush, because compression would have been - * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to - * transform a block into a stored block. - */ - _tr_stored_block(s, buf, stored_len, last); + while (x.isEven() && y.isEven()) { + x.iushrn(1); + y.iushrn(1); + ++g; + } - } else if (s.strategy === Z_FIXED || static_lenb === opt_lenb) { + var yp = y.clone(); + var xp = x.clone(); - send_bits(s, (STATIC_TREES << 1) + (last ? 1 : 0), 3); - compress_block(s, static_ltree, static_dtree); + while (!x.isZero()) { + for (var i = 0, im = 1; (x.words[0] & im) === 0 && i < 26; ++i, im <<= 1); + if (i > 0) { + x.iushrn(i); + while (i-- > 0) { + if (A.isOdd() || B.isOdd()) { + A.iadd(yp); + B.isub(xp); + } - } else { - send_bits(s, (DYN_TREES << 1) + (last ? 1 : 0), 3); - send_all_trees(s, s.l_desc.max_code + 1, s.d_desc.max_code + 1, max_blindex + 1); - compress_block(s, s.dyn_ltree, s.dyn_dtree); - } - // Assert (s->compressed_len == s->bits_sent, "bad compressed size"); - /* The above check is made mod 2^32, for files larger than 512 MB - * and uLong implemented on 32 bits. - */ - init_block(s); + A.iushrn(1); + B.iushrn(1); + } + } - if (last) { - bi_windup(s); - } - // Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3, - // s->compressed_len-7*last)); -}; + for (var j = 0, jm = 1; (y.words[0] & jm) === 0 && j < 26; ++j, jm <<= 1); + if (j > 0) { + y.iushrn(j); + while (j-- > 0) { + if (C.isOdd() || D.isOdd()) { + C.iadd(yp); + D.isub(xp); + } -/* =========================================================================== - * Save the match info and tally the frequency counts. Return true if - * the current block must be flushed. - */ -const _tr_tally = (s, dist, lc) => -// deflate_state *s; -// unsigned dist; /* distance of matched string */ -// unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */ -{ - //let out_length, in_length, dcode; + C.iushrn(1); + D.iushrn(1); + } + } - s.pending_buf[s.d_buf + s.last_lit * 2] = (dist >>> 8) & 0xff; - s.pending_buf[s.d_buf + s.last_lit * 2 + 1] = dist & 0xff; + if (x.cmp(y) >= 0) { + x.isub(y); + A.isub(C); + B.isub(D); + } else { + y.isub(x); + C.isub(A); + D.isub(B); + } + } - s.pending_buf[s.l_buf + s.last_lit] = lc & 0xff; - s.last_lit++; + return { + a: C, + b: D, + gcd: y.iushln(g) + }; + }; - if (dist === 0) { - /* lc is the unmatched char */ - s.dyn_ltree[lc * 2]/*.Freq*/++; - } else { - s.matches++; - /* Here, lc is the match length - MIN_MATCH */ - dist--; /* dist = match distance - 1 */ - //Assert((ush)dist < (ush)MAX_DIST(s) && - // (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && - // (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match"); + // This is reduced incarnation of the binary EEA + // above, designated to invert members of the + // _prime_ fields F(p) at a maximal speed + BN.prototype._invmp = function _invmp (p) { + assert(p.negative === 0); + assert(!p.isZero()); - s.dyn_ltree[(_length_code[lc] + LITERALS + 1) * 2]/*.Freq*/++; - s.dyn_dtree[d_code(dist) * 2]/*.Freq*/++; - } + var a = this; + var b = p.clone(); -// (!) This block is disabled in zlib defaults, -// don't enable it for binary compatibility + if (a.negative !== 0) { + a = a.umod(p); + } else { + a = a.clone(); + } -//#ifdef TRUNCATE_BLOCK -// /* Try to guess if it is profitable to stop the current block here */ -// if ((s.last_lit & 0x1fff) === 0 && s.level > 2) { -// /* Compute an upper bound for the compressed length */ -// out_length = s.last_lit*8; -// in_length = s.strstart - s.block_start; -// -// for (dcode = 0; dcode < D_CODES; dcode++) { -// out_length += s.dyn_dtree[dcode*2]/*.Freq*/ * (5 + extra_dbits[dcode]); -// } -// out_length >>>= 3; -// //Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ", -// // s->last_lit, in_length, out_length, -// // 100L - out_length*100L/in_length)); -// if (s.matches < (s.last_lit>>1)/*int /2*/ && out_length < (in_length>>1)/*int /2*/) { -// return true; -// } -// } -//#endif + var x1 = new BN(1); + var x2 = new BN(0); - return (s.last_lit === s.lit_bufsize - 1); - /* We avoid equality with lit_bufsize because of wraparound at 64K - * on 16 bit machines and because stored blocks are restricted to - * 64K-1 bytes. - */ -}; + var delta = b.clone(); -module.exports._tr_init = _tr_init; -module.exports._tr_stored_block = _tr_stored_block; -module.exports._tr_flush_block = _tr_flush_block; -module.exports._tr_tally = _tr_tally; -module.exports._tr_align = _tr_align; + while (a.cmpn(1) > 0 && b.cmpn(1) > 0) { + for (var i = 0, im = 1; (a.words[0] & im) === 0 && i < 26; ++i, im <<= 1); + if (i > 0) { + a.iushrn(i); + while (i-- > 0) { + if (x1.isOdd()) { + x1.iadd(delta); + } -},{}],80:[function(require,module,exports){ -'use strict'; + x1.iushrn(1); + } + } -// (C) 1995-2013 Jean-loup Gailly and Mark Adler -// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. + for (var j = 0, jm = 1; (b.words[0] & jm) === 0 && j < 26; ++j, jm <<= 1); + if (j > 0) { + b.iushrn(j); + while (j-- > 0) { + if (x2.isOdd()) { + x2.iadd(delta); + } -function ZStream() { - /* next input byte */ - this.input = null; // JS specific, because we have no pointers - this.next_in = 0; - /* number of bytes available at input */ - this.avail_in = 0; - /* total number of input bytes read so far */ - this.total_in = 0; - /* next output byte should be put there */ - this.output = null; // JS specific, because we have no pointers - this.next_out = 0; - /* remaining free space at output */ - this.avail_out = 0; - /* total number of bytes output so far */ - this.total_out = 0; - /* last error message, NULL if no error */ - this.msg = ''/*Z_NULL*/; - /* not visible by applications */ - this.state = null; - /* best guess about the data type: binary or text */ - this.data_type = 2/*Z_UNKNOWN*/; - /* adler32 value of the uncompressed data */ - this.adler = 0; -} + x2.iushrn(1); + } + } -module.exports = ZStream; + if (a.cmp(b) >= 0) { + a.isub(b); + x1.isub(x2); + } else { + b.isub(a); + x2.isub(x1); + } + } -},{}],81:[function(require,module,exports){ -var v1 = require('./v1'); -var v4 = require('./v4'); + var res; + if (a.cmpn(1) === 0) { + res = x1; + } else { + res = x2; + } -var uuid = v4; -uuid.v1 = v1; -uuid.v4 = v4; + if (res.cmpn(0) < 0) { + res.iadd(p); + } -module.exports = uuid; + return res; + }; -},{"./v1":84,"./v4":85}],82:[function(require,module,exports){ -/** - * Convert array of 16 byte values to UUID string format of the form: - * XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX - */ -var byteToHex = []; -for (var i = 0; i < 256; ++i) { - byteToHex[i] = (i + 0x100).toString(16).substr(1); -} + BN.prototype.gcd = function gcd (num) { + if (this.isZero()) return num.abs(); + if (num.isZero()) return this.abs(); -function bytesToUuid(buf, offset) { - var i = offset || 0; - var bth = byteToHex; - // join used to fix memory issue caused by concatenation: https://bugs.chromium.org/p/v8/issues/detail?id=3175#c4 - return ([ - bth[buf[i++]], bth[buf[i++]], - bth[buf[i++]], bth[buf[i++]], '-', - bth[buf[i++]], bth[buf[i++]], '-', - bth[buf[i++]], bth[buf[i++]], '-', - bth[buf[i++]], bth[buf[i++]], '-', - bth[buf[i++]], bth[buf[i++]], - bth[buf[i++]], bth[buf[i++]], - bth[buf[i++]], bth[buf[i++]] - ]).join(''); -} + var a = this.clone(); + var b = num.clone(); + a.negative = 0; + b.negative = 0; -module.exports = bytesToUuid; + // Remove common factor of two + for (var shift = 0; a.isEven() && b.isEven(); shift++) { + a.iushrn(1); + b.iushrn(1); + } -},{}],83:[function(require,module,exports){ -// Unique ID creation requires a high quality random # generator. In the -// browser this is a little complicated due to unknown quality of Math.random() -// and inconsistent support for the `crypto` API. We do the best we can via -// feature-detection + do { + while (a.isEven()) { + a.iushrn(1); + } + while (b.isEven()) { + b.iushrn(1); + } -// getRandomValues needs to be invoked in a context where "this" is a Crypto -// implementation. Also, find the complete implementation of crypto on IE11. -var getRandomValues = (typeof(crypto) != 'undefined' && crypto.getRandomValues && crypto.getRandomValues.bind(crypto)) || - (typeof(msCrypto) != 'undefined' && typeof window.msCrypto.getRandomValues == 'function' && msCrypto.getRandomValues.bind(msCrypto)); + var r = a.cmp(b); + if (r < 0) { + // Swap `a` and `b` to make `a` always bigger than `b` + var t = a; + a = b; + b = t; + } else if (r === 0 || b.cmpn(1) === 0) { + break; + } -if (getRandomValues) { - // WHATWG crypto RNG - http://wiki.whatwg.org/wiki/Crypto - var rnds8 = new Uint8Array(16); // eslint-disable-line no-undef + a.isub(b); + } while (true); - module.exports = function whatwgRNG() { - getRandomValues(rnds8); - return rnds8; + return b.iushln(shift); }; -} else { - // Math.random()-based (RNG) - // - // If all else fails, use Math.random(). It's fast, but is of unspecified - // quality. - var rnds = new Array(16); - - module.exports = function mathRNG() { - for (var i = 0, r; i < 16; i++) { - if ((i & 0x03) === 0) r = Math.random() * 0x100000000; - rnds[i] = r >>> ((i & 0x03) << 3) & 0xff; - } - return rnds; + // Invert number in the field F(num) + BN.prototype.invm = function invm (num) { + return this.egcd(num).a.umod(num); }; -} - -},{}],84:[function(require,module,exports){ -var rng = require('./lib/rng'); -var bytesToUuid = require('./lib/bytesToUuid'); -// **`v1()` - Generate time-based UUID** -// -// Inspired by https://github.com/LiosK/UUID.js -// and http://docs.python.org/library/uuid.html + BN.prototype.isEven = function isEven () { + return (this.words[0] & 1) === 0; + }; -var _nodeId; -var _clockseq; + BN.prototype.isOdd = function isOdd () { + return (this.words[0] & 1) === 1; + }; -// Previous uuid creation time -var _lastMSecs = 0; -var _lastNSecs = 0; + // And first word and num + BN.prototype.andln = function andln (num) { + return this.words[0] & num; + }; -// See https://github.com/uuidjs/uuid for API details -function v1(options, buf, offset) { - var i = buf && offset || 0; - var b = buf || []; + // Increment at the bit position in-line + BN.prototype.bincn = function bincn (bit) { + assert(typeof bit === 'number'); + var r = bit % 26; + var s = (bit - r) / 26; + var q = 1 << r; - options = options || {}; - var node = options.node || _nodeId; - var clockseq = options.clockseq !== undefined ? options.clockseq : _clockseq; + // Fast case: bit is much higher than all existing words + if (this.length <= s) { + this._expand(s + 1); + this.words[s] |= q; + return this; + } - // node and clockseq need to be initialized to random values if they're not - // specified. We do this lazily to minimize issues related to insufficient - // system entropy. See #189 - if (node == null || clockseq == null) { - var seedBytes = rng(); - if (node == null) { - // Per 4.5, create and 48-bit node id, (47 random bits + multicast bit = 1) - node = _nodeId = [ - seedBytes[0] | 0x01, - seedBytes[1], seedBytes[2], seedBytes[3], seedBytes[4], seedBytes[5] - ]; + // Add bit and propagate, if needed + var carry = q; + for (var i = s; carry !== 0 && i < this.length; i++) { + var w = this.words[i] | 0; + w += carry; + carry = w >>> 26; + w &= 0x3ffffff; + this.words[i] = w; } - if (clockseq == null) { - // Per 4.2.2, randomize (14 bit) clockseq - clockseq = _clockseq = (seedBytes[6] << 8 | seedBytes[7]) & 0x3fff; + if (carry !== 0) { + this.words[i] = carry; + this.length++; } - } + return this; + }; - // UUID timestamps are 100 nano-second units since the Gregorian epoch, - // (1582-10-15 00:00). JSNumbers aren't precise enough for this, so - // time is handled internally as 'msecs' (integer milliseconds) and 'nsecs' - // (100-nanoseconds offset from msecs) since unix epoch, 1970-01-01 00:00. - var msecs = options.msecs !== undefined ? options.msecs : new Date().getTime(); + BN.prototype.isZero = function isZero () { + return this.length === 1 && this.words[0] === 0; + }; - // Per 4.2.1.2, use count of uuid's generated during the current clock - // cycle to simulate higher resolution clock - var nsecs = options.nsecs !== undefined ? options.nsecs : _lastNSecs + 1; + BN.prototype.cmpn = function cmpn (num) { + var negative = num < 0; - // Time since last uuid creation (in msecs) - var dt = (msecs - _lastMSecs) + (nsecs - _lastNSecs)/10000; + if (this.negative !== 0 && !negative) return -1; + if (this.negative === 0 && negative) return 1; - // Per 4.2.1.2, Bump clockseq on clock regression - if (dt < 0 && options.clockseq === undefined) { - clockseq = clockseq + 1 & 0x3fff; - } + this.strip(); - // Reset nsecs if clock regresses (new clockseq) or we've moved onto a new - // time interval - if ((dt < 0 || msecs > _lastMSecs) && options.nsecs === undefined) { - nsecs = 0; - } + var res; + if (this.length > 1) { + res = 1; + } else { + if (negative) { + num = -num; + } - // Per 4.2.1.2 Throw error if too many uuids are requested - if (nsecs >= 10000) { - throw new Error('uuid.v1(): Can\'t create more than 10M uuids/sec'); - } + assert(num <= 0x3ffffff, 'Number is too big'); - _lastMSecs = msecs; - _lastNSecs = nsecs; - _clockseq = clockseq; + var w = this.words[0] | 0; + res = w === num ? 0 : w < num ? -1 : 1; + } + if (this.negative !== 0) return -res | 0; + return res; + }; - // Per 4.1.4 - Convert from unix epoch to Gregorian epoch - msecs += 12219292800000; + // Compare two numbers and return: + // 1 - if `this` > `num` + // 0 - if `this` == `num` + // -1 - if `this` < `num` + BN.prototype.cmp = function cmp (num) { + if (this.negative !== 0 && num.negative === 0) return -1; + if (this.negative === 0 && num.negative !== 0) return 1; - // `time_low` - var tl = ((msecs & 0xfffffff) * 10000 + nsecs) % 0x100000000; - b[i++] = tl >>> 24 & 0xff; - b[i++] = tl >>> 16 & 0xff; - b[i++] = tl >>> 8 & 0xff; - b[i++] = tl & 0xff; + var res = this.ucmp(num); + if (this.negative !== 0) return -res | 0; + return res; + }; - // `time_mid` - var tmh = (msecs / 0x100000000 * 10000) & 0xfffffff; - b[i++] = tmh >>> 8 & 0xff; - b[i++] = tmh & 0xff; + // Unsigned comparison + BN.prototype.ucmp = function ucmp (num) { + // At this point both numbers have the same sign + if (this.length > num.length) return 1; + if (this.length < num.length) return -1; - // `time_high_and_version` - b[i++] = tmh >>> 24 & 0xf | 0x10; // include version - b[i++] = tmh >>> 16 & 0xff; + var res = 0; + for (var i = this.length - 1; i >= 0; i--) { + var a = this.words[i] | 0; + var b = num.words[i] | 0; - // `clock_seq_hi_and_reserved` (Per 4.2.2 - include variant) - b[i++] = clockseq >>> 8 | 0x80; + if (a === b) continue; + if (a < b) { + res = -1; + } else if (a > b) { + res = 1; + } + break; + } + return res; + }; - // `clock_seq_low` - b[i++] = clockseq & 0xff; + BN.prototype.gtn = function gtn (num) { + return this.cmpn(num) === 1; + }; - // `node` - for (var n = 0; n < 6; ++n) { - b[i + n] = node[n]; - } + BN.prototype.gt = function gt (num) { + return this.cmp(num) === 1; + }; - return buf ? buf : bytesToUuid(b); -} + BN.prototype.gten = function gten (num) { + return this.cmpn(num) >= 0; + }; -module.exports = v1; + BN.prototype.gte = function gte (num) { + return this.cmp(num) >= 0; + }; -},{"./lib/bytesToUuid":82,"./lib/rng":83}],85:[function(require,module,exports){ -var rng = require('./lib/rng'); -var bytesToUuid = require('./lib/bytesToUuid'); + BN.prototype.ltn = function ltn (num) { + return this.cmpn(num) === -1; + }; -function v4(options, buf, offset) { - var i = buf && offset || 0; + BN.prototype.lt = function lt (num) { + return this.cmp(num) === -1; + }; - if (typeof(options) == 'string') { - buf = options === 'binary' ? new Array(16) : null; - options = null; - } - options = options || {}; + BN.prototype.lten = function lten (num) { + return this.cmpn(num) <= 0; + }; - var rnds = options.random || (options.rng || rng)(); + BN.prototype.lte = function lte (num) { + return this.cmp(num) <= 0; + }; - // Per 4.4, set bits for version and `clock_seq_hi_and_reserved` - rnds[6] = (rnds[6] & 0x0f) | 0x40; - rnds[8] = (rnds[8] & 0x3f) | 0x80; + BN.prototype.eqn = function eqn (num) { + return this.cmpn(num) === 0; + }; - // Copy bytes to buffer, if provided - if (buf) { - for (var ii = 0; ii < 16; ++ii) { - buf[i + ii] = rnds[ii]; - } - } + BN.prototype.eq = function eq (num) { + return this.cmp(num) === 0; + }; - return buf || bytesToUuid(rnds); -} - -module.exports = v4; + // + // A reduce context, could be using montgomery or something better, depending + // on the `m` itself. + // + BN.red = function red (num) { + return new Red(num); + }; -},{"./lib/bytesToUuid":82,"./lib/rng":83}],86:[function(require,module,exports){ -const uuid = require('./uuid') -const Frontend = require('../frontend') -const { OPTIONS } = require('../frontend/constants') -const { encodeChange, decodeChange } = require('../backend/columnar') -const { isObject } = require('./common') -let backend = require('../backend') // mutable: can be overridden with setDefaultBackend() + BN.prototype.toRed = function toRed (ctx) { + assert(!this.red, 'Already a number in reduction context'); + assert(this.negative === 0, 'red works only with positives'); + return ctx.convertTo(this)._forceRed(ctx); + }; -/** - * Automerge.* API - * The functions in this file constitute the publicly facing Automerge API which combines - * the features of the Frontend (a document interface) and the backend (CRDT operations) - */ + BN.prototype.fromRed = function fromRed () { + assert(this.red, 'fromRed works only with numbers in reduction context'); + return this.red.convertFrom(this); + }; -function init(options) { - if (typeof options === 'string') { - options = {actorId: options} - } else if (typeof options === 'undefined') { - options = {} - } else if (!isObject(options)) { - throw new TypeError(`Unsupported options for init(): ${options}`) - } - return Frontend.init(Object.assign({backend}, options)) -} + BN.prototype._forceRed = function _forceRed (ctx) { + this.red = ctx; + return this; + }; -/** - * Returns a new document object initialized with the given state. - */ -function from(initialState, options) { - const changeOpts = {message: 'Initialization'} - return change(init(options), changeOpts, doc => Object.assign(doc, initialState)) -} + BN.prototype.forceRed = function forceRed (ctx) { + assert(!this.red, 'Already a number in reduction context'); + return this._forceRed(ctx); + }; -function change(doc, options, callback) { - const [newDoc] = Frontend.change(doc, options, callback) - return newDoc -} + BN.prototype.redAdd = function redAdd (num) { + assert(this.red, 'redAdd works only with red numbers'); + return this.red.add(this, num); + }; -function emptyChange(doc, options) { - const [newDoc] = Frontend.emptyChange(doc, options) - return newDoc -} + BN.prototype.redIAdd = function redIAdd (num) { + assert(this.red, 'redIAdd works only with red numbers'); + return this.red.iadd(this, num); + }; -function clone(doc, options = {}) { - const state = backend.clone(Frontend.getBackendState(doc, 'clone')) - return applyPatch(init(options), backend.getPatch(state), state, [], options) -} + BN.prototype.redSub = function redSub (num) { + assert(this.red, 'redSub works only with red numbers'); + return this.red.sub(this, num); + }; -function free(doc) { - backend.free(Frontend.getBackendState(doc, 'free')) -} + BN.prototype.redISub = function redISub (num) { + assert(this.red, 'redISub works only with red numbers'); + return this.red.isub(this, num); + }; -function load(data, options = {}) { - const state = backend.load(data) - return applyPatch(init(options), backend.getPatch(state), state, [data], options) -} + BN.prototype.redShl = function redShl (num) { + assert(this.red, 'redShl works only with red numbers'); + return this.red.shl(this, num); + }; -function save(doc) { - return backend.save(Frontend.getBackendState(doc, 'save')) -} + BN.prototype.redMul = function redMul (num) { + assert(this.red, 'redMul works only with red numbers'); + this.red._verify2(this, num); + return this.red.mul(this, num); + }; -function merge(localDoc, remoteDoc) { - const localState = Frontend.getBackendState(localDoc, 'merge') - const remoteState = Frontend.getBackendState(remoteDoc, 'merge', 'second') - if (Frontend.getActorId(localDoc) === Frontend.getActorId(remoteDoc)) { - throw new RangeError('Cannot merge an actor with itself') - } - const changes = backend.getChangesAdded(localState, remoteState) - const [updatedDoc] = applyChanges(localDoc, changes) - return updatedDoc -} + BN.prototype.redIMul = function redIMul (num) { + assert(this.red, 'redMul works only with red numbers'); + this.red._verify2(this, num); + return this.red.imul(this, num); + }; -function getChanges(oldDoc, newDoc) { - const oldState = Frontend.getBackendState(oldDoc, 'getChanges') - const newState = Frontend.getBackendState(newDoc, 'getChanges', 'second') - return backend.getChanges(newState, backend.getHeads(oldState)) -} + BN.prototype.redSqr = function redSqr () { + assert(this.red, 'redSqr works only with red numbers'); + this.red._verify1(this); + return this.red.sqr(this); + }; -function getAllChanges(doc) { - return backend.getAllChanges(Frontend.getBackendState(doc, 'getAllChanges')) -} + BN.prototype.redISqr = function redISqr () { + assert(this.red, 'redISqr works only with red numbers'); + this.red._verify1(this); + return this.red.isqr(this); + }; -function applyPatch(doc, patch, backendState, changes, options) { - const newDoc = Frontend.applyPatch(doc, patch, backendState) - const patchCallback = options.patchCallback || doc[OPTIONS].patchCallback - if (patchCallback) { - patchCallback(patch, doc, newDoc, false, changes) - } - return newDoc -} + // Square root over p + BN.prototype.redSqrt = function redSqrt () { + assert(this.red, 'redSqrt works only with red numbers'); + this.red._verify1(this); + return this.red.sqrt(this); + }; -function applyChanges(doc, changes, options = {}) { - const oldState = Frontend.getBackendState(doc, 'applyChanges') - const [newState, patch] = backend.applyChanges(oldState, changes) - return [applyPatch(doc, patch, newState, changes, options), patch] -} + BN.prototype.redInvm = function redInvm () { + assert(this.red, 'redInvm works only with red numbers'); + this.red._verify1(this); + return this.red.invm(this); + }; -function equals(val1, val2) { - if (!isObject(val1) || !isObject(val2)) return val1 === val2 - const keys1 = Object.keys(val1).sort(), keys2 = Object.keys(val2).sort() - if (keys1.length !== keys2.length) return false - for (let i = 0; i < keys1.length; i++) { - if (keys1[i] !== keys2[i]) return false - if (!equals(val1[keys1[i]], val2[keys2[i]])) return false - } - return true -} + // Return negative clone of `this` % `red modulo` + BN.prototype.redNeg = function redNeg () { + assert(this.red, 'redNeg works only with red numbers'); + this.red._verify1(this); + return this.red.neg(this); + }; -function getHistory(doc) { - const actor = Frontend.getActorId(doc) - const history = getAllChanges(doc) - return history.map((change, index) => ({ - get change () { - return decodeChange(change) - }, - get snapshot () { - const state = backend.loadChanges(backend.init(), history.slice(0, index + 1)) - return Frontend.applyPatch(init(actor), backend.getPatch(state), state) - } - }) - ) -} + BN.prototype.redPow = function redPow (num) { + assert(this.red && !num.red, 'redPow(normalNum)'); + this.red._verify1(this); + return this.red.pow(this, num); + }; -function generateSyncMessage(doc, syncState) { - const state = Frontend.getBackendState(doc, 'generateSyncMessage') - return backend.generateSyncMessage(state, syncState) -} + // Prime numbers with efficient reduction + var primes = { + k256: null, + p224: null, + p192: null, + p25519: null + }; -function receiveSyncMessage(doc, oldSyncState, message) { - const oldBackendState = Frontend.getBackendState(doc, 'receiveSyncMessage') - const [backendState, syncState, patch] = backend.receiveSyncMessage(oldBackendState, oldSyncState, message) - if (!patch) return [doc, syncState, patch] + // Pseudo-Mersenne prime + function MPrime (name, p) { + // P = 2 ^ N - K + this.name = name; + this.p = new BN(p, 16); + this.n = this.p.bitLength(); + this.k = new BN(1).iushln(this.n).isub(this.p); - // The patchCallback is passed as argument all changes that are applied. - // We get those from the sync message if a patchCallback is present. - let changes = null - if (doc[OPTIONS].patchCallback) { - changes = backend.decodeSyncMessage(message).changes + this.tmp = this._tmp(); } - return [applyPatch(doc, patch, backendState, changes, {}), syncState, patch] -} -function initSyncState() { - return backend.initSyncState() -} + MPrime.prototype._tmp = function _tmp () { + var tmp = new BN(null); + tmp.words = new Array(Math.ceil(this.n / 13)); + return tmp; + }; -/** - * Replaces the default backend implementation with a different one. - * This allows you to switch to using the Rust/WebAssembly implementation. - */ -function setDefaultBackend(newBackend) { - backend = newBackend -} + MPrime.prototype.ireduce = function ireduce (num) { + // Assumes that `num` is less than `P^2` + // num = HI * (2 ^ N - K) + HI * K + LO = HI * K + LO (mod P) + var r = num; + var rlen; -module.exports = { - init, from, change, emptyChange, clone, free, - load, save, merge, getChanges, getAllChanges, applyChanges, - encodeChange, decodeChange, equals, getHistory, uuid, - Frontend, setDefaultBackend, generateSyncMessage, receiveSyncMessage, initSyncState, - get Backend() { return backend } -} + do { + this.split(r, this.tmp); + r = this.imulK(r); + r = r.iadd(this.tmp); + rlen = r.bitLength(); + } while (rlen > this.n); -for (let name of ['getObjectId', 'getObjectById', 'getActorId', - 'setActorId', 'getConflicts', 'getLastLocalChange', - 'Text', 'Table', 'Counter', 'Observable', 'Int', 'Uint', 'Float64']) { - module.exports[name] = Frontend[name] -} + var cmp = rlen < this.n ? -1 : r.ucmp(this.p); + if (cmp === 0) { + r.words[0] = 0; + r.length = 1; + } else if (cmp > 0) { + r.isub(this.p); + } else { + if (r.strip !== undefined) { + // r is BN v4 instance + r.strip(); + } else { + // r is BN v5 instance + r._strip(); + } + } -},{"../backend":51,"../backend/columnar":49,"../frontend":59,"../frontend/constants":56,"./common":87,"./uuid":88}],87:[function(require,module,exports){ -function isObject(obj) { - return typeof obj === 'object' && obj !== null -} + return r; + }; -/** - * Returns a shallow copy of the object `obj`. Faster than `Object.assign({}, obj)`. - * https://jsperf.com/cloning-large-objects/1 - */ -function copyObject(obj) { - if (!isObject(obj)) return {} - let copy = {} - for (let key of Object.keys(obj)) { - copy[key] = obj[key] - } - return copy -} + MPrime.prototype.split = function split (input, out) { + input.iushrn(this.n, 0, out); + }; -/** - * Takes a string in the form that is used to identify operations (a counter concatenated - * with an actor ID, separated by an `@` sign) and returns an object `{counter, actorId}`. - */ -function parseOpId(opId) { - const match = /^(\d+)@(.*)$/.exec(opId || '') - if (!match) { - throw new RangeError(`Not a valid opId: ${opId}`) - } - return {counter: parseInt(match[1], 10), actorId: match[2]} -} + MPrime.prototype.imulK = function imulK (num) { + return num.imul(this.k); + }; -/** - * Returns true if the two byte arrays contain the same data, false if not. - */ -function equalBytes(array1, array2) { - if (!(array1 instanceof Uint8Array) || !(array2 instanceof Uint8Array)) { - throw new TypeError('equalBytes can only compare Uint8Arrays') - } - if (array1.byteLength !== array2.byteLength) return false - for (let i = 0; i < array1.byteLength; i++) { - if (array1[i] !== array2[i]) return false + function K256 () { + MPrime.call( + this, + 'k256', + 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe fffffc2f'); } - return true -} - -/** - * Creates an array containing the value `null` repeated `length` times. - */ -function createArrayOfNulls(length) { - const array = new Array(length) - for (let i = 0; i < length; i++) array[i] = null - return array -} - -module.exports = { - isObject, copyObject, parseOpId, equalBytes, createArrayOfNulls -} + inherits(K256, MPrime); -},{}],88:[function(require,module,exports){ -const { v4: uuid } = require('uuid') + K256.prototype.split = function split (input, output) { + // 256 = 9 * 26 + 22 + var mask = 0x3fffff; -function defaultFactory() { - return uuid().replace(/-/g, '') -} + var outLen = Math.min(input.length, 9); + for (var i = 0; i < outLen; i++) { + output.words[i] = input.words[i]; + } + output.length = outLen; -let factory = defaultFactory + if (input.length <= 9) { + input.words[0] = 0; + input.length = 1; + return; + } -function makeUuid() { - return factory() -} + // Shift by 9 limbs + var prev = input.words[9]; + output.words[output.length++] = prev & mask; -makeUuid.setFactory = newFactory => { factory = newFactory } -makeUuid.reset = () => { factory = defaultFactory } + for (i = 10; i < input.length; i++) { + var next = input.words[i] | 0; + input.words[i - 10] = ((next & mask) << 4) | (prev >>> 22); + prev = next; + } + prev >>>= 22; + input.words[i - 10] = prev; + if (prev === 0 && input.length > 10) { + input.length -= 10; + } else { + input.length -= 9; + } + }; -module.exports = makeUuid + K256.prototype.imulK = function imulK (num) { + // K = 0x1000003d1 = [ 0x40, 0x3d1 ] + num.words[num.length] = 0; + num.words[num.length + 1] = 0; + num.length += 2; -},{"uuid":81}],89:[function(require,module,exports){ -(function (global){(function (){ -'use strict'; + // bounded at: 0x40 * 0x3ffffff + 0x3d0 = 0x100000390 + var lo = 0; + for (var i = 0; i < num.length; i++) { + var w = num.words[i] | 0; + lo += w * 0x3d1; + num.words[i] = lo & 0x3ffffff; + lo = w * 0x40 + ((lo / 0x4000000) | 0); + } -var possibleNames = require('possible-typed-array-names'); + // Fast length reduction + if (num.words[num.length - 1] === 0) { + num.length--; + if (num.words[num.length - 1] === 0) { + num.length--; + } + } + return num; + }; -var g = typeof globalThis === 'undefined' ? global : globalThis; + function P224 () { + MPrime.call( + this, + 'p224', + 'ffffffff ffffffff ffffffff ffffffff 00000000 00000000 00000001'); + } + inherits(P224, MPrime); -/** @type {import('.')} */ -module.exports = function availableTypedArrays() { - var /** @type {ReturnType} */ out = []; - for (var i = 0; i < possibleNames.length; i++) { - if (typeof g[possibleNames[i]] === 'function') { - // @ts-expect-error - out[out.length] = possibleNames[i]; - } - } - return out; -}; + function P192 () { + MPrime.call( + this, + 'p192', + 'ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff'); + } + inherits(P192, MPrime); -}).call(this)}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"possible-typed-array-names":390}],90:[function(require,module,exports){ -'use strict' + function P25519 () { + // 2 ^ 255 - 19 + MPrime.call( + this, + '25519', + '7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed'); + } + inherits(P25519, MPrime); -exports.byteLength = byteLength -exports.toByteArray = toByteArray -exports.fromByteArray = fromByteArray + P25519.prototype.imulK = function imulK (num) { + // K = 0x13 + var carry = 0; + for (var i = 0; i < num.length; i++) { + var hi = (num.words[i] | 0) * 0x13 + carry; + var lo = hi & 0x3ffffff; + hi >>>= 26; -var lookup = [] -var revLookup = [] -var Arr = typeof Uint8Array !== 'undefined' ? Uint8Array : Array + num.words[i] = lo; + carry = hi; + } + if (carry !== 0) { + num.words[num.length++] = carry; + } + return num; + }; -var code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' -for (var i = 0, len = code.length; i < len; ++i) { - lookup[i] = code[i] - revLookup[code.charCodeAt(i)] = i -} + // Exported mostly for testing purposes, use plain name instead + BN._prime = function prime (name) { + // Cached version of prime + if (primes[name]) return primes[name]; -// Support decoding URL-safe base64 strings, as Node.js does. -// See: https://en.wikipedia.org/wiki/Base64#URL_applications -revLookup['-'.charCodeAt(0)] = 62 -revLookup['_'.charCodeAt(0)] = 63 + var prime; + if (name === 'k256') { + prime = new K256(); + } else if (name === 'p224') { + prime = new P224(); + } else if (name === 'p192') { + prime = new P192(); + } else if (name === 'p25519') { + prime = new P25519(); + } else { + throw new Error('Unknown prime ' + name); + } + primes[name] = prime; -function getLens (b64) { - var len = b64.length + return prime; + }; - if (len % 4 > 0) { - throw new Error('Invalid string. Length must be a multiple of 4') + // + // Base reduction engine + // + function Red (m) { + if (typeof m === 'string') { + var prime = BN._prime(m); + this.m = prime.p; + this.prime = prime; + } else { + assert(m.gtn(1), 'modulus must be greater than 1'); + this.m = m; + this.prime = null; + } } - // Trim off extra bytes after placeholder bytes are found - // See: https://github.com/beatgammit/base64-js/issues/42 - var validLen = b64.indexOf('=') - if (validLen === -1) validLen = len - - var placeHoldersLen = validLen === len - ? 0 - : 4 - (validLen % 4) - - return [validLen, placeHoldersLen] -} - -// base64 is 4/3 + up to two characters of the original data -function byteLength (b64) { - var lens = getLens(b64) - var validLen = lens[0] - var placeHoldersLen = lens[1] - return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen -} + Red.prototype._verify1 = function _verify1 (a) { + assert(a.negative === 0, 'red works only with positives'); + assert(a.red, 'red works only with red numbers'); + }; -function _byteLength (b64, validLen, placeHoldersLen) { - return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen -} + Red.prototype._verify2 = function _verify2 (a, b) { + assert((a.negative | b.negative) === 0, 'red works only with positives'); + assert(a.red && a.red === b.red, + 'red works only with red numbers'); + }; -function toByteArray (b64) { - var tmp - var lens = getLens(b64) - var validLen = lens[0] - var placeHoldersLen = lens[1] + Red.prototype.imod = function imod (a) { + if (this.prime) return this.prime.ireduce(a)._forceRed(this); + return a.umod(this.m)._forceRed(this); + }; - var arr = new Arr(_byteLength(b64, validLen, placeHoldersLen)) + Red.prototype.neg = function neg (a) { + if (a.isZero()) { + return a.clone(); + } - var curByte = 0 + return this.m.sub(a)._forceRed(this); + }; - // if there are placeholders, only get up to the last complete 4 chars - var len = placeHoldersLen > 0 - ? validLen - 4 - : validLen + Red.prototype.add = function add (a, b) { + this._verify2(a, b); - var i - for (i = 0; i < len; i += 4) { - tmp = - (revLookup[b64.charCodeAt(i)] << 18) | - (revLookup[b64.charCodeAt(i + 1)] << 12) | - (revLookup[b64.charCodeAt(i + 2)] << 6) | - revLookup[b64.charCodeAt(i + 3)] - arr[curByte++] = (tmp >> 16) & 0xFF - arr[curByte++] = (tmp >> 8) & 0xFF - arr[curByte++] = tmp & 0xFF - } + var res = a.add(b); + if (res.cmp(this.m) >= 0) { + res.isub(this.m); + } + return res._forceRed(this); + }; - if (placeHoldersLen === 2) { - tmp = - (revLookup[b64.charCodeAt(i)] << 2) | - (revLookup[b64.charCodeAt(i + 1)] >> 4) - arr[curByte++] = tmp & 0xFF - } + Red.prototype.iadd = function iadd (a, b) { + this._verify2(a, b); - if (placeHoldersLen === 1) { - tmp = - (revLookup[b64.charCodeAt(i)] << 10) | - (revLookup[b64.charCodeAt(i + 1)] << 4) | - (revLookup[b64.charCodeAt(i + 2)] >> 2) - arr[curByte++] = (tmp >> 8) & 0xFF - arr[curByte++] = tmp & 0xFF - } + var res = a.iadd(b); + if (res.cmp(this.m) >= 0) { + res.isub(this.m); + } + return res; + }; - return arr -} + Red.prototype.sub = function sub (a, b) { + this._verify2(a, b); -function tripletToBase64 (num) { - return lookup[num >> 18 & 0x3F] + - lookup[num >> 12 & 0x3F] + - lookup[num >> 6 & 0x3F] + - lookup[num & 0x3F] -} + var res = a.sub(b); + if (res.cmpn(0) < 0) { + res.iadd(this.m); + } + return res._forceRed(this); + }; -function encodeChunk (uint8, start, end) { - var tmp - var output = [] - for (var i = start; i < end; i += 3) { - tmp = - ((uint8[i] << 16) & 0xFF0000) + - ((uint8[i + 1] << 8) & 0xFF00) + - (uint8[i + 2] & 0xFF) - output.push(tripletToBase64(tmp)) - } - return output.join('') -} + Red.prototype.isub = function isub (a, b) { + this._verify2(a, b); -function fromByteArray (uint8) { - var tmp - var len = uint8.length - var extraBytes = len % 3 // if we have 1 byte left, pad 2 bytes - var parts = [] - var maxChunkLength = 16383 // must be multiple of 3 + var res = a.isub(b); + if (res.cmpn(0) < 0) { + res.iadd(this.m); + } + return res; + }; - // go through the array every three bytes, we'll deal with trailing stuff later - for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) { - parts.push(encodeChunk(uint8, i, (i + maxChunkLength) > len2 ? len2 : (i + maxChunkLength))) - } + Red.prototype.shl = function shl (a, num) { + this._verify1(a); + return this.imod(a.ushln(num)); + }; - // pad the end with zeros, but make sure to not forget the extra bytes - if (extraBytes === 1) { - tmp = uint8[len - 1] - parts.push( - lookup[tmp >> 2] + - lookup[(tmp << 4) & 0x3F] + - '==' - ) - } else if (extraBytes === 2) { - tmp = (uint8[len - 2] << 8) + uint8[len - 1] - parts.push( - lookup[tmp >> 10] + - lookup[(tmp >> 4) & 0x3F] + - lookup[(tmp << 2) & 0x3F] + - '=' - ) - } + Red.prototype.imul = function imul (a, b) { + this._verify2(a, b); + return this.imod(a.imul(b)); + }; - return parts.join('') -} + Red.prototype.mul = function mul (a, b) { + this._verify2(a, b); + return this.imod(a.mul(b)); + }; -},{}],91:[function(require,module,exports){ -(function (module, exports) { - 'use strict'; + Red.prototype.isqr = function isqr (a) { + return this.imul(a, a.clone()); + }; - // Utils - function assert (val, msg) { - if (!val) throw new Error(msg || 'Assertion failed'); - } + Red.prototype.sqr = function sqr (a) { + return this.mul(a, a); + }; - // Could use `inherits` module, but don't want to move from single file - // architecture yet. - function inherits (ctor, superCtor) { - ctor.super_ = superCtor; - var TempCtor = function () {}; - TempCtor.prototype = superCtor.prototype; - ctor.prototype = new TempCtor(); - ctor.prototype.constructor = ctor; - } + Red.prototype.sqrt = function sqrt (a) { + if (a.isZero()) return a.clone(); - // BN + var mod3 = this.m.andln(3); + assert(mod3 % 2 === 1); - function BN (number, base, endian) { - if (BN.isBN(number)) { - return number; + // Fast case + if (mod3 === 3) { + var pow = this.m.add(new BN(1)).iushrn(2); + return this.pow(a, pow); } - this.negative = 0; - this.words = null; - this.length = 0; + // Tonelli-Shanks algorithm (Totally unoptimized and slow) + // + // Find Q and S, that Q * 2 ^ S = (P - 1) + var q = this.m.subn(1); + var s = 0; + while (!q.isZero() && q.andln(1) === 0) { + s++; + q.iushrn(1); + } + assert(!q.isZero()); - // Reduction context - this.red = null; + var one = new BN(1).toRed(this); + var nOne = one.redNeg(); - if (number !== null) { - if (base === 'le' || base === 'be') { - endian = base; - base = 10; - } + // Find quadratic non-residue + // NOTE: Max is such because of generalized Riemann hypothesis. + var lpow = this.m.subn(1).iushrn(1); + var z = this.m.bitLength(); + z = new BN(2 * z * z).toRed(this); - this._init(number || 0, base || 10, endian || 'be'); + while (this.pow(z, lpow).cmp(nOne) !== 0) { + z.redIAdd(nOne); } - } - if (typeof module === 'object') { - module.exports = BN; - } else { - exports.BN = BN; - } - - BN.BN = BN; - BN.wordSize = 26; - var Buffer; - try { - if (typeof window !== 'undefined' && typeof window.Buffer !== 'undefined') { - Buffer = window.Buffer; - } else { - Buffer = require('buffer').Buffer; - } - } catch (e) { - } + var c = this.pow(z, q); + var r = this.pow(a, q.addn(1).iushrn(1)); + var t = this.pow(a, q); + var m = s; + while (t.cmp(one) !== 0) { + var tmp = t; + for (var i = 0; tmp.cmp(one) !== 0; i++) { + tmp = tmp.redSqr(); + } + assert(i < m); + var b = this.pow(c, new BN(1).iushln(m - i - 1)); - BN.isBN = function isBN (num) { - if (num instanceof BN) { - return true; + r = r.redMul(b); + c = b.redSqr(); + t = t.redMul(c); + m = i; } - return num !== null && typeof num === 'object' && - num.constructor.wordSize === BN.wordSize && Array.isArray(num.words); - }; - - BN.max = function max (left, right) { - if (left.cmp(right) > 0) return left; - return right; + return r; }; - BN.min = function min (left, right) { - if (left.cmp(right) < 0) return left; - return right; + Red.prototype.invm = function invm (a) { + var inv = a._invmp(this.m); + if (inv.negative !== 0) { + inv.negative = 0; + return this.imod(inv).redNeg(); + } else { + return this.imod(inv); + } }; - BN.prototype._init = function init (number, base, endian) { - if (typeof number === 'number') { - return this._initNumber(number, base, endian); - } + Red.prototype.pow = function pow (a, num) { + if (num.isZero()) return new BN(1).toRed(this); + if (num.cmpn(1) === 0) return a.clone(); - if (typeof number === 'object') { - return this._initArray(number, base, endian); + var windowSize = 4; + var wnd = new Array(1 << windowSize); + wnd[0] = new BN(1).toRed(this); + wnd[1] = a; + for (var i = 2; i < wnd.length; i++) { + wnd[i] = this.mul(wnd[i - 1], a); } - if (base === 'hex') { - base = 16; + var res = wnd[0]; + var current = 0; + var currentLen = 0; + var start = num.bitLength() % 26; + if (start === 0) { + start = 26; } - assert(base === (base | 0) && base >= 2 && base <= 36); - number = number.toString().replace(/\s+/g, ''); - var start = 0; - if (number[0] === '-') { - start++; - this.negative = 1; - } + for (i = num.length - 1; i >= 0; i--) { + var word = num.words[i]; + for (var j = start - 1; j >= 0; j--) { + var bit = (word >> j) & 1; + if (res !== wnd[0]) { + res = this.sqr(res); + } - if (start < number.length) { - if (base === 16) { - this._parseHex(number, start, endian); - } else { - this._parseBase(number, base, start); - if (endian === 'le') { - this._initArray(this.toArray(), base, endian); + if (bit === 0 && current === 0) { + currentLen = 0; + continue; } + + current <<= 1; + current |= bit; + currentLen++; + if (currentLen !== windowSize && (i !== 0 || j !== 0)) continue; + + res = this.mul(res, wnd[current]); + currentLen = 0; + current = 0; } + start = 26; } - }; - BN.prototype._initNumber = function _initNumber (number, base, endian) { - if (number < 0) { - this.negative = 1; - number = -number; - } - if (number < 0x4000000) { - this.words = [number & 0x3ffffff]; - this.length = 1; - } else if (number < 0x10000000000000) { - this.words = [ - number & 0x3ffffff, - (number / 0x4000000) & 0x3ffffff - ]; - this.length = 2; - } else { - assert(number < 0x20000000000000); // 2 ^ 53 (unsafe) - this.words = [ - number & 0x3ffffff, - (number / 0x4000000) & 0x3ffffff, - 1 - ]; - this.length = 3; - } + return res; + }; - if (endian !== 'le') return; + Red.prototype.convertTo = function convertTo (num) { + var r = num.umod(this.m); - // Reverse the bytes - this._initArray(this.toArray(), base, endian); + return r === num ? r.clone() : r; }; - BN.prototype._initArray = function _initArray (number, base, endian) { - // Perhaps a Uint8Array - assert(typeof number.length === 'number'); - if (number.length <= 0) { - this.words = [0]; - this.length = 1; - return this; - } + Red.prototype.convertFrom = function convertFrom (num) { + var res = num.clone(); + res.red = null; + return res; + }; - this.length = Math.ceil(number.length / 3); - this.words = new Array(this.length); - for (var i = 0; i < this.length; i++) { - this.words[i] = 0; - } + // + // Montgomery method engine + // - var j, w; - var off = 0; - if (endian === 'be') { - for (i = number.length - 1, j = 0; i >= 0; i -= 3) { - w = number[i] | (number[i - 1] << 8) | (number[i - 2] << 16); - this.words[j] |= (w << off) & 0x3ffffff; - this.words[j + 1] = (w >>> (26 - off)) & 0x3ffffff; - off += 24; - if (off >= 26) { - off -= 26; - j++; - } - } - } else if (endian === 'le') { - for (i = 0, j = 0; i < number.length; i += 3) { - w = number[i] | (number[i + 1] << 8) | (number[i + 2] << 16); - this.words[j] |= (w << off) & 0x3ffffff; - this.words[j + 1] = (w >>> (26 - off)) & 0x3ffffff; - off += 24; - if (off >= 26) { - off -= 26; - j++; - } - } - } - return this._strip(); + BN.mont = function mont (num) { + return new Mont(num); }; - function parseHex4Bits (string, index) { - var c = string.charCodeAt(index); - // '0' - '9' - if (c >= 48 && c <= 57) { - return c - 48; - // 'A' - 'F' - } else if (c >= 65 && c <= 70) { - return c - 55; - // 'a' - 'f' - } else if (c >= 97 && c <= 102) { - return c - 87; - } else { - assert(false, 'Invalid character in ' + string); + function Mont (m) { + Red.call(this, m); + + this.shift = this.m.bitLength(); + if (this.shift % 26 !== 0) { + this.shift += 26 - (this.shift % 26); } + + this.r = new BN(1).iushln(this.shift); + this.r2 = this.imod(this.r.sqr()); + this.rinv = this.r._invmp(this.m); + + this.minv = this.rinv.mul(this.r).isubn(1).div(this.m); + this.minv = this.minv.umod(this.r); + this.minv = this.r.sub(this.minv); } + inherits(Mont, Red); - function parseHexByte (string, lowerBound, index) { - var r = parseHex4Bits(string, index); - if (index - 1 >= lowerBound) { - r |= parseHex4Bits(string, index - 1) << 4; - } + Mont.prototype.convertTo = function convertTo (num) { + return this.imod(num.ushln(this.shift)); + }; + + Mont.prototype.convertFrom = function convertFrom (num) { + var r = this.imod(num.mul(this.rinv)); + r.red = null; return r; - } + }; - BN.prototype._parseHex = function _parseHex (number, start, endian) { - // Create possibly bigger array to ensure that it fits the number - this.length = Math.ceil((number.length - start) / 6); - this.words = new Array(this.length); - for (var i = 0; i < this.length; i++) { - this.words[i] = 0; + Mont.prototype.imul = function imul (a, b) { + if (a.isZero() || b.isZero()) { + a.words[0] = 0; + a.length = 1; + return a; } - // 24-bits chunks - var off = 0; - var j = 0; + var t = a.imul(b); + var c = t.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m); + var u = t.isub(c).iushrn(this.shift); + var res = u; - var w; - if (endian === 'be') { - for (i = number.length - 1; i >= start; i -= 2) { - w = parseHexByte(number, start, i) << off; - this.words[j] |= w & 0x3ffffff; - if (off >= 18) { - off -= 18; - j += 1; - this.words[j] |= w >>> 26; - } else { - off += 8; - } - } - } else { - var parseLength = number.length - start; - for (i = parseLength % 2 === 0 ? start + 1 : start; i < number.length; i += 2) { - w = parseHexByte(number, start, i) << off; - this.words[j] |= w & 0x3ffffff; - if (off >= 18) { - off -= 18; - j += 1; - this.words[j] |= w >>> 26; - } else { - off += 8; - } - } + if (u.cmp(this.m) >= 0) { + res = u.isub(this.m); + } else if (u.cmpn(0) < 0) { + res = u.iadd(this.m); } - this._strip(); + return res._forceRed(this); }; - function parseBase (str, start, end, mul) { - var r = 0; - var b = 0; - var len = Math.min(str.length, end); - for (var i = start; i < len; i++) { - var c = str.charCodeAt(i) - 48; - - r *= mul; - - // 'a' - if (c >= 49) { - b = c - 49 + 0xa; - - // 'A' - } else if (c >= 17) { - b = c - 17 + 0xa; + Mont.prototype.mul = function mul (a, b) { + if (a.isZero() || b.isZero()) return new BN(0)._forceRed(this); - // '0' - '9' - } else { - b = c; - } - assert(c >= 0 && b < mul, 'Invalid character'); - r += b; + var t = a.mul(b); + var c = t.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m); + var u = t.isub(c).iushrn(this.shift); + var res = u; + if (u.cmp(this.m) >= 0) { + res = u.isub(this.m); + } else if (u.cmpn(0) < 0) { + res = u.iadd(this.m); } - return r; - } - BN.prototype._parseBase = function _parseBase (number, base, start) { - // Initialize as zero - this.words = [0]; - this.length = 1; + return res._forceRed(this); + }; - // Find length of limb in base - for (var limbLen = 0, limbPow = 1; limbPow <= 0x3ffffff; limbPow *= base) { - limbLen++; - } - limbLen--; - limbPow = (limbPow / base) | 0; + Mont.prototype.invm = function invm (a) { + // (AR)^-1 * R^2 = (A^-1 * R^-1) * R^2 = A^-1 * R + var res = this.imod(a._invmp(this.m).mul(this.r2)); + return res._forceRed(this); + }; +})(typeof module === 'undefined' || module, this); - var total = number.length - start; - var mod = total % limbLen; - var end = Math.min(total, total - mod) + start; +},{"buffer":88}],87:[function(require,module,exports){ +var r; - var word = 0; - for (var i = start; i < end; i += limbLen) { - word = parseBase(number, i, i + limbLen, base); +module.exports = function rand(len) { + if (!r) + r = new Rand(null); - this.imuln(limbPow); - if (this.words[0] + word < 0x4000000) { - this.words[0] += word; - } else { - this._iaddn(word); - } - } + return r.generate(len); +}; - if (mod !== 0) { - var pow = 1; - word = parseBase(number, i, number.length, base); +function Rand(rand) { + this.rand = rand; +} +module.exports.Rand = Rand; - for (i = 0; i < mod; i++) { - pow *= base; - } +Rand.prototype.generate = function generate(len) { + return this._rand(len); +}; - this.imuln(pow); - if (this.words[0] + word < 0x4000000) { - this.words[0] += word; - } else { - this._iaddn(word); - } - } +// Emulate crypto API using randy +Rand.prototype._rand = function _rand(n) { + if (this.rand.getBytes) + return this.rand.getBytes(n); - this._strip(); - }; + var res = new Uint8Array(n); + for (var i = 0; i < res.length; i++) + res[i] = this.rand.getByte(); + return res; +}; - BN.prototype.copy = function copy (dest) { - dest.words = new Array(this.length); - for (var i = 0; i < this.length; i++) { - dest.words[i] = this.words[i]; - } - dest.length = this.length; - dest.negative = this.negative; - dest.red = this.red; - }; +if (typeof self === 'object') { + if (self.crypto && self.crypto.getRandomValues) { + // Modern browsers + Rand.prototype._rand = function _rand(n) { + var arr = new Uint8Array(n); + self.crypto.getRandomValues(arr); + return arr; + }; + } else if (self.msCrypto && self.msCrypto.getRandomValues) { + // IE + Rand.prototype._rand = function _rand(n) { + var arr = new Uint8Array(n); + self.msCrypto.getRandomValues(arr); + return arr; + }; - function move (dest, src) { - dest.words = src.words; - dest.length = src.length; - dest.negative = src.negative; - dest.red = src.red; + // Safari's WebWorkers do not have `crypto` + } else if (typeof window === 'object') { + // Old junk + Rand.prototype._rand = function() { + throw new Error('Not implemented yet'); + }; } +} else { + // Node.js or Web worker with no crypto support + try { + var crypto = require('crypto'); + if (typeof crypto.randomBytes !== 'function') + throw new Error('Not supported'); - BN.prototype._move = function _move (dest) { - move(dest, this); - }; + Rand.prototype._rand = function _rand(n) { + return crypto.randomBytes(n); + }; + } catch (e) { + } +} - BN.prototype.clone = function clone () { - var r = new BN(null); - this.copy(r); - return r; - }; +},{"crypto":88}],88:[function(require,module,exports){ - BN.prototype._expand = function _expand (size) { - while (this.length < size) { - this.words[this.length++] = 0; - } - return this; - }; +},{}],89:[function(require,module,exports){ +// based on the aes implimentation in triple sec +// https://github.com/keybase/triplesec +// which is in turn based on the one from crypto-js +// https://code.google.com/p/crypto-js/ - // Remove leading `0` from `this` - BN.prototype._strip = function strip () { - while (this.length > 1 && this.words[this.length - 1] === 0) { - this.length--; - } - return this._normSign(); - }; +var Buffer = require('safe-buffer').Buffer - BN.prototype._normSign = function _normSign () { - // -0 = 0 - if (this.length === 1 && this.words[0] === 0) { - this.negative = 0; - } - return this; - }; +function asUInt32Array (buf) { + if (!Buffer.isBuffer(buf)) buf = Buffer.from(buf) - // Check Symbol.for because not everywhere where Symbol defined - // See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol#Browser_compatibility - if (typeof Symbol !== 'undefined' && typeof Symbol.for === 'function') { - try { - BN.prototype[Symbol.for('nodejs.util.inspect.custom')] = inspect; - } catch (e) { - BN.prototype.inspect = inspect; - } - } else { - BN.prototype.inspect = inspect; - } + var len = (buf.length / 4) | 0 + var out = new Array(len) - function inspect () { - return (this.red ? ''; + for (var i = 0; i < len; i++) { + out[i] = buf.readUInt32BE(i * 4) } - /* - - var zeros = []; - var groupSizes = []; - var groupBases = []; + return out +} - var s = ''; - var i = -1; - while (++i < BN.wordSize) { - zeros[i] = s; - s += '0'; - } - groupSizes[0] = 0; - groupSizes[1] = 0; - groupBases[0] = 0; - groupBases[1] = 0; - var base = 2 - 1; - while (++base < 36 + 1) { - var groupSize = 0; - var groupBase = 1; - while (groupBase < (1 << BN.wordSize) / base) { - groupBase *= base; - groupSize += 1; - } - groupSizes[base] = groupSize; - groupBases[base] = groupBase; +function scrubVec (v) { + for (var i = 0; i < v.length; v++) { + v[i] = 0 } +} - */ +function cryptBlock (M, keySchedule, SUB_MIX, SBOX, nRounds) { + var SUB_MIX0 = SUB_MIX[0] + var SUB_MIX1 = SUB_MIX[1] + var SUB_MIX2 = SUB_MIX[2] + var SUB_MIX3 = SUB_MIX[3] - var zeros = [ - '', - '0', - '00', - '000', - '0000', - '00000', - '000000', - '0000000', - '00000000', - '000000000', - '0000000000', - '00000000000', - '000000000000', - '0000000000000', - '00000000000000', - '000000000000000', - '0000000000000000', - '00000000000000000', - '000000000000000000', - '0000000000000000000', - '00000000000000000000', - '000000000000000000000', - '0000000000000000000000', - '00000000000000000000000', - '000000000000000000000000', - '0000000000000000000000000' - ]; + var s0 = M[0] ^ keySchedule[0] + var s1 = M[1] ^ keySchedule[1] + var s2 = M[2] ^ keySchedule[2] + var s3 = M[3] ^ keySchedule[3] + var t0, t1, t2, t3 + var ksRow = 4 - var groupSizes = [ - 0, 0, - 25, 16, 12, 11, 10, 9, 8, - 8, 7, 7, 7, 7, 6, 6, - 6, 6, 6, 6, 6, 5, 5, - 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5 - ]; + for (var round = 1; round < nRounds; round++) { + t0 = SUB_MIX0[s0 >>> 24] ^ SUB_MIX1[(s1 >>> 16) & 0xff] ^ SUB_MIX2[(s2 >>> 8) & 0xff] ^ SUB_MIX3[s3 & 0xff] ^ keySchedule[ksRow++] + t1 = SUB_MIX0[s1 >>> 24] ^ SUB_MIX1[(s2 >>> 16) & 0xff] ^ SUB_MIX2[(s3 >>> 8) & 0xff] ^ SUB_MIX3[s0 & 0xff] ^ keySchedule[ksRow++] + t2 = SUB_MIX0[s2 >>> 24] ^ SUB_MIX1[(s3 >>> 16) & 0xff] ^ SUB_MIX2[(s0 >>> 8) & 0xff] ^ SUB_MIX3[s1 & 0xff] ^ keySchedule[ksRow++] + t3 = SUB_MIX0[s3 >>> 24] ^ SUB_MIX1[(s0 >>> 16) & 0xff] ^ SUB_MIX2[(s1 >>> 8) & 0xff] ^ SUB_MIX3[s2 & 0xff] ^ keySchedule[ksRow++] + s0 = t0 + s1 = t1 + s2 = t2 + s3 = t3 + } - var groupBases = [ - 0, 0, - 33554432, 43046721, 16777216, 48828125, 60466176, 40353607, 16777216, - 43046721, 10000000, 19487171, 35831808, 62748517, 7529536, 11390625, - 16777216, 24137569, 34012224, 47045881, 64000000, 4084101, 5153632, - 6436343, 7962624, 9765625, 11881376, 14348907, 17210368, 20511149, - 24300000, 28629151, 33554432, 39135393, 45435424, 52521875, 60466176 - ]; + t0 = ((SBOX[s0 >>> 24] << 24) | (SBOX[(s1 >>> 16) & 0xff] << 16) | (SBOX[(s2 >>> 8) & 0xff] << 8) | SBOX[s3 & 0xff]) ^ keySchedule[ksRow++] + t1 = ((SBOX[s1 >>> 24] << 24) | (SBOX[(s2 >>> 16) & 0xff] << 16) | (SBOX[(s3 >>> 8) & 0xff] << 8) | SBOX[s0 & 0xff]) ^ keySchedule[ksRow++] + t2 = ((SBOX[s2 >>> 24] << 24) | (SBOX[(s3 >>> 16) & 0xff] << 16) | (SBOX[(s0 >>> 8) & 0xff] << 8) | SBOX[s1 & 0xff]) ^ keySchedule[ksRow++] + t3 = ((SBOX[s3 >>> 24] << 24) | (SBOX[(s0 >>> 16) & 0xff] << 16) | (SBOX[(s1 >>> 8) & 0xff] << 8) | SBOX[s2 & 0xff]) ^ keySchedule[ksRow++] + t0 = t0 >>> 0 + t1 = t1 >>> 0 + t2 = t2 >>> 0 + t3 = t3 >>> 0 - BN.prototype.toString = function toString (base, padding) { - base = base || 10; - padding = padding | 0 || 1; + return [t0, t1, t2, t3] +} - var out; - if (base === 16 || base === 'hex') { - out = ''; - var off = 0; - var carry = 0; - for (var i = 0; i < this.length; i++) { - var w = this.words[i]; - var word = (((w << off) | carry) & 0xffffff).toString(16); - carry = (w >>> (24 - off)) & 0xffffff; - if (carry !== 0 || i !== this.length - 1) { - out = zeros[6 - word.length] + word + out; - } else { - out = word + out; - } - off += 2; - if (off >= 26) { - off -= 26; - i--; - } - } - if (carry !== 0) { - out = carry.toString(16) + out; - } - while (out.length % padding !== 0) { - out = '0' + out; - } - if (this.negative !== 0) { - out = '-' + out; - } - return out; +// AES constants +var RCON = [0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36] +var G = (function () { + // Compute double table + var d = new Array(256) + for (var j = 0; j < 256; j++) { + if (j < 128) { + d[j] = j << 1 + } else { + d[j] = (j << 1) ^ 0x11b } + } - if (base === (base | 0) && base >= 2 && base <= 36) { - // var groupSize = Math.floor(BN.wordSize * Math.LN2 / Math.log(base)); - var groupSize = groupSizes[base]; - // var groupBase = Math.pow(base, groupSize); - var groupBase = groupBases[base]; - out = ''; - var c = this.clone(); - c.negative = 0; - while (!c.isZero()) { - var r = c.modrn(groupBase).toString(base); - c = c.idivn(groupBase); + var SBOX = [] + var INV_SBOX = [] + var SUB_MIX = [[], [], [], []] + var INV_SUB_MIX = [[], [], [], []] - if (!c.isZero()) { - out = zeros[groupSize - r.length] + r + out; - } else { - out = r + out; - } - } - if (this.isZero()) { - out = '0' + out; - } - while (out.length % padding !== 0) { - out = '0' + out; - } - if (this.negative !== 0) { - out = '-' + out; - } - return out; - } + // Walk GF(2^8) + var x = 0 + var xi = 0 + for (var i = 0; i < 256; ++i) { + // Compute sbox + var sx = xi ^ (xi << 1) ^ (xi << 2) ^ (xi << 3) ^ (xi << 4) + sx = (sx >>> 8) ^ (sx & 0xff) ^ 0x63 + SBOX[x] = sx + INV_SBOX[sx] = x - assert(false, 'Base should be between 2 and 36'); - }; + // Compute multiplication + var x2 = d[x] + var x4 = d[x2] + var x8 = d[x4] - BN.prototype.toNumber = function toNumber () { - var ret = this.words[0]; - if (this.length === 2) { - ret += this.words[1] * 0x4000000; - } else if (this.length === 3 && this.words[2] === 0x01) { - // NOTE: at this stage it is known that the top bit is set - ret += 0x10000000000000 + (this.words[1] * 0x4000000); - } else if (this.length > 2) { - assert(false, 'Number can only safely store up to 53 bits'); - } - return (this.negative !== 0) ? -ret : ret; - }; + // Compute sub bytes, mix columns tables + var t = (d[sx] * 0x101) ^ (sx * 0x1010100) + SUB_MIX[0][x] = (t << 24) | (t >>> 8) + SUB_MIX[1][x] = (t << 16) | (t >>> 16) + SUB_MIX[2][x] = (t << 8) | (t >>> 24) + SUB_MIX[3][x] = t - BN.prototype.toJSON = function toJSON () { - return this.toString(16, 2); - }; + // Compute inv sub bytes, inv mix columns tables + t = (x8 * 0x1010101) ^ (x4 * 0x10001) ^ (x2 * 0x101) ^ (x * 0x1010100) + INV_SUB_MIX[0][sx] = (t << 24) | (t >>> 8) + INV_SUB_MIX[1][sx] = (t << 16) | (t >>> 16) + INV_SUB_MIX[2][sx] = (t << 8) | (t >>> 24) + INV_SUB_MIX[3][sx] = t - if (Buffer) { - BN.prototype.toBuffer = function toBuffer (endian, length) { - return this.toArrayLike(Buffer, endian, length); - }; + if (x === 0) { + x = xi = 1 + } else { + x = x2 ^ d[d[d[x8 ^ x2]]] + xi ^= d[d[xi]] + } } - BN.prototype.toArray = function toArray (endian, length) { - return this.toArrayLike(Array, endian, length); - }; + return { + SBOX: SBOX, + INV_SBOX: INV_SBOX, + SUB_MIX: SUB_MIX, + INV_SUB_MIX: INV_SUB_MIX + } +})() - var allocate = function allocate (ArrayType, size) { - if (ArrayType.allocUnsafe) { - return ArrayType.allocUnsafe(size); - } - return new ArrayType(size); - }; +function AES (key) { + this._key = asUInt32Array(key) + this._reset() +} - BN.prototype.toArrayLike = function toArrayLike (ArrayType, endian, length) { - this._strip(); +AES.blockSize = 4 * 4 +AES.keySize = 256 / 8 +AES.prototype.blockSize = AES.blockSize +AES.prototype.keySize = AES.keySize +AES.prototype._reset = function () { + var keyWords = this._key + var keySize = keyWords.length + var nRounds = keySize + 6 + var ksRows = (nRounds + 1) * 4 - var byteLength = this.byteLength(); - var reqLength = length || Math.max(1, byteLength); - assert(byteLength <= reqLength, 'byte array longer than desired length'); - assert(reqLength > 0, 'Requested array length <= 0'); + var keySchedule = [] + for (var k = 0; k < keySize; k++) { + keySchedule[k] = keyWords[k] + } - var res = allocate(ArrayType, reqLength); - var postfix = endian === 'le' ? 'LE' : 'BE'; - this['_toArrayLike' + postfix](res, byteLength); - return res; - }; + for (k = keySize; k < ksRows; k++) { + var t = keySchedule[k - 1] - BN.prototype._toArrayLikeLE = function _toArrayLikeLE (res, byteLength) { - var position = 0; - var carry = 0; + if (k % keySize === 0) { + t = (t << 8) | (t >>> 24) + t = + (G.SBOX[t >>> 24] << 24) | + (G.SBOX[(t >>> 16) & 0xff] << 16) | + (G.SBOX[(t >>> 8) & 0xff] << 8) | + (G.SBOX[t & 0xff]) - for (var i = 0, shift = 0; i < this.length; i++) { - var word = (this.words[i] << shift) | carry; + t ^= RCON[(k / keySize) | 0] << 24 + } else if (keySize > 6 && k % keySize === 4) { + t = + (G.SBOX[t >>> 24] << 24) | + (G.SBOX[(t >>> 16) & 0xff] << 16) | + (G.SBOX[(t >>> 8) & 0xff] << 8) | + (G.SBOX[t & 0xff]) + } - res[position++] = word & 0xff; - if (position < res.length) { - res[position++] = (word >> 8) & 0xff; - } - if (position < res.length) { - res[position++] = (word >> 16) & 0xff; - } + keySchedule[k] = keySchedule[k - keySize] ^ t + } - if (shift === 6) { - if (position < res.length) { - res[position++] = (word >> 24) & 0xff; - } - carry = 0; - shift = 0; - } else { - carry = word >>> 24; - shift += 2; - } + var invKeySchedule = [] + for (var ik = 0; ik < ksRows; ik++) { + var ksR = ksRows - ik + var tt = keySchedule[ksR - (ik % 4 ? 0 : 4)] + + if (ik < 4 || ksR <= 4) { + invKeySchedule[ik] = tt + } else { + invKeySchedule[ik] = + G.INV_SUB_MIX[0][G.SBOX[tt >>> 24]] ^ + G.INV_SUB_MIX[1][G.SBOX[(tt >>> 16) & 0xff]] ^ + G.INV_SUB_MIX[2][G.SBOX[(tt >>> 8) & 0xff]] ^ + G.INV_SUB_MIX[3][G.SBOX[tt & 0xff]] } + } - if (position < res.length) { - res[position++] = carry; + this._nRounds = nRounds + this._keySchedule = keySchedule + this._invKeySchedule = invKeySchedule +} - while (position < res.length) { - res[position++] = 0; - } - } - }; +AES.prototype.encryptBlockRaw = function (M) { + M = asUInt32Array(M) + return cryptBlock(M, this._keySchedule, G.SUB_MIX, G.SBOX, this._nRounds) +} - BN.prototype._toArrayLikeBE = function _toArrayLikeBE (res, byteLength) { - var position = res.length - 1; - var carry = 0; +AES.prototype.encryptBlock = function (M) { + var out = this.encryptBlockRaw(M) + var buf = Buffer.allocUnsafe(16) + buf.writeUInt32BE(out[0], 0) + buf.writeUInt32BE(out[1], 4) + buf.writeUInt32BE(out[2], 8) + buf.writeUInt32BE(out[3], 12) + return buf +} - for (var i = 0, shift = 0; i < this.length; i++) { - var word = (this.words[i] << shift) | carry; +AES.prototype.decryptBlock = function (M) { + M = asUInt32Array(M) - res[position--] = word & 0xff; - if (position >= 0) { - res[position--] = (word >> 8) & 0xff; - } - if (position >= 0) { - res[position--] = (word >> 16) & 0xff; - } + // swap + var m1 = M[1] + M[1] = M[3] + M[3] = m1 - if (shift === 6) { - if (position >= 0) { - res[position--] = (word >> 24) & 0xff; - } - carry = 0; - shift = 0; - } else { - carry = word >>> 24; - shift += 2; - } - } + var out = cryptBlock(M, this._invKeySchedule, G.INV_SUB_MIX, G.INV_SBOX, this._nRounds) + var buf = Buffer.allocUnsafe(16) + buf.writeUInt32BE(out[0], 0) + buf.writeUInt32BE(out[3], 4) + buf.writeUInt32BE(out[2], 8) + buf.writeUInt32BE(out[1], 12) + return buf +} - if (position >= 0) { - res[position--] = carry; +AES.prototype.scrub = function () { + scrubVec(this._keySchedule) + scrubVec(this._invKeySchedule) + scrubVec(this._key) +} - while (position >= 0) { - res[position--] = 0; - } - } - }; +module.exports.AES = AES - if (Math.clz32) { - BN.prototype._countBits = function _countBits (w) { - return 32 - Math.clz32(w); - }; - } else { - BN.prototype._countBits = function _countBits (w) { - var t = w; - var r = 0; - if (t >= 0x1000) { - r += 13; - t >>>= 13; - } - if (t >= 0x40) { - r += 7; - t >>>= 7; - } - if (t >= 0x8) { - r += 4; - t >>>= 4; - } - if (t >= 0x02) { - r += 2; - t >>>= 2; - } - return r + t; - }; +},{"safe-buffer":390}],90:[function(require,module,exports){ +var aes = require('./aes') +var Buffer = require('safe-buffer').Buffer +var Transform = require('cipher-base') +var inherits = require('inherits') +var GHASH = require('./ghash') +var xor = require('buffer-xor') +var incr32 = require('./incr32') + +function xorTest (a, b) { + var out = 0 + if (a.length !== b.length) out++ + + var len = Math.min(a.length, b.length) + for (var i = 0; i < len; ++i) { + out += (a[i] ^ b[i]) } - BN.prototype._zeroBits = function _zeroBits (w) { - // Short-cut - if (w === 0) return 26; + return out +} - var t = w; - var r = 0; - if ((t & 0x1fff) === 0) { - r += 13; - t >>>= 13; - } - if ((t & 0x7f) === 0) { - r += 7; - t >>>= 7; - } - if ((t & 0xf) === 0) { - r += 4; - t >>>= 4; - } - if ((t & 0x3) === 0) { - r += 2; - t >>>= 2; - } - if ((t & 0x1) === 0) { - r++; - } - return r; - }; +function calcIv (self, iv, ck) { + if (iv.length === 12) { + self._finID = Buffer.concat([iv, Buffer.from([0, 0, 0, 1])]) + return Buffer.concat([iv, Buffer.from([0, 0, 0, 2])]) + } + var ghash = new GHASH(ck) + var len = iv.length + var toPad = len % 16 + ghash.update(iv) + if (toPad) { + toPad = 16 - toPad + ghash.update(Buffer.alloc(toPad, 0)) + } + ghash.update(Buffer.alloc(8, 0)) + var ivBits = len * 8 + var tail = Buffer.alloc(8) + tail.writeUIntBE(ivBits, 0, 8) + ghash.update(tail) + self._finID = ghash.state + var out = Buffer.from(self._finID) + incr32(out) + return out +} +function StreamCipher (mode, key, iv, decrypt) { + Transform.call(this) - // Return number of used bits in a BN - BN.prototype.bitLength = function bitLength () { - var w = this.words[this.length - 1]; - var hi = this._countBits(w); - return (this.length - 1) * 26 + hi; - }; + var h = Buffer.alloc(4, 0) - function toBitArray (num) { - var w = new Array(num.bitLength()); + this._cipher = new aes.AES(key) + var ck = this._cipher.encryptBlock(h) + this._ghash = new GHASH(ck) + iv = calcIv(this, iv, ck) - for (var bit = 0; bit < w.length; bit++) { - var off = (bit / 26) | 0; - var wbit = bit % 26; + this._prev = Buffer.from(iv) + this._cache = Buffer.allocUnsafe(0) + this._secCache = Buffer.allocUnsafe(0) + this._decrypt = decrypt + this._alen = 0 + this._len = 0 + this._mode = mode - w[bit] = (num.words[off] >>> wbit) & 0x01; + this._authTag = null + this._called = false +} + +inherits(StreamCipher, Transform) + +StreamCipher.prototype._update = function (chunk) { + if (!this._called && this._alen) { + var rump = 16 - (this._alen % 16) + if (rump < 16) { + rump = Buffer.alloc(rump, 0) + this._ghash.update(rump) } + } - return w; + this._called = true + var out = this._mode.encrypt(this, chunk) + if (this._decrypt) { + this._ghash.update(chunk) + } else { + this._ghash.update(out) } + this._len += chunk.length + return out +} - // Number of trailing zero bits - BN.prototype.zeroBits = function zeroBits () { - if (this.isZero()) return 0; +StreamCipher.prototype._final = function () { + if (this._decrypt && !this._authTag) throw new Error('Unsupported state or unable to authenticate data') - var r = 0; - for (var i = 0; i < this.length; i++) { - var b = this._zeroBits(this.words[i]); - r += b; - if (b !== 26) break; - } - return r; - }; + var tag = xor(this._ghash.final(this._alen * 8, this._len * 8), this._cipher.encryptBlock(this._finID)) + if (this._decrypt && xorTest(tag, this._authTag)) throw new Error('Unsupported state or unable to authenticate data') - BN.prototype.byteLength = function byteLength () { - return Math.ceil(this.bitLength() / 8); - }; + this._authTag = tag + this._cipher.scrub() +} - BN.prototype.toTwos = function toTwos (width) { - if (this.negative !== 0) { - return this.abs().inotn(width).iaddn(1); - } - return this.clone(); - }; +StreamCipher.prototype.getAuthTag = function getAuthTag () { + if (this._decrypt || !Buffer.isBuffer(this._authTag)) throw new Error('Attempting to get auth tag in unsupported state') - BN.prototype.fromTwos = function fromTwos (width) { - if (this.testn(width - 1)) { - return this.notn(width).iaddn(1).ineg(); - } - return this.clone(); - }; + return this._authTag +} - BN.prototype.isNeg = function isNeg () { - return this.negative !== 0; - }; +StreamCipher.prototype.setAuthTag = function setAuthTag (tag) { + if (!this._decrypt) throw new Error('Attempting to set auth tag in unsupported state') - // Return negative clone of `this` - BN.prototype.neg = function neg () { - return this.clone().ineg(); - }; + this._authTag = tag +} - BN.prototype.ineg = function ineg () { - if (!this.isZero()) { - this.negative ^= 1; - } +StreamCipher.prototype.setAAD = function setAAD (buf) { + if (this._called) throw new Error('Attempting to set AAD in unsupported state') - return this; - }; + this._ghash.update(buf) + this._alen += buf.length +} - // Or `num` with `this` in-place - BN.prototype.iuor = function iuor (num) { - while (this.length < num.length) { - this.words[this.length++] = 0; - } +module.exports = StreamCipher - for (var i = 0; i < num.length; i++) { - this.words[i] = this.words[i] | num.words[i]; - } +},{"./aes":89,"./ghash":94,"./incr32":95,"buffer-xor":119,"cipher-base":124,"inherits":200,"safe-buffer":390}],91:[function(require,module,exports){ +var ciphers = require('./encrypter') +var deciphers = require('./decrypter') +var modes = require('./modes/list.json') - return this._strip(); - }; +function getCiphers () { + return Object.keys(modes) +} - BN.prototype.ior = function ior (num) { - assert((this.negative | num.negative) === 0); - return this.iuor(num); - }; +exports.createCipher = exports.Cipher = ciphers.createCipher +exports.createCipheriv = exports.Cipheriv = ciphers.createCipheriv +exports.createDecipher = exports.Decipher = deciphers.createDecipher +exports.createDecipheriv = exports.Decipheriv = deciphers.createDecipheriv +exports.listCiphers = exports.getCiphers = getCiphers - // Or `num` with `this` - BN.prototype.or = function or (num) { - if (this.length > num.length) return this.clone().ior(num); - return num.clone().ior(this); - }; +},{"./decrypter":92,"./encrypter":93,"./modes/list.json":103}],92:[function(require,module,exports){ +var AuthCipher = require('./authCipher') +var Buffer = require('safe-buffer').Buffer +var MODES = require('./modes') +var StreamCipher = require('./streamCipher') +var Transform = require('cipher-base') +var aes = require('./aes') +var ebtk = require('evp_bytestokey') +var inherits = require('inherits') - BN.prototype.uor = function uor (num) { - if (this.length > num.length) return this.clone().iuor(num); - return num.clone().iuor(this); - }; +function Decipher (mode, key, iv) { + Transform.call(this) - // And `num` with `this` in-place - BN.prototype.iuand = function iuand (num) { - // b = min-length(num, this) - var b; - if (this.length > num.length) { - b = num; - } else { - b = this; - } + this._cache = new Splitter() + this._last = void 0 + this._cipher = new aes.AES(key) + this._prev = Buffer.from(iv) + this._mode = mode + this._autopadding = true +} - for (var i = 0; i < b.length; i++) { - this.words[i] = this.words[i] & num.words[i]; - } +inherits(Decipher, Transform) - this.length = b.length; +Decipher.prototype._update = function (data) { + this._cache.add(data) + var chunk + var thing + var out = [] + while ((chunk = this._cache.get(this._autopadding))) { + thing = this._mode.decrypt(this, chunk) + out.push(thing) + } + return Buffer.concat(out) +} - return this._strip(); - }; +Decipher.prototype._final = function () { + var chunk = this._cache.flush() + if (this._autopadding) { + return unpad(this._mode.decrypt(this, chunk)) + } else if (chunk) { + throw new Error('data not multiple of block length') + } +} - BN.prototype.iand = function iand (num) { - assert((this.negative | num.negative) === 0); - return this.iuand(num); - }; +Decipher.prototype.setAutoPadding = function (setTo) { + this._autopadding = !!setTo + return this +} - // And `num` with `this` - BN.prototype.and = function and (num) { - if (this.length > num.length) return this.clone().iand(num); - return num.clone().iand(this); - }; +function Splitter () { + this.cache = Buffer.allocUnsafe(0) +} - BN.prototype.uand = function uand (num) { - if (this.length > num.length) return this.clone().iuand(num); - return num.clone().iuand(this); - }; +Splitter.prototype.add = function (data) { + this.cache = Buffer.concat([this.cache, data]) +} - // Xor `num` with `this` in-place - BN.prototype.iuxor = function iuxor (num) { - // a.length > b.length - var a; - var b; - if (this.length > num.length) { - a = this; - b = num; - } else { - a = num; - b = this; +Splitter.prototype.get = function (autoPadding) { + var out + if (autoPadding) { + if (this.cache.length > 16) { + out = this.cache.slice(0, 16) + this.cache = this.cache.slice(16) + return out } - - for (var i = 0; i < b.length; i++) { - this.words[i] = a.words[i] ^ b.words[i]; + } else { + if (this.cache.length >= 16) { + out = this.cache.slice(0, 16) + this.cache = this.cache.slice(16) + return out } + } - if (this !== a) { - for (; i < a.length; i++) { - this.words[i] = a.words[i]; - } - } + return null +} - this.length = a.length; +Splitter.prototype.flush = function () { + if (this.cache.length) return this.cache +} - return this._strip(); - }; +function unpad (last) { + var padded = last[15] + if (padded < 1 || padded > 16) { + throw new Error('unable to decrypt data') + } + var i = -1 + while (++i < padded) { + if (last[(i + (16 - padded))] !== padded) { + throw new Error('unable to decrypt data') + } + } + if (padded === 16) return - BN.prototype.ixor = function ixor (num) { - assert((this.negative | num.negative) === 0); - return this.iuxor(num); - }; + return last.slice(0, 16 - padded) +} - // Xor `num` with `this` - BN.prototype.xor = function xor (num) { - if (this.length > num.length) return this.clone().ixor(num); - return num.clone().ixor(this); - }; +function createDecipheriv (suite, password, iv) { + var config = MODES[suite.toLowerCase()] + if (!config) throw new TypeError('invalid suite type') - BN.prototype.uxor = function uxor (num) { - if (this.length > num.length) return this.clone().iuxor(num); - return num.clone().iuxor(this); - }; + if (typeof iv === 'string') iv = Buffer.from(iv) + if (config.mode !== 'GCM' && iv.length !== config.iv) throw new TypeError('invalid iv length ' + iv.length) - // Not ``this`` with ``width`` bitwidth - BN.prototype.inotn = function inotn (width) { - assert(typeof width === 'number' && width >= 0); + if (typeof password === 'string') password = Buffer.from(password) + if (password.length !== config.key / 8) throw new TypeError('invalid key length ' + password.length) - var bytesNeeded = Math.ceil(width / 26) | 0; - var bitsLeft = width % 26; + if (config.type === 'stream') { + return new StreamCipher(config.module, password, iv, true) + } else if (config.type === 'auth') { + return new AuthCipher(config.module, password, iv, true) + } - // Extend the buffer with leading zeroes - this._expand(bytesNeeded); + return new Decipher(config.module, password, iv) +} - if (bitsLeft > 0) { - bytesNeeded--; - } +function createDecipher (suite, password) { + var config = MODES[suite.toLowerCase()] + if (!config) throw new TypeError('invalid suite type') - // Handle complete words - for (var i = 0; i < bytesNeeded; i++) { - this.words[i] = ~this.words[i] & 0x3ffffff; - } + var keys = ebtk(password, false, config.key, config.iv) + return createDecipheriv(suite, keys.key, keys.iv) +} - // Handle the residue - if (bitsLeft > 0) { - this.words[i] = ~this.words[i] & (0x3ffffff >> (26 - bitsLeft)); - } +exports.createDecipher = createDecipher +exports.createDecipheriv = createDecipheriv - // And remove leading zeroes - return this._strip(); - }; +},{"./aes":89,"./authCipher":90,"./modes":102,"./streamCipher":105,"cipher-base":124,"evp_bytestokey":173,"inherits":200,"safe-buffer":390}],93:[function(require,module,exports){ +var MODES = require('./modes') +var AuthCipher = require('./authCipher') +var Buffer = require('safe-buffer').Buffer +var StreamCipher = require('./streamCipher') +var Transform = require('cipher-base') +var aes = require('./aes') +var ebtk = require('evp_bytestokey') +var inherits = require('inherits') - BN.prototype.notn = function notn (width) { - return this.clone().inotn(width); - }; +function Cipher (mode, key, iv) { + Transform.call(this) - // Set `bit` of `this` - BN.prototype.setn = function setn (bit, val) { - assert(typeof bit === 'number' && bit >= 0); + this._cache = new Splitter() + this._cipher = new aes.AES(key) + this._prev = Buffer.from(iv) + this._mode = mode + this._autopadding = true +} - var off = (bit / 26) | 0; - var wbit = bit % 26; +inherits(Cipher, Transform) - this._expand(off + 1); +Cipher.prototype._update = function (data) { + this._cache.add(data) + var chunk + var thing + var out = [] - if (val) { - this.words[off] = this.words[off] | (1 << wbit); - } else { - this.words[off] = this.words[off] & ~(1 << wbit); - } + while ((chunk = this._cache.get())) { + thing = this._mode.encrypt(this, chunk) + out.push(thing) + } - return this._strip(); - }; + return Buffer.concat(out) +} - // Add `num` to `this` in-place - BN.prototype.iadd = function iadd (num) { - var r; +var PADDING = Buffer.alloc(16, 0x10) - // negative + positive - if (this.negative !== 0 && num.negative === 0) { - this.negative = 0; - r = this.isub(num); - this.negative ^= 1; - return this._normSign(); +Cipher.prototype._final = function () { + var chunk = this._cache.flush() + if (this._autopadding) { + chunk = this._mode.encrypt(this, chunk) + this._cipher.scrub() + return chunk + } - // positive + negative - } else if (this.negative === 0 && num.negative !== 0) { - num.negative = 0; - r = this.isub(num); - num.negative = 1; - return r._normSign(); - } + if (!chunk.equals(PADDING)) { + this._cipher.scrub() + throw new Error('data not multiple of block length') + } +} - // a.length > b.length - var a, b; - if (this.length > num.length) { - a = this; - b = num; - } else { - a = num; - b = this; - } +Cipher.prototype.setAutoPadding = function (setTo) { + this._autopadding = !!setTo + return this +} - var carry = 0; - for (var i = 0; i < b.length; i++) { - r = (a.words[i] | 0) + (b.words[i] | 0) + carry; - this.words[i] = r & 0x3ffffff; - carry = r >>> 26; - } - for (; carry !== 0 && i < a.length; i++) { - r = (a.words[i] | 0) + carry; - this.words[i] = r & 0x3ffffff; - carry = r >>> 26; - } +function Splitter () { + this.cache = Buffer.allocUnsafe(0) +} - this.length = a.length; - if (carry !== 0) { - this.words[this.length] = carry; - this.length++; - // Copy the rest of the words - } else if (a !== this) { - for (; i < a.length; i++) { - this.words[i] = a.words[i]; - } - } +Splitter.prototype.add = function (data) { + this.cache = Buffer.concat([this.cache, data]) +} - return this; - }; +Splitter.prototype.get = function () { + if (this.cache.length > 15) { + var out = this.cache.slice(0, 16) + this.cache = this.cache.slice(16) + return out + } + return null +} - // Add `num` to `this` - BN.prototype.add = function add (num) { - var res; - if (num.negative !== 0 && this.negative === 0) { - num.negative = 0; - res = this.sub(num); - num.negative ^= 1; - return res; - } else if (num.negative === 0 && this.negative !== 0) { - this.negative = 0; - res = num.sub(this); - this.negative = 1; - return res; - } +Splitter.prototype.flush = function () { + var len = 16 - this.cache.length + var padBuff = Buffer.allocUnsafe(len) - if (this.length > num.length) return this.clone().iadd(num); + var i = -1 + while (++i < len) { + padBuff.writeUInt8(len, i) + } - return num.clone().iadd(this); - }; + return Buffer.concat([this.cache, padBuff]) +} - // Subtract `num` from `this` in-place - BN.prototype.isub = function isub (num) { - // this - (-num) = this + num - if (num.negative !== 0) { - num.negative = 0; - var r = this.iadd(num); - num.negative = 1; - return r._normSign(); +function createCipheriv (suite, password, iv) { + var config = MODES[suite.toLowerCase()] + if (!config) throw new TypeError('invalid suite type') - // -this - num = -(this + num) - } else if (this.negative !== 0) { - this.negative = 0; - this.iadd(num); - this.negative = 1; - return this._normSign(); - } + if (typeof password === 'string') password = Buffer.from(password) + if (password.length !== config.key / 8) throw new TypeError('invalid key length ' + password.length) - // At this point both numbers are positive - var cmp = this.cmp(num); + if (typeof iv === 'string') iv = Buffer.from(iv) + if (config.mode !== 'GCM' && iv.length !== config.iv) throw new TypeError('invalid iv length ' + iv.length) - // Optimization - zeroify - if (cmp === 0) { - this.negative = 0; - this.length = 1; - this.words[0] = 0; - return this; - } + if (config.type === 'stream') { + return new StreamCipher(config.module, password, iv) + } else if (config.type === 'auth') { + return new AuthCipher(config.module, password, iv) + } - // a > b - var a, b; - if (cmp > 0) { - a = this; - b = num; - } else { - a = num; - b = this; - } + return new Cipher(config.module, password, iv) +} - var carry = 0; - for (var i = 0; i < b.length; i++) { - r = (a.words[i] | 0) - (b.words[i] | 0) + carry; - carry = r >> 26; - this.words[i] = r & 0x3ffffff; +function createCipher (suite, password) { + var config = MODES[suite.toLowerCase()] + if (!config) throw new TypeError('invalid suite type') + + var keys = ebtk(password, false, config.key, config.iv) + return createCipheriv(suite, keys.key, keys.iv) +} + +exports.createCipheriv = createCipheriv +exports.createCipher = createCipher + +},{"./aes":89,"./authCipher":90,"./modes":102,"./streamCipher":105,"cipher-base":124,"evp_bytestokey":173,"inherits":200,"safe-buffer":390}],94:[function(require,module,exports){ +var Buffer = require('safe-buffer').Buffer +var ZEROES = Buffer.alloc(16, 0) + +function toArray (buf) { + return [ + buf.readUInt32BE(0), + buf.readUInt32BE(4), + buf.readUInt32BE(8), + buf.readUInt32BE(12) + ] +} + +function fromArray (out) { + var buf = Buffer.allocUnsafe(16) + buf.writeUInt32BE(out[0] >>> 0, 0) + buf.writeUInt32BE(out[1] >>> 0, 4) + buf.writeUInt32BE(out[2] >>> 0, 8) + buf.writeUInt32BE(out[3] >>> 0, 12) + return buf +} + +function GHASH (key) { + this.h = key + this.state = Buffer.alloc(16, 0) + this.cache = Buffer.allocUnsafe(0) +} + +// from http://bitwiseshiftleft.github.io/sjcl/doc/symbols/src/core_gcm.js.html +// by Juho Vähä-Herttua +GHASH.prototype.ghash = function (block) { + var i = -1 + while (++i < block.length) { + this.state[i] ^= block[i] + } + this._multiply() +} + +GHASH.prototype._multiply = function () { + var Vi = toArray(this.h) + var Zi = [0, 0, 0, 0] + var j, xi, lsbVi + var i = -1 + while (++i < 128) { + xi = (this.state[~~(i / 8)] & (1 << (7 - (i % 8)))) !== 0 + if (xi) { + // Z_i+1 = Z_i ^ V_i + Zi[0] ^= Vi[0] + Zi[1] ^= Vi[1] + Zi[2] ^= Vi[2] + Zi[3] ^= Vi[3] } - for (; carry !== 0 && i < a.length; i++) { - r = (a.words[i] | 0) + carry; - carry = r >> 26; - this.words[i] = r & 0x3ffffff; + + // Store the value of LSB(V_i) + lsbVi = (Vi[3] & 1) !== 0 + + // V_i+1 = V_i >> 1 + for (j = 3; j > 0; j--) { + Vi[j] = (Vi[j] >>> 1) | ((Vi[j - 1] & 1) << 31) } + Vi[0] = Vi[0] >>> 1 - // Copy rest of the words - if (carry === 0 && i < a.length && a !== this) { - for (; i < a.length; i++) { - this.words[i] = a.words[i]; - } + // If LSB(V_i) is 1, V_i+1 = (V_i >> 1) ^ R + if (lsbVi) { + Vi[0] = Vi[0] ^ (0xe1 << 24) } + } + this.state = fromArray(Zi) +} - this.length = Math.max(this.length, i); +GHASH.prototype.update = function (buf) { + this.cache = Buffer.concat([this.cache, buf]) + var chunk + while (this.cache.length >= 16) { + chunk = this.cache.slice(0, 16) + this.cache = this.cache.slice(16) + this.ghash(chunk) + } +} - if (a !== this) { - this.negative = 1; +GHASH.prototype.final = function (abl, bl) { + if (this.cache.length) { + this.ghash(Buffer.concat([this.cache, ZEROES], 16)) + } + + this.ghash(fromArray([0, abl, 0, bl])) + return this.state +} + +module.exports = GHASH + +},{"safe-buffer":390}],95:[function(require,module,exports){ +function incr32 (iv) { + var len = iv.length + var item + while (len--) { + item = iv.readUInt8(len) + if (item === 255) { + iv.writeUInt8(0, len) + } else { + item++ + iv.writeUInt8(item, len) + break } + } +} +module.exports = incr32 - return this._strip(); - }; +},{}],96:[function(require,module,exports){ +var xor = require('buffer-xor') - // Subtract `num` from `this` - BN.prototype.sub = function sub (num) { - return this.clone().isub(num); - }; +exports.encrypt = function (self, block) { + var data = xor(block, self._prev) - function smallMulTo (self, num, out) { - out.negative = num.negative ^ self.negative; - var len = (self.length + num.length) | 0; - out.length = len; - len = (len - 1) | 0; + self._prev = self._cipher.encryptBlock(data) + return self._prev +} - // Peel one iteration (compiler can't do it, because of code complexity) - var a = self.words[0] | 0; - var b = num.words[0] | 0; - var r = a * b; +exports.decrypt = function (self, block) { + var pad = self._prev - var lo = r & 0x3ffffff; - var carry = (r / 0x4000000) | 0; - out.words[0] = lo; + self._prev = block + var out = self._cipher.decryptBlock(block) - for (var k = 1; k < len; k++) { - // Sum all words with the same `i + j = k` and accumulate `ncarry`, - // note that ncarry could be >= 0x3ffffff - var ncarry = carry >>> 26; - var rword = carry & 0x3ffffff; - var maxJ = Math.min(k, num.length - 1); - for (var j = Math.max(0, k - self.length + 1); j <= maxJ; j++) { - var i = (k - j) | 0; - a = self.words[i] | 0; - b = num.words[j] | 0; - r = a * b + rword; - ncarry += (r / 0x4000000) | 0; - rword = r & 0x3ffffff; - } - out.words[k] = rword | 0; - carry = ncarry | 0; + return xor(out, pad) +} + +},{"buffer-xor":119}],97:[function(require,module,exports){ +var Buffer = require('safe-buffer').Buffer +var xor = require('buffer-xor') + +function encryptStart (self, data, decrypt) { + var len = data.length + var out = xor(data, self._cache) + self._cache = self._cache.slice(len) + self._prev = Buffer.concat([self._prev, decrypt ? data : out]) + return out +} + +exports.encrypt = function (self, data, decrypt) { + var out = Buffer.allocUnsafe(0) + var len + + while (data.length) { + if (self._cache.length === 0) { + self._cache = self._cipher.encryptBlock(self._prev) + self._prev = Buffer.allocUnsafe(0) } - if (carry !== 0) { - out.words[k] = carry | 0; + + if (self._cache.length <= data.length) { + len = self._cache.length + out = Buffer.concat([out, encryptStart(self, data.slice(0, len), decrypt)]) + data = data.slice(len) } else { - out.length--; + out = Buffer.concat([out, encryptStart(self, data, decrypt)]) + break } + } - return out._strip(); + return out +} + +},{"buffer-xor":119,"safe-buffer":390}],98:[function(require,module,exports){ +var Buffer = require('safe-buffer').Buffer + +function encryptByte (self, byteParam, decrypt) { + var pad + var i = -1 + var len = 8 + var out = 0 + var bit, value + while (++i < len) { + pad = self._cipher.encryptBlock(self._prev) + bit = (byteParam & (1 << (7 - i))) ? 0x80 : 0 + value = pad[0] ^ bit + out += ((value & 0x80) >> (i % 8)) + self._prev = shiftIn(self._prev, decrypt ? bit : value) } + return out +} - // TODO(indutny): it may be reasonable to omit it for users who don't need - // to work with 256-bit numbers, otherwise it gives 20% improvement for 256-bit - // multiplication (like elliptic secp256k1). - var comb10MulTo = function comb10MulTo (self, num, out) { - var a = self.words; - var b = num.words; - var o = out.words; - var c = 0; - var lo; - var mid; - var hi; - var a0 = a[0] | 0; - var al0 = a0 & 0x1fff; - var ah0 = a0 >>> 13; - var a1 = a[1] | 0; - var al1 = a1 & 0x1fff; - var ah1 = a1 >>> 13; - var a2 = a[2] | 0; - var al2 = a2 & 0x1fff; - var ah2 = a2 >>> 13; - var a3 = a[3] | 0; - var al3 = a3 & 0x1fff; - var ah3 = a3 >>> 13; - var a4 = a[4] | 0; - var al4 = a4 & 0x1fff; - var ah4 = a4 >>> 13; - var a5 = a[5] | 0; - var al5 = a5 & 0x1fff; - var ah5 = a5 >>> 13; - var a6 = a[6] | 0; - var al6 = a6 & 0x1fff; - var ah6 = a6 >>> 13; - var a7 = a[7] | 0; - var al7 = a7 & 0x1fff; - var ah7 = a7 >>> 13; - var a8 = a[8] | 0; - var al8 = a8 & 0x1fff; - var ah8 = a8 >>> 13; - var a9 = a[9] | 0; - var al9 = a9 & 0x1fff; - var ah9 = a9 >>> 13; - var b0 = b[0] | 0; - var bl0 = b0 & 0x1fff; - var bh0 = b0 >>> 13; - var b1 = b[1] | 0; - var bl1 = b1 & 0x1fff; - var bh1 = b1 >>> 13; - var b2 = b[2] | 0; - var bl2 = b2 & 0x1fff; - var bh2 = b2 >>> 13; - var b3 = b[3] | 0; - var bl3 = b3 & 0x1fff; - var bh3 = b3 >>> 13; - var b4 = b[4] | 0; - var bl4 = b4 & 0x1fff; - var bh4 = b4 >>> 13; - var b5 = b[5] | 0; - var bl5 = b5 & 0x1fff; - var bh5 = b5 >>> 13; - var b6 = b[6] | 0; - var bl6 = b6 & 0x1fff; - var bh6 = b6 >>> 13; - var b7 = b[7] | 0; - var bl7 = b7 & 0x1fff; - var bh7 = b7 >>> 13; - var b8 = b[8] | 0; - var bl8 = b8 & 0x1fff; - var bh8 = b8 >>> 13; - var b9 = b[9] | 0; - var bl9 = b9 & 0x1fff; - var bh9 = b9 >>> 13; +function shiftIn (buffer, value) { + var len = buffer.length + var i = -1 + var out = Buffer.allocUnsafe(buffer.length) + buffer = Buffer.concat([buffer, Buffer.from([value])]) - out.negative = self.negative ^ num.negative; - out.length = 19; - /* k = 0 */ - lo = Math.imul(al0, bl0); - mid = Math.imul(al0, bh0); - mid = (mid + Math.imul(ah0, bl0)) | 0; - hi = Math.imul(ah0, bh0); - var w0 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w0 >>> 26)) | 0; - w0 &= 0x3ffffff; - /* k = 1 */ - lo = Math.imul(al1, bl0); - mid = Math.imul(al1, bh0); - mid = (mid + Math.imul(ah1, bl0)) | 0; - hi = Math.imul(ah1, bh0); - lo = (lo + Math.imul(al0, bl1)) | 0; - mid = (mid + Math.imul(al0, bh1)) | 0; - mid = (mid + Math.imul(ah0, bl1)) | 0; - hi = (hi + Math.imul(ah0, bh1)) | 0; - var w1 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w1 >>> 26)) | 0; - w1 &= 0x3ffffff; - /* k = 2 */ - lo = Math.imul(al2, bl0); - mid = Math.imul(al2, bh0); - mid = (mid + Math.imul(ah2, bl0)) | 0; - hi = Math.imul(ah2, bh0); - lo = (lo + Math.imul(al1, bl1)) | 0; - mid = (mid + Math.imul(al1, bh1)) | 0; - mid = (mid + Math.imul(ah1, bl1)) | 0; - hi = (hi + Math.imul(ah1, bh1)) | 0; - lo = (lo + Math.imul(al0, bl2)) | 0; - mid = (mid + Math.imul(al0, bh2)) | 0; - mid = (mid + Math.imul(ah0, bl2)) | 0; - hi = (hi + Math.imul(ah0, bh2)) | 0; - var w2 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w2 >>> 26)) | 0; - w2 &= 0x3ffffff; - /* k = 3 */ - lo = Math.imul(al3, bl0); - mid = Math.imul(al3, bh0); - mid = (mid + Math.imul(ah3, bl0)) | 0; - hi = Math.imul(ah3, bh0); - lo = (lo + Math.imul(al2, bl1)) | 0; - mid = (mid + Math.imul(al2, bh1)) | 0; - mid = (mid + Math.imul(ah2, bl1)) | 0; - hi = (hi + Math.imul(ah2, bh1)) | 0; - lo = (lo + Math.imul(al1, bl2)) | 0; - mid = (mid + Math.imul(al1, bh2)) | 0; - mid = (mid + Math.imul(ah1, bl2)) | 0; - hi = (hi + Math.imul(ah1, bh2)) | 0; - lo = (lo + Math.imul(al0, bl3)) | 0; - mid = (mid + Math.imul(al0, bh3)) | 0; - mid = (mid + Math.imul(ah0, bl3)) | 0; - hi = (hi + Math.imul(ah0, bh3)) | 0; - var w3 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w3 >>> 26)) | 0; - w3 &= 0x3ffffff; - /* k = 4 */ - lo = Math.imul(al4, bl0); - mid = Math.imul(al4, bh0); - mid = (mid + Math.imul(ah4, bl0)) | 0; - hi = Math.imul(ah4, bh0); - lo = (lo + Math.imul(al3, bl1)) | 0; - mid = (mid + Math.imul(al3, bh1)) | 0; - mid = (mid + Math.imul(ah3, bl1)) | 0; - hi = (hi + Math.imul(ah3, bh1)) | 0; - lo = (lo + Math.imul(al2, bl2)) | 0; - mid = (mid + Math.imul(al2, bh2)) | 0; - mid = (mid + Math.imul(ah2, bl2)) | 0; - hi = (hi + Math.imul(ah2, bh2)) | 0; - lo = (lo + Math.imul(al1, bl3)) | 0; - mid = (mid + Math.imul(al1, bh3)) | 0; - mid = (mid + Math.imul(ah1, bl3)) | 0; - hi = (hi + Math.imul(ah1, bh3)) | 0; - lo = (lo + Math.imul(al0, bl4)) | 0; - mid = (mid + Math.imul(al0, bh4)) | 0; - mid = (mid + Math.imul(ah0, bl4)) | 0; - hi = (hi + Math.imul(ah0, bh4)) | 0; - var w4 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w4 >>> 26)) | 0; - w4 &= 0x3ffffff; - /* k = 5 */ - lo = Math.imul(al5, bl0); - mid = Math.imul(al5, bh0); - mid = (mid + Math.imul(ah5, bl0)) | 0; - hi = Math.imul(ah5, bh0); - lo = (lo + Math.imul(al4, bl1)) | 0; - mid = (mid + Math.imul(al4, bh1)) | 0; - mid = (mid + Math.imul(ah4, bl1)) | 0; - hi = (hi + Math.imul(ah4, bh1)) | 0; - lo = (lo + Math.imul(al3, bl2)) | 0; - mid = (mid + Math.imul(al3, bh2)) | 0; - mid = (mid + Math.imul(ah3, bl2)) | 0; - hi = (hi + Math.imul(ah3, bh2)) | 0; - lo = (lo + Math.imul(al2, bl3)) | 0; - mid = (mid + Math.imul(al2, bh3)) | 0; - mid = (mid + Math.imul(ah2, bl3)) | 0; - hi = (hi + Math.imul(ah2, bh3)) | 0; - lo = (lo + Math.imul(al1, bl4)) | 0; - mid = (mid + Math.imul(al1, bh4)) | 0; - mid = (mid + Math.imul(ah1, bl4)) | 0; - hi = (hi + Math.imul(ah1, bh4)) | 0; - lo = (lo + Math.imul(al0, bl5)) | 0; - mid = (mid + Math.imul(al0, bh5)) | 0; - mid = (mid + Math.imul(ah0, bl5)) | 0; - hi = (hi + Math.imul(ah0, bh5)) | 0; - var w5 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w5 >>> 26)) | 0; - w5 &= 0x3ffffff; - /* k = 6 */ - lo = Math.imul(al6, bl0); - mid = Math.imul(al6, bh0); - mid = (mid + Math.imul(ah6, bl0)) | 0; - hi = Math.imul(ah6, bh0); - lo = (lo + Math.imul(al5, bl1)) | 0; - mid = (mid + Math.imul(al5, bh1)) | 0; - mid = (mid + Math.imul(ah5, bl1)) | 0; - hi = (hi + Math.imul(ah5, bh1)) | 0; - lo = (lo + Math.imul(al4, bl2)) | 0; - mid = (mid + Math.imul(al4, bh2)) | 0; - mid = (mid + Math.imul(ah4, bl2)) | 0; - hi = (hi + Math.imul(ah4, bh2)) | 0; - lo = (lo + Math.imul(al3, bl3)) | 0; - mid = (mid + Math.imul(al3, bh3)) | 0; - mid = (mid + Math.imul(ah3, bl3)) | 0; - hi = (hi + Math.imul(ah3, bh3)) | 0; - lo = (lo + Math.imul(al2, bl4)) | 0; - mid = (mid + Math.imul(al2, bh4)) | 0; - mid = (mid + Math.imul(ah2, bl4)) | 0; - hi = (hi + Math.imul(ah2, bh4)) | 0; - lo = (lo + Math.imul(al1, bl5)) | 0; - mid = (mid + Math.imul(al1, bh5)) | 0; - mid = (mid + Math.imul(ah1, bl5)) | 0; - hi = (hi + Math.imul(ah1, bh5)) | 0; - lo = (lo + Math.imul(al0, bl6)) | 0; - mid = (mid + Math.imul(al0, bh6)) | 0; - mid = (mid + Math.imul(ah0, bl6)) | 0; - hi = (hi + Math.imul(ah0, bh6)) | 0; - var w6 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w6 >>> 26)) | 0; - w6 &= 0x3ffffff; - /* k = 7 */ - lo = Math.imul(al7, bl0); - mid = Math.imul(al7, bh0); - mid = (mid + Math.imul(ah7, bl0)) | 0; - hi = Math.imul(ah7, bh0); - lo = (lo + Math.imul(al6, bl1)) | 0; - mid = (mid + Math.imul(al6, bh1)) | 0; - mid = (mid + Math.imul(ah6, bl1)) | 0; - hi = (hi + Math.imul(ah6, bh1)) | 0; - lo = (lo + Math.imul(al5, bl2)) | 0; - mid = (mid + Math.imul(al5, bh2)) | 0; - mid = (mid + Math.imul(ah5, bl2)) | 0; - hi = (hi + Math.imul(ah5, bh2)) | 0; - lo = (lo + Math.imul(al4, bl3)) | 0; - mid = (mid + Math.imul(al4, bh3)) | 0; - mid = (mid + Math.imul(ah4, bl3)) | 0; - hi = (hi + Math.imul(ah4, bh3)) | 0; - lo = (lo + Math.imul(al3, bl4)) | 0; - mid = (mid + Math.imul(al3, bh4)) | 0; - mid = (mid + Math.imul(ah3, bl4)) | 0; - hi = (hi + Math.imul(ah3, bh4)) | 0; - lo = (lo + Math.imul(al2, bl5)) | 0; - mid = (mid + Math.imul(al2, bh5)) | 0; - mid = (mid + Math.imul(ah2, bl5)) | 0; - hi = (hi + Math.imul(ah2, bh5)) | 0; - lo = (lo + Math.imul(al1, bl6)) | 0; - mid = (mid + Math.imul(al1, bh6)) | 0; - mid = (mid + Math.imul(ah1, bl6)) | 0; - hi = (hi + Math.imul(ah1, bh6)) | 0; - lo = (lo + Math.imul(al0, bl7)) | 0; - mid = (mid + Math.imul(al0, bh7)) | 0; - mid = (mid + Math.imul(ah0, bl7)) | 0; - hi = (hi + Math.imul(ah0, bh7)) | 0; - var w7 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w7 >>> 26)) | 0; - w7 &= 0x3ffffff; - /* k = 8 */ - lo = Math.imul(al8, bl0); - mid = Math.imul(al8, bh0); - mid = (mid + Math.imul(ah8, bl0)) | 0; - hi = Math.imul(ah8, bh0); - lo = (lo + Math.imul(al7, bl1)) | 0; - mid = (mid + Math.imul(al7, bh1)) | 0; - mid = (mid + Math.imul(ah7, bl1)) | 0; - hi = (hi + Math.imul(ah7, bh1)) | 0; - lo = (lo + Math.imul(al6, bl2)) | 0; - mid = (mid + Math.imul(al6, bh2)) | 0; - mid = (mid + Math.imul(ah6, bl2)) | 0; - hi = (hi + Math.imul(ah6, bh2)) | 0; - lo = (lo + Math.imul(al5, bl3)) | 0; - mid = (mid + Math.imul(al5, bh3)) | 0; - mid = (mid + Math.imul(ah5, bl3)) | 0; - hi = (hi + Math.imul(ah5, bh3)) | 0; - lo = (lo + Math.imul(al4, bl4)) | 0; - mid = (mid + Math.imul(al4, bh4)) | 0; - mid = (mid + Math.imul(ah4, bl4)) | 0; - hi = (hi + Math.imul(ah4, bh4)) | 0; - lo = (lo + Math.imul(al3, bl5)) | 0; - mid = (mid + Math.imul(al3, bh5)) | 0; - mid = (mid + Math.imul(ah3, bl5)) | 0; - hi = (hi + Math.imul(ah3, bh5)) | 0; - lo = (lo + Math.imul(al2, bl6)) | 0; - mid = (mid + Math.imul(al2, bh6)) | 0; - mid = (mid + Math.imul(ah2, bl6)) | 0; - hi = (hi + Math.imul(ah2, bh6)) | 0; - lo = (lo + Math.imul(al1, bl7)) | 0; - mid = (mid + Math.imul(al1, bh7)) | 0; - mid = (mid + Math.imul(ah1, bl7)) | 0; - hi = (hi + Math.imul(ah1, bh7)) | 0; - lo = (lo + Math.imul(al0, bl8)) | 0; - mid = (mid + Math.imul(al0, bh8)) | 0; - mid = (mid + Math.imul(ah0, bl8)) | 0; - hi = (hi + Math.imul(ah0, bh8)) | 0; - var w8 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w8 >>> 26)) | 0; - w8 &= 0x3ffffff; - /* k = 9 */ - lo = Math.imul(al9, bl0); - mid = Math.imul(al9, bh0); - mid = (mid + Math.imul(ah9, bl0)) | 0; - hi = Math.imul(ah9, bh0); - lo = (lo + Math.imul(al8, bl1)) | 0; - mid = (mid + Math.imul(al8, bh1)) | 0; - mid = (mid + Math.imul(ah8, bl1)) | 0; - hi = (hi + Math.imul(ah8, bh1)) | 0; - lo = (lo + Math.imul(al7, bl2)) | 0; - mid = (mid + Math.imul(al7, bh2)) | 0; - mid = (mid + Math.imul(ah7, bl2)) | 0; - hi = (hi + Math.imul(ah7, bh2)) | 0; - lo = (lo + Math.imul(al6, bl3)) | 0; - mid = (mid + Math.imul(al6, bh3)) | 0; - mid = (mid + Math.imul(ah6, bl3)) | 0; - hi = (hi + Math.imul(ah6, bh3)) | 0; - lo = (lo + Math.imul(al5, bl4)) | 0; - mid = (mid + Math.imul(al5, bh4)) | 0; - mid = (mid + Math.imul(ah5, bl4)) | 0; - hi = (hi + Math.imul(ah5, bh4)) | 0; - lo = (lo + Math.imul(al4, bl5)) | 0; - mid = (mid + Math.imul(al4, bh5)) | 0; - mid = (mid + Math.imul(ah4, bl5)) | 0; - hi = (hi + Math.imul(ah4, bh5)) | 0; - lo = (lo + Math.imul(al3, bl6)) | 0; - mid = (mid + Math.imul(al3, bh6)) | 0; - mid = (mid + Math.imul(ah3, bl6)) | 0; - hi = (hi + Math.imul(ah3, bh6)) | 0; - lo = (lo + Math.imul(al2, bl7)) | 0; - mid = (mid + Math.imul(al2, bh7)) | 0; - mid = (mid + Math.imul(ah2, bl7)) | 0; - hi = (hi + Math.imul(ah2, bh7)) | 0; - lo = (lo + Math.imul(al1, bl8)) | 0; - mid = (mid + Math.imul(al1, bh8)) | 0; - mid = (mid + Math.imul(ah1, bl8)) | 0; - hi = (hi + Math.imul(ah1, bh8)) | 0; - lo = (lo + Math.imul(al0, bl9)) | 0; - mid = (mid + Math.imul(al0, bh9)) | 0; - mid = (mid + Math.imul(ah0, bl9)) | 0; - hi = (hi + Math.imul(ah0, bh9)) | 0; - var w9 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w9 >>> 26)) | 0; - w9 &= 0x3ffffff; - /* k = 10 */ - lo = Math.imul(al9, bl1); - mid = Math.imul(al9, bh1); - mid = (mid + Math.imul(ah9, bl1)) | 0; - hi = Math.imul(ah9, bh1); - lo = (lo + Math.imul(al8, bl2)) | 0; - mid = (mid + Math.imul(al8, bh2)) | 0; - mid = (mid + Math.imul(ah8, bl2)) | 0; - hi = (hi + Math.imul(ah8, bh2)) | 0; - lo = (lo + Math.imul(al7, bl3)) | 0; - mid = (mid + Math.imul(al7, bh3)) | 0; - mid = (mid + Math.imul(ah7, bl3)) | 0; - hi = (hi + Math.imul(ah7, bh3)) | 0; - lo = (lo + Math.imul(al6, bl4)) | 0; - mid = (mid + Math.imul(al6, bh4)) | 0; - mid = (mid + Math.imul(ah6, bl4)) | 0; - hi = (hi + Math.imul(ah6, bh4)) | 0; - lo = (lo + Math.imul(al5, bl5)) | 0; - mid = (mid + Math.imul(al5, bh5)) | 0; - mid = (mid + Math.imul(ah5, bl5)) | 0; - hi = (hi + Math.imul(ah5, bh5)) | 0; - lo = (lo + Math.imul(al4, bl6)) | 0; - mid = (mid + Math.imul(al4, bh6)) | 0; - mid = (mid + Math.imul(ah4, bl6)) | 0; - hi = (hi + Math.imul(ah4, bh6)) | 0; - lo = (lo + Math.imul(al3, bl7)) | 0; - mid = (mid + Math.imul(al3, bh7)) | 0; - mid = (mid + Math.imul(ah3, bl7)) | 0; - hi = (hi + Math.imul(ah3, bh7)) | 0; - lo = (lo + Math.imul(al2, bl8)) | 0; - mid = (mid + Math.imul(al2, bh8)) | 0; - mid = (mid + Math.imul(ah2, bl8)) | 0; - hi = (hi + Math.imul(ah2, bh8)) | 0; - lo = (lo + Math.imul(al1, bl9)) | 0; - mid = (mid + Math.imul(al1, bh9)) | 0; - mid = (mid + Math.imul(ah1, bl9)) | 0; - hi = (hi + Math.imul(ah1, bh9)) | 0; - var w10 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w10 >>> 26)) | 0; - w10 &= 0x3ffffff; - /* k = 11 */ - lo = Math.imul(al9, bl2); - mid = Math.imul(al9, bh2); - mid = (mid + Math.imul(ah9, bl2)) | 0; - hi = Math.imul(ah9, bh2); - lo = (lo + Math.imul(al8, bl3)) | 0; - mid = (mid + Math.imul(al8, bh3)) | 0; - mid = (mid + Math.imul(ah8, bl3)) | 0; - hi = (hi + Math.imul(ah8, bh3)) | 0; - lo = (lo + Math.imul(al7, bl4)) | 0; - mid = (mid + Math.imul(al7, bh4)) | 0; - mid = (mid + Math.imul(ah7, bl4)) | 0; - hi = (hi + Math.imul(ah7, bh4)) | 0; - lo = (lo + Math.imul(al6, bl5)) | 0; - mid = (mid + Math.imul(al6, bh5)) | 0; - mid = (mid + Math.imul(ah6, bl5)) | 0; - hi = (hi + Math.imul(ah6, bh5)) | 0; - lo = (lo + Math.imul(al5, bl6)) | 0; - mid = (mid + Math.imul(al5, bh6)) | 0; - mid = (mid + Math.imul(ah5, bl6)) | 0; - hi = (hi + Math.imul(ah5, bh6)) | 0; - lo = (lo + Math.imul(al4, bl7)) | 0; - mid = (mid + Math.imul(al4, bh7)) | 0; - mid = (mid + Math.imul(ah4, bl7)) | 0; - hi = (hi + Math.imul(ah4, bh7)) | 0; - lo = (lo + Math.imul(al3, bl8)) | 0; - mid = (mid + Math.imul(al3, bh8)) | 0; - mid = (mid + Math.imul(ah3, bl8)) | 0; - hi = (hi + Math.imul(ah3, bh8)) | 0; - lo = (lo + Math.imul(al2, bl9)) | 0; - mid = (mid + Math.imul(al2, bh9)) | 0; - mid = (mid + Math.imul(ah2, bl9)) | 0; - hi = (hi + Math.imul(ah2, bh9)) | 0; - var w11 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w11 >>> 26)) | 0; - w11 &= 0x3ffffff; - /* k = 12 */ - lo = Math.imul(al9, bl3); - mid = Math.imul(al9, bh3); - mid = (mid + Math.imul(ah9, bl3)) | 0; - hi = Math.imul(ah9, bh3); - lo = (lo + Math.imul(al8, bl4)) | 0; - mid = (mid + Math.imul(al8, bh4)) | 0; - mid = (mid + Math.imul(ah8, bl4)) | 0; - hi = (hi + Math.imul(ah8, bh4)) | 0; - lo = (lo + Math.imul(al7, bl5)) | 0; - mid = (mid + Math.imul(al7, bh5)) | 0; - mid = (mid + Math.imul(ah7, bl5)) | 0; - hi = (hi + Math.imul(ah7, bh5)) | 0; - lo = (lo + Math.imul(al6, bl6)) | 0; - mid = (mid + Math.imul(al6, bh6)) | 0; - mid = (mid + Math.imul(ah6, bl6)) | 0; - hi = (hi + Math.imul(ah6, bh6)) | 0; - lo = (lo + Math.imul(al5, bl7)) | 0; - mid = (mid + Math.imul(al5, bh7)) | 0; - mid = (mid + Math.imul(ah5, bl7)) | 0; - hi = (hi + Math.imul(ah5, bh7)) | 0; - lo = (lo + Math.imul(al4, bl8)) | 0; - mid = (mid + Math.imul(al4, bh8)) | 0; - mid = (mid + Math.imul(ah4, bl8)) | 0; - hi = (hi + Math.imul(ah4, bh8)) | 0; - lo = (lo + Math.imul(al3, bl9)) | 0; - mid = (mid + Math.imul(al3, bh9)) | 0; - mid = (mid + Math.imul(ah3, bl9)) | 0; - hi = (hi + Math.imul(ah3, bh9)) | 0; - var w12 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w12 >>> 26)) | 0; - w12 &= 0x3ffffff; - /* k = 13 */ - lo = Math.imul(al9, bl4); - mid = Math.imul(al9, bh4); - mid = (mid + Math.imul(ah9, bl4)) | 0; - hi = Math.imul(ah9, bh4); - lo = (lo + Math.imul(al8, bl5)) | 0; - mid = (mid + Math.imul(al8, bh5)) | 0; - mid = (mid + Math.imul(ah8, bl5)) | 0; - hi = (hi + Math.imul(ah8, bh5)) | 0; - lo = (lo + Math.imul(al7, bl6)) | 0; - mid = (mid + Math.imul(al7, bh6)) | 0; - mid = (mid + Math.imul(ah7, bl6)) | 0; - hi = (hi + Math.imul(ah7, bh6)) | 0; - lo = (lo + Math.imul(al6, bl7)) | 0; - mid = (mid + Math.imul(al6, bh7)) | 0; - mid = (mid + Math.imul(ah6, bl7)) | 0; - hi = (hi + Math.imul(ah6, bh7)) | 0; - lo = (lo + Math.imul(al5, bl8)) | 0; - mid = (mid + Math.imul(al5, bh8)) | 0; - mid = (mid + Math.imul(ah5, bl8)) | 0; - hi = (hi + Math.imul(ah5, bh8)) | 0; - lo = (lo + Math.imul(al4, bl9)) | 0; - mid = (mid + Math.imul(al4, bh9)) | 0; - mid = (mid + Math.imul(ah4, bl9)) | 0; - hi = (hi + Math.imul(ah4, bh9)) | 0; - var w13 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w13 >>> 26)) | 0; - w13 &= 0x3ffffff; - /* k = 14 */ - lo = Math.imul(al9, bl5); - mid = Math.imul(al9, bh5); - mid = (mid + Math.imul(ah9, bl5)) | 0; - hi = Math.imul(ah9, bh5); - lo = (lo + Math.imul(al8, bl6)) | 0; - mid = (mid + Math.imul(al8, bh6)) | 0; - mid = (mid + Math.imul(ah8, bl6)) | 0; - hi = (hi + Math.imul(ah8, bh6)) | 0; - lo = (lo + Math.imul(al7, bl7)) | 0; - mid = (mid + Math.imul(al7, bh7)) | 0; - mid = (mid + Math.imul(ah7, bl7)) | 0; - hi = (hi + Math.imul(ah7, bh7)) | 0; - lo = (lo + Math.imul(al6, bl8)) | 0; - mid = (mid + Math.imul(al6, bh8)) | 0; - mid = (mid + Math.imul(ah6, bl8)) | 0; - hi = (hi + Math.imul(ah6, bh8)) | 0; - lo = (lo + Math.imul(al5, bl9)) | 0; - mid = (mid + Math.imul(al5, bh9)) | 0; - mid = (mid + Math.imul(ah5, bl9)) | 0; - hi = (hi + Math.imul(ah5, bh9)) | 0; - var w14 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w14 >>> 26)) | 0; - w14 &= 0x3ffffff; - /* k = 15 */ - lo = Math.imul(al9, bl6); - mid = Math.imul(al9, bh6); - mid = (mid + Math.imul(ah9, bl6)) | 0; - hi = Math.imul(ah9, bh6); - lo = (lo + Math.imul(al8, bl7)) | 0; - mid = (mid + Math.imul(al8, bh7)) | 0; - mid = (mid + Math.imul(ah8, bl7)) | 0; - hi = (hi + Math.imul(ah8, bh7)) | 0; - lo = (lo + Math.imul(al7, bl8)) | 0; - mid = (mid + Math.imul(al7, bh8)) | 0; - mid = (mid + Math.imul(ah7, bl8)) | 0; - hi = (hi + Math.imul(ah7, bh8)) | 0; - lo = (lo + Math.imul(al6, bl9)) | 0; - mid = (mid + Math.imul(al6, bh9)) | 0; - mid = (mid + Math.imul(ah6, bl9)) | 0; - hi = (hi + Math.imul(ah6, bh9)) | 0; - var w15 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w15 >>> 26)) | 0; - w15 &= 0x3ffffff; - /* k = 16 */ - lo = Math.imul(al9, bl7); - mid = Math.imul(al9, bh7); - mid = (mid + Math.imul(ah9, bl7)) | 0; - hi = Math.imul(ah9, bh7); - lo = (lo + Math.imul(al8, bl8)) | 0; - mid = (mid + Math.imul(al8, bh8)) | 0; - mid = (mid + Math.imul(ah8, bl8)) | 0; - hi = (hi + Math.imul(ah8, bh8)) | 0; - lo = (lo + Math.imul(al7, bl9)) | 0; - mid = (mid + Math.imul(al7, bh9)) | 0; - mid = (mid + Math.imul(ah7, bl9)) | 0; - hi = (hi + Math.imul(ah7, bh9)) | 0; - var w16 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w16 >>> 26)) | 0; - w16 &= 0x3ffffff; - /* k = 17 */ - lo = Math.imul(al9, bl8); - mid = Math.imul(al9, bh8); - mid = (mid + Math.imul(ah9, bl8)) | 0; - hi = Math.imul(ah9, bh8); - lo = (lo + Math.imul(al8, bl9)) | 0; - mid = (mid + Math.imul(al8, bh9)) | 0; - mid = (mid + Math.imul(ah8, bl9)) | 0; - hi = (hi + Math.imul(ah8, bh9)) | 0; - var w17 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w17 >>> 26)) | 0; - w17 &= 0x3ffffff; - /* k = 18 */ - lo = Math.imul(al9, bl9); - mid = Math.imul(al9, bh9); - mid = (mid + Math.imul(ah9, bl9)) | 0; - hi = Math.imul(ah9, bh9); - var w18 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w18 >>> 26)) | 0; - w18 &= 0x3ffffff; - o[0] = w0; - o[1] = w1; - o[2] = w2; - o[3] = w3; - o[4] = w4; - o[5] = w5; - o[6] = w6; - o[7] = w7; - o[8] = w8; - o[9] = w9; - o[10] = w10; - o[11] = w11; - o[12] = w12; - o[13] = w13; - o[14] = w14; - o[15] = w15; - o[16] = w16; - o[17] = w17; - o[18] = w18; - if (c !== 0) { - o[19] = c; - out.length++; - } - return out; - }; - - // Polyfill comb - if (!Math.imul) { - comb10MulTo = smallMulTo; + while (++i < len) { + out[i] = buffer[i] << 1 | buffer[i + 1] >> (7) } - function bigMulTo (self, num, out) { - out.negative = num.negative ^ self.negative; - out.length = self.length + num.length; + return out +} - var carry = 0; - var hncarry = 0; - for (var k = 0; k < out.length - 1; k++) { - // Sum all words with the same `i + j = k` and accumulate `ncarry`, - // note that ncarry could be >= 0x3ffffff - var ncarry = hncarry; - hncarry = 0; - var rword = carry & 0x3ffffff; - var maxJ = Math.min(k, num.length - 1); - for (var j = Math.max(0, k - self.length + 1); j <= maxJ; j++) { - var i = k - j; - var a = self.words[i] | 0; - var b = num.words[j] | 0; - var r = a * b; +exports.encrypt = function (self, chunk, decrypt) { + var len = chunk.length + var out = Buffer.allocUnsafe(len) + var i = -1 - var lo = r & 0x3ffffff; - ncarry = (ncarry + ((r / 0x4000000) | 0)) | 0; - lo = (lo + rword) | 0; - rword = lo & 0x3ffffff; - ncarry = (ncarry + (lo >>> 26)) | 0; + while (++i < len) { + out[i] = encryptByte(self, chunk[i], decrypt) + } - hncarry += ncarry >>> 26; - ncarry &= 0x3ffffff; - } - out.words[k] = rword; - carry = ncarry; - ncarry = hncarry; - } - if (carry !== 0) { - out.words[k] = carry; - } else { - out.length--; - } + return out +} - return out._strip(); - } +},{"safe-buffer":390}],99:[function(require,module,exports){ +var Buffer = require('safe-buffer').Buffer - function jumboMulTo (self, num, out) { - // Temporary disable, see https://github.com/indutny/bn.js/issues/211 - // var fftm = new FFTM(); - // return fftm.mulp(self, num, out); - return bigMulTo(self, num, out); - } +function encryptByte (self, byteParam, decrypt) { + var pad = self._cipher.encryptBlock(self._prev) + var out = pad[0] ^ byteParam - BN.prototype.mulTo = function mulTo (num, out) { - var res; - var len = this.length + num.length; - if (this.length === 10 && num.length === 10) { - res = comb10MulTo(this, num, out); - } else if (len < 63) { - res = smallMulTo(this, num, out); - } else if (len < 1024) { - res = bigMulTo(this, num, out); - } else { - res = jumboMulTo(this, num, out); - } + self._prev = Buffer.concat([ + self._prev.slice(1), + Buffer.from([decrypt ? byteParam : out]) + ]) - return res; - }; + return out +} - // Cooley-Tukey algorithm for FFT - // slightly revisited to rely on looping instead of recursion +exports.encrypt = function (self, chunk, decrypt) { + var len = chunk.length + var out = Buffer.allocUnsafe(len) + var i = -1 - function FFTM (x, y) { - this.x = x; - this.y = y; + while (++i < len) { + out[i] = encryptByte(self, chunk[i], decrypt) } - FFTM.prototype.makeRBT = function makeRBT (N) { - var t = new Array(N); - var l = BN.prototype._countBits(N) - 1; - for (var i = 0; i < N; i++) { - t[i] = this.revBin(i, l, N); - } - - return t; - }; + return out +} - // Returns binary-reversed representation of `x` - FFTM.prototype.revBin = function revBin (x, l, N) { - if (x === 0 || x === N - 1) return x; +},{"safe-buffer":390}],100:[function(require,module,exports){ +var xor = require('buffer-xor') +var Buffer = require('safe-buffer').Buffer +var incr32 = require('../incr32') - var rb = 0; - for (var i = 0; i < l; i++) { - rb |= (x & 1) << (l - i - 1); - x >>= 1; - } +function getBlock (self) { + var out = self._cipher.encryptBlockRaw(self._prev) + incr32(self._prev) + return out +} - return rb; - }; +var blockSize = 16 +exports.encrypt = function (self, chunk) { + var chunkNum = Math.ceil(chunk.length / blockSize) + var start = self._cache.length + self._cache = Buffer.concat([ + self._cache, + Buffer.allocUnsafe(chunkNum * blockSize) + ]) + for (var i = 0; i < chunkNum; i++) { + var out = getBlock(self) + var offset = start + i * blockSize + self._cache.writeUInt32BE(out[0], offset + 0) + self._cache.writeUInt32BE(out[1], offset + 4) + self._cache.writeUInt32BE(out[2], offset + 8) + self._cache.writeUInt32BE(out[3], offset + 12) + } + var pad = self._cache.slice(0, chunk.length) + self._cache = self._cache.slice(chunk.length) + return xor(chunk, pad) +} - // Performs "tweedling" phase, therefore 'emulating' - // behaviour of the recursive algorithm - FFTM.prototype.permute = function permute (rbt, rws, iws, rtws, itws, N) { - for (var i = 0; i < N; i++) { - rtws[i] = rws[rbt[i]]; - itws[i] = iws[rbt[i]]; - } - }; +},{"../incr32":95,"buffer-xor":119,"safe-buffer":390}],101:[function(require,module,exports){ +exports.encrypt = function (self, block) { + return self._cipher.encryptBlock(block) +} - FFTM.prototype.transform = function transform (rws, iws, rtws, itws, N, rbt) { - this.permute(rbt, rws, iws, rtws, itws, N); +exports.decrypt = function (self, block) { + return self._cipher.decryptBlock(block) +} - for (var s = 1; s < N; s <<= 1) { - var l = s << 1; +},{}],102:[function(require,module,exports){ +var modeModules = { + ECB: require('./ecb'), + CBC: require('./cbc'), + CFB: require('./cfb'), + CFB8: require('./cfb8'), + CFB1: require('./cfb1'), + OFB: require('./ofb'), + CTR: require('./ctr'), + GCM: require('./ctr') +} - var rtwdf = Math.cos(2 * Math.PI / l); - var itwdf = Math.sin(2 * Math.PI / l); +var modes = require('./list.json') - for (var p = 0; p < N; p += l) { - var rtwdf_ = rtwdf; - var itwdf_ = itwdf; +for (var key in modes) { + modes[key].module = modeModules[modes[key].mode] +} - for (var j = 0; j < s; j++) { - var re = rtws[p + j]; - var ie = itws[p + j]; +module.exports = modes - var ro = rtws[p + j + s]; - var io = itws[p + j + s]; +},{"./cbc":96,"./cfb":97,"./cfb1":98,"./cfb8":99,"./ctr":100,"./ecb":101,"./list.json":103,"./ofb":104}],103:[function(require,module,exports){ +module.exports={ + "aes-128-ecb": { + "cipher": "AES", + "key": 128, + "iv": 0, + "mode": "ECB", + "type": "block" + }, + "aes-192-ecb": { + "cipher": "AES", + "key": 192, + "iv": 0, + "mode": "ECB", + "type": "block" + }, + "aes-256-ecb": { + "cipher": "AES", + "key": 256, + "iv": 0, + "mode": "ECB", + "type": "block" + }, + "aes-128-cbc": { + "cipher": "AES", + "key": 128, + "iv": 16, + "mode": "CBC", + "type": "block" + }, + "aes-192-cbc": { + "cipher": "AES", + "key": 192, + "iv": 16, + "mode": "CBC", + "type": "block" + }, + "aes-256-cbc": { + "cipher": "AES", + "key": 256, + "iv": 16, + "mode": "CBC", + "type": "block" + }, + "aes128": { + "cipher": "AES", + "key": 128, + "iv": 16, + "mode": "CBC", + "type": "block" + }, + "aes192": { + "cipher": "AES", + "key": 192, + "iv": 16, + "mode": "CBC", + "type": "block" + }, + "aes256": { + "cipher": "AES", + "key": 256, + "iv": 16, + "mode": "CBC", + "type": "block" + }, + "aes-128-cfb": { + "cipher": "AES", + "key": 128, + "iv": 16, + "mode": "CFB", + "type": "stream" + }, + "aes-192-cfb": { + "cipher": "AES", + "key": 192, + "iv": 16, + "mode": "CFB", + "type": "stream" + }, + "aes-256-cfb": { + "cipher": "AES", + "key": 256, + "iv": 16, + "mode": "CFB", + "type": "stream" + }, + "aes-128-cfb8": { + "cipher": "AES", + "key": 128, + "iv": 16, + "mode": "CFB8", + "type": "stream" + }, + "aes-192-cfb8": { + "cipher": "AES", + "key": 192, + "iv": 16, + "mode": "CFB8", + "type": "stream" + }, + "aes-256-cfb8": { + "cipher": "AES", + "key": 256, + "iv": 16, + "mode": "CFB8", + "type": "stream" + }, + "aes-128-cfb1": { + "cipher": "AES", + "key": 128, + "iv": 16, + "mode": "CFB1", + "type": "stream" + }, + "aes-192-cfb1": { + "cipher": "AES", + "key": 192, + "iv": 16, + "mode": "CFB1", + "type": "stream" + }, + "aes-256-cfb1": { + "cipher": "AES", + "key": 256, + "iv": 16, + "mode": "CFB1", + "type": "stream" + }, + "aes-128-ofb": { + "cipher": "AES", + "key": 128, + "iv": 16, + "mode": "OFB", + "type": "stream" + }, + "aes-192-ofb": { + "cipher": "AES", + "key": 192, + "iv": 16, + "mode": "OFB", + "type": "stream" + }, + "aes-256-ofb": { + "cipher": "AES", + "key": 256, + "iv": 16, + "mode": "OFB", + "type": "stream" + }, + "aes-128-ctr": { + "cipher": "AES", + "key": 128, + "iv": 16, + "mode": "CTR", + "type": "stream" + }, + "aes-192-ctr": { + "cipher": "AES", + "key": 192, + "iv": 16, + "mode": "CTR", + "type": "stream" + }, + "aes-256-ctr": { + "cipher": "AES", + "key": 256, + "iv": 16, + "mode": "CTR", + "type": "stream" + }, + "aes-128-gcm": { + "cipher": "AES", + "key": 128, + "iv": 12, + "mode": "GCM", + "type": "auth" + }, + "aes-192-gcm": { + "cipher": "AES", + "key": 192, + "iv": 12, + "mode": "GCM", + "type": "auth" + }, + "aes-256-gcm": { + "cipher": "AES", + "key": 256, + "iv": 12, + "mode": "GCM", + "type": "auth" + } +} - var rx = rtwdf_ * ro - itwdf_ * io; +},{}],104:[function(require,module,exports){ +(function (Buffer){(function (){ +var xor = require('buffer-xor') - io = rtwdf_ * io + itwdf_ * ro; - ro = rx; +function getBlock (self) { + self._prev = self._cipher.encryptBlock(self._prev) + return self._prev +} - rtws[p + j] = re + ro; - itws[p + j] = ie + io; +exports.encrypt = function (self, chunk) { + while (self._cache.length < chunk.length) { + self._cache = Buffer.concat([self._cache, getBlock(self)]) + } - rtws[p + j + s] = re - ro; - itws[p + j + s] = ie - io; + var pad = self._cache.slice(0, chunk.length) + self._cache = self._cache.slice(chunk.length) + return xor(chunk, pad) +} - /* jshint maxdepth : false */ - if (j !== l) { - rx = rtwdf * rtwdf_ - itwdf * itwdf_; +}).call(this)}).call(this,require("buffer").Buffer) +},{"buffer":118,"buffer-xor":119}],105:[function(require,module,exports){ +var aes = require('./aes') +var Buffer = require('safe-buffer').Buffer +var Transform = require('cipher-base') +var inherits = require('inherits') - itwdf_ = rtwdf * itwdf_ + itwdf * rtwdf_; - rtwdf_ = rx; - } - } - } - } - }; +function StreamCipher (mode, key, iv, decrypt) { + Transform.call(this) - FFTM.prototype.guessLen13b = function guessLen13b (n, m) { - var N = Math.max(m, n) | 1; - var odd = N & 1; - var i = 0; - for (N = N / 2 | 0; N; N = N >>> 1) { - i++; - } + this._cipher = new aes.AES(key) + this._prev = Buffer.from(iv) + this._cache = Buffer.allocUnsafe(0) + this._secCache = Buffer.allocUnsafe(0) + this._decrypt = decrypt + this._mode = mode +} - return 1 << i + 1 + odd; - }; +inherits(StreamCipher, Transform) - FFTM.prototype.conjugate = function conjugate (rws, iws, N) { - if (N <= 1) return; +StreamCipher.prototype._update = function (chunk) { + return this._mode.encrypt(this, chunk, this._decrypt) +} - for (var i = 0; i < N / 2; i++) { - var t = rws[i]; +StreamCipher.prototype._final = function () { + this._cipher.scrub() +} - rws[i] = rws[N - i - 1]; - rws[N - i - 1] = t; +module.exports = StreamCipher - t = iws[i]; +},{"./aes":89,"cipher-base":124,"inherits":200,"safe-buffer":390}],106:[function(require,module,exports){ +var DES = require('browserify-des') +var aes = require('browserify-aes/browser') +var aesModes = require('browserify-aes/modes') +var desModes = require('browserify-des/modes') +var ebtk = require('evp_bytestokey') - iws[i] = -iws[N - i - 1]; - iws[N - i - 1] = -t; - } - }; +function createCipher (suite, password) { + suite = suite.toLowerCase() - FFTM.prototype.normalize13b = function normalize13b (ws, N) { - var carry = 0; - for (var i = 0; i < N / 2; i++) { - var w = Math.round(ws[2 * i + 1] / N) * 0x2000 + - Math.round(ws[2 * i] / N) + - carry; + var keyLen, ivLen + if (aesModes[suite]) { + keyLen = aesModes[suite].key + ivLen = aesModes[suite].iv + } else if (desModes[suite]) { + keyLen = desModes[suite].key * 8 + ivLen = desModes[suite].iv + } else { + throw new TypeError('invalid suite type') + } - ws[i] = w & 0x3ffffff; + var keys = ebtk(password, false, keyLen, ivLen) + return createCipheriv(suite, keys.key, keys.iv) +} - if (w < 0x4000000) { - carry = 0; - } else { - carry = w / 0x4000000 | 0; - } - } +function createDecipher (suite, password) { + suite = suite.toLowerCase() - return ws; - }; + var keyLen, ivLen + if (aesModes[suite]) { + keyLen = aesModes[suite].key + ivLen = aesModes[suite].iv + } else if (desModes[suite]) { + keyLen = desModes[suite].key * 8 + ivLen = desModes[suite].iv + } else { + throw new TypeError('invalid suite type') + } - FFTM.prototype.convert13b = function convert13b (ws, len, rws, N) { - var carry = 0; - for (var i = 0; i < len; i++) { - carry = carry + (ws[i] | 0); + var keys = ebtk(password, false, keyLen, ivLen) + return createDecipheriv(suite, keys.key, keys.iv) +} - rws[2 * i] = carry & 0x1fff; carry = carry >>> 13; - rws[2 * i + 1] = carry & 0x1fff; carry = carry >>> 13; - } +function createCipheriv (suite, key, iv) { + suite = suite.toLowerCase() + if (aesModes[suite]) return aes.createCipheriv(suite, key, iv) + if (desModes[suite]) return new DES({ key: key, iv: iv, mode: suite }) - // Pad with zeroes - for (i = 2 * len; i < N; ++i) { - rws[i] = 0; - } + throw new TypeError('invalid suite type') +} - assert(carry === 0); - assert((carry & ~0x1fff) === 0); - }; +function createDecipheriv (suite, key, iv) { + suite = suite.toLowerCase() + if (aesModes[suite]) return aes.createDecipheriv(suite, key, iv) + if (desModes[suite]) return new DES({ key: key, iv: iv, mode: suite, decrypt: true }) - FFTM.prototype.stub = function stub (N) { - var ph = new Array(N); - for (var i = 0; i < N; i++) { - ph[i] = 0; - } + throw new TypeError('invalid suite type') +} - return ph; - }; +function getCiphers () { + return Object.keys(desModes).concat(aes.getCiphers()) +} - FFTM.prototype.mulp = function mulp (x, y, out) { - var N = 2 * this.guessLen13b(x.length, y.length); +exports.createCipher = exports.Cipher = createCipher +exports.createCipheriv = exports.Cipheriv = createCipheriv +exports.createDecipher = exports.Decipher = createDecipher +exports.createDecipheriv = exports.Decipheriv = createDecipheriv +exports.listCiphers = exports.getCiphers = getCiphers - var rbt = this.makeRBT(N); +},{"browserify-aes/browser":91,"browserify-aes/modes":102,"browserify-des":107,"browserify-des/modes":108,"evp_bytestokey":173}],107:[function(require,module,exports){ +var CipherBase = require('cipher-base') +var des = require('des.js') +var inherits = require('inherits') +var Buffer = require('safe-buffer').Buffer - var _ = this.stub(N); +var modes = { + 'des-ede3-cbc': des.CBC.instantiate(des.EDE), + 'des-ede3': des.EDE, + 'des-ede-cbc': des.CBC.instantiate(des.EDE), + 'des-ede': des.EDE, + 'des-cbc': des.CBC.instantiate(des.DES), + 'des-ecb': des.DES +} +modes.des = modes['des-cbc'] +modes.des3 = modes['des-ede3-cbc'] +module.exports = DES +inherits(DES, CipherBase) +function DES (opts) { + CipherBase.call(this) + var modeName = opts.mode.toLowerCase() + var mode = modes[modeName] + var type + if (opts.decrypt) { + type = 'decrypt' + } else { + type = 'encrypt' + } + var key = opts.key + if (!Buffer.isBuffer(key)) { + key = Buffer.from(key) + } + if (modeName === 'des-ede' || modeName === 'des-ede-cbc') { + key = Buffer.concat([key, key.slice(0, 8)]) + } + var iv = opts.iv + if (!Buffer.isBuffer(iv)) { + iv = Buffer.from(iv) + } + this._des = mode.create({ + key: key, + iv: iv, + type: type + }) +} +DES.prototype._update = function (data) { + return Buffer.from(this._des.update(data)) +} +DES.prototype._final = function () { + return Buffer.from(this._des.final()) +} - var rws = new Array(N); - var rwst = new Array(N); - var iwst = new Array(N); +},{"cipher-base":124,"des.js":137,"inherits":200,"safe-buffer":390}],108:[function(require,module,exports){ +exports['des-ecb'] = { + key: 8, + iv: 0 +} +exports['des-cbc'] = exports.des = { + key: 8, + iv: 8 +} +exports['des-ede3-cbc'] = exports.des3 = { + key: 24, + iv: 8 +} +exports['des-ede3'] = { + key: 24, + iv: 0 +} +exports['des-ede-cbc'] = { + key: 16, + iv: 8 +} +exports['des-ede'] = { + key: 16, + iv: 0 +} - var nrws = new Array(N); - var nrwst = new Array(N); - var niwst = new Array(N); +},{}],109:[function(require,module,exports){ +(function (Buffer){(function (){ +var BN = require('bn.js') +var randomBytes = require('randombytes') - var rmws = out.words; - rmws.length = N; +function blind (priv) { + var r = getr(priv) + var blinder = r.toRed(BN.mont(priv.modulus)).redPow(new BN(priv.publicExponent)).fromRed() + return { blinder: blinder, unblinder: r.invm(priv.modulus) } +} - this.convert13b(x.words, x.length, rws, N); - this.convert13b(y.words, y.length, nrws, N); +function getr (priv) { + var len = priv.modulus.byteLength() + var r + do { + r = new BN(randomBytes(len)) + } while (r.cmp(priv.modulus) >= 0 || !r.umod(priv.prime1) || !r.umod(priv.prime2)) + return r +} - this.transform(rws, _, rwst, iwst, N, rbt); - this.transform(nrws, _, nrwst, niwst, N, rbt); +function crt (msg, priv) { + var blinds = blind(priv) + var len = priv.modulus.byteLength() + var blinded = new BN(msg).mul(blinds.blinder).umod(priv.modulus) + var c1 = blinded.toRed(BN.mont(priv.prime1)) + var c2 = blinded.toRed(BN.mont(priv.prime2)) + var qinv = priv.coefficient + var p = priv.prime1 + var q = priv.prime2 + var m1 = c1.redPow(priv.exponent1).fromRed() + var m2 = c2.redPow(priv.exponent2).fromRed() + var h = m1.isub(m2).imul(qinv).umod(p).imul(q) + return m2.iadd(h).imul(blinds.unblinder).umod(priv.modulus).toArrayLike(Buffer, 'be', len) +} +crt.getr = getr - for (var i = 0; i < N; i++) { - var rx = rwst[i] * nrwst[i] - iwst[i] * niwst[i]; - iwst[i] = rwst[i] * niwst[i] + iwst[i] * nrwst[i]; - rwst[i] = rx; - } +module.exports = crt - this.conjugate(rwst, iwst, N); - this.transform(rwst, iwst, rmws, _, N, rbt); - this.conjugate(rmws, _, N); - this.normalize13b(rmws, N); +}).call(this)}).call(this,require("buffer").Buffer) +},{"bn.js":110,"buffer":118,"randombytes":358}],110:[function(require,module,exports){ +(function (module, exports) { + 'use strict'; - out.negative = x.negative ^ y.negative; - out.length = x.length + y.length; - return out._strip(); - }; + // Utils + function assert (val, msg) { + if (!val) throw new Error(msg || 'Assertion failed'); + } - // Multiply `this` by `num` - BN.prototype.mul = function mul (num) { - var out = new BN(null); - out.words = new Array(this.length + num.length); - return this.mulTo(num, out); - }; + // Could use `inherits` module, but don't want to move from single file + // architecture yet. + function inherits (ctor, superCtor) { + ctor.super_ = superCtor; + var TempCtor = function () {}; + TempCtor.prototype = superCtor.prototype; + ctor.prototype = new TempCtor(); + ctor.prototype.constructor = ctor; + } - // Multiply employing FFT - BN.prototype.mulf = function mulf (num) { - var out = new BN(null); - out.words = new Array(this.length + num.length); - return jumboMulTo(this, num, out); - }; + // BN - // In-place Multiplication - BN.prototype.imul = function imul (num) { - return this.clone().mulTo(num, this); - }; + function BN (number, base, endian) { + if (BN.isBN(number)) { + return number; + } - BN.prototype.imuln = function imuln (num) { - var isNegNum = num < 0; - if (isNegNum) num = -num; + this.negative = 0; + this.words = null; + this.length = 0; - assert(typeof num === 'number'); - assert(num < 0x4000000); + // Reduction context + this.red = null; - // Carry - var carry = 0; - for (var i = 0; i < this.length; i++) { - var w = (this.words[i] | 0) * num; - var lo = (w & 0x3ffffff) + (carry & 0x3ffffff); - carry >>= 26; - carry += (w / 0x4000000) | 0; - // NOTE: lo is 27bit maximum - carry += lo >>> 26; - this.words[i] = lo & 0x3ffffff; + if (number !== null) { + if (base === 'le' || base === 'be') { + endian = base; + base = 10; + } + + this._init(number || 0, base || 10, endian || 'be'); } + } + if (typeof module === 'object') { + module.exports = BN; + } else { + exports.BN = BN; + } - if (carry !== 0) { - this.words[i] = carry; - this.length++; + BN.BN = BN; + BN.wordSize = 26; + + var Buffer; + try { + if (typeof window !== 'undefined' && typeof window.Buffer !== 'undefined') { + Buffer = window.Buffer; + } else { + Buffer = require('buffer').Buffer; } + } catch (e) { + } - return isNegNum ? this.ineg() : this; - }; + BN.isBN = function isBN (num) { + if (num instanceof BN) { + return true; + } - BN.prototype.muln = function muln (num) { - return this.clone().imuln(num); + return num !== null && typeof num === 'object' && + num.constructor.wordSize === BN.wordSize && Array.isArray(num.words); }; - // `this` * `this` - BN.prototype.sqr = function sqr () { - return this.mul(this); + BN.max = function max (left, right) { + if (left.cmp(right) > 0) return left; + return right; }; - // `this` * `this` in-place - BN.prototype.isqr = function isqr () { - return this.imul(this.clone()); + BN.min = function min (left, right) { + if (left.cmp(right) < 0) return left; + return right; }; - // Math.pow(`this`, `num`) - BN.prototype.pow = function pow (num) { - var w = toBitArray(num); - if (w.length === 0) return new BN(1); - - // Skip leading zeroes - var res = this; - for (var i = 0; i < w.length; i++, res = res.sqr()) { - if (w[i] !== 0) break; + BN.prototype._init = function init (number, base, endian) { + if (typeof number === 'number') { + return this._initNumber(number, base, endian); } - if (++i < w.length) { - for (var q = res.sqr(); i < w.length; i++, q = q.sqr()) { - if (w[i] === 0) continue; - - res = res.mul(q); - } + if (typeof number === 'object') { + return this._initArray(number, base, endian); } - return res; - }; - - // Shift-left in-place - BN.prototype.iushln = function iushln (bits) { - assert(typeof bits === 'number' && bits >= 0); - var r = bits % 26; - var s = (bits - r) / 26; - var carryMask = (0x3ffffff >>> (26 - r)) << (26 - r); - var i; - - if (r !== 0) { - var carry = 0; - - for (i = 0; i < this.length; i++) { - var newCarry = this.words[i] & carryMask; - var c = ((this.words[i] | 0) - newCarry) << r; - this.words[i] = c | carry; - carry = newCarry >>> (26 - r); - } - - if (carry) { - this.words[i] = carry; - this.length++; - } + if (base === 'hex') { + base = 16; } + assert(base === (base | 0) && base >= 2 && base <= 36); - if (s !== 0) { - for (i = this.length - 1; i >= 0; i--) { - this.words[i + s] = this.words[i]; - } + number = number.toString().replace(/\s+/g, ''); + var start = 0; + if (number[0] === '-') { + start++; + this.negative = 1; + } - for (i = 0; i < s; i++) { - this.words[i] = 0; + if (start < number.length) { + if (base === 16) { + this._parseHex(number, start, endian); + } else { + this._parseBase(number, base, start); + if (endian === 'le') { + this._initArray(this.toArray(), base, endian); + } } + } + }; - this.length += s; + BN.prototype._initNumber = function _initNumber (number, base, endian) { + if (number < 0) { + this.negative = 1; + number = -number; + } + if (number < 0x4000000) { + this.words = [number & 0x3ffffff]; + this.length = 1; + } else if (number < 0x10000000000000) { + this.words = [ + number & 0x3ffffff, + (number / 0x4000000) & 0x3ffffff + ]; + this.length = 2; + } else { + assert(number < 0x20000000000000); // 2 ^ 53 (unsafe) + this.words = [ + number & 0x3ffffff, + (number / 0x4000000) & 0x3ffffff, + 1 + ]; + this.length = 3; } - return this._strip(); - }; + if (endian !== 'le') return; - BN.prototype.ishln = function ishln (bits) { - // TODO(indutny): implement me - assert(this.negative === 0); - return this.iushln(bits); + // Reverse the bytes + this._initArray(this.toArray(), base, endian); }; - // Shift-right in-place - // NOTE: `hint` is a lowest bit before trailing zeroes - // NOTE: if `extended` is present - it will be filled with destroyed bits - BN.prototype.iushrn = function iushrn (bits, hint, extended) { - assert(typeof bits === 'number' && bits >= 0); - var h; - if (hint) { - h = (hint - (hint % 26)) / 26; - } else { - h = 0; + BN.prototype._initArray = function _initArray (number, base, endian) { + // Perhaps a Uint8Array + assert(typeof number.length === 'number'); + if (number.length <= 0) { + this.words = [0]; + this.length = 1; + return this; } - var r = bits % 26; - var s = Math.min((bits - r) / 26, this.length); - var mask = 0x3ffffff ^ ((0x3ffffff >>> r) << r); - var maskedWords = extended; - - h -= s; - h = Math.max(0, h); + this.length = Math.ceil(number.length / 3); + this.words = new Array(this.length); + for (var i = 0; i < this.length; i++) { + this.words[i] = 0; + } - // Extended mode, copy masked part - if (maskedWords) { - for (var i = 0; i < s; i++) { - maskedWords.words[i] = this.words[i]; + var j, w; + var off = 0; + if (endian === 'be') { + for (i = number.length - 1, j = 0; i >= 0; i -= 3) { + w = number[i] | (number[i - 1] << 8) | (number[i - 2] << 16); + this.words[j] |= (w << off) & 0x3ffffff; + this.words[j + 1] = (w >>> (26 - off)) & 0x3ffffff; + off += 24; + if (off >= 26) { + off -= 26; + j++; + } + } + } else if (endian === 'le') { + for (i = 0, j = 0; i < number.length; i += 3) { + w = number[i] | (number[i + 1] << 8) | (number[i + 2] << 16); + this.words[j] |= (w << off) & 0x3ffffff; + this.words[j + 1] = (w >>> (26 - off)) & 0x3ffffff; + off += 24; + if (off >= 26) { + off -= 26; + j++; + } } - maskedWords.length = s; } + return this._strip(); + }; - if (s === 0) { - // No-op, we should not move anything at all - } else if (this.length > s) { - this.length -= s; - for (i = 0; i < this.length; i++) { - this.words[i] = this.words[i + s]; - } + function parseHex4Bits (string, index) { + var c = string.charCodeAt(index); + // '0' - '9' + if (c >= 48 && c <= 57) { + return c - 48; + // 'A' - 'F' + } else if (c >= 65 && c <= 70) { + return c - 55; + // 'a' - 'f' + } else if (c >= 97 && c <= 102) { + return c - 87; } else { - this.words[0] = 0; - this.length = 1; + assert(false, 'Invalid character in ' + string); } + } - var carry = 0; - for (i = this.length - 1; i >= 0 && (carry !== 0 || i >= h); i--) { - var word = this.words[i] | 0; - this.words[i] = (carry << (26 - r)) | (word >>> r); - carry = word & mask; + function parseHexByte (string, lowerBound, index) { + var r = parseHex4Bits(string, index); + if (index - 1 >= lowerBound) { + r |= parseHex4Bits(string, index - 1) << 4; } + return r; + } - // Push carried bits as a mask - if (maskedWords && carry !== 0) { - maskedWords.words[maskedWords.length++] = carry; + BN.prototype._parseHex = function _parseHex (number, start, endian) { + // Create possibly bigger array to ensure that it fits the number + this.length = Math.ceil((number.length - start) / 6); + this.words = new Array(this.length); + for (var i = 0; i < this.length; i++) { + this.words[i] = 0; } - if (this.length === 0) { - this.words[0] = 0; - this.length = 1; + // 24-bits chunks + var off = 0; + var j = 0; + + var w; + if (endian === 'be') { + for (i = number.length - 1; i >= start; i -= 2) { + w = parseHexByte(number, start, i) << off; + this.words[j] |= w & 0x3ffffff; + if (off >= 18) { + off -= 18; + j += 1; + this.words[j] |= w >>> 26; + } else { + off += 8; + } + } + } else { + var parseLength = number.length - start; + for (i = parseLength % 2 === 0 ? start + 1 : start; i < number.length; i += 2) { + w = parseHexByte(number, start, i) << off; + this.words[j] |= w & 0x3ffffff; + if (off >= 18) { + off -= 18; + j += 1; + this.words[j] |= w >>> 26; + } else { + off += 8; + } + } } - return this._strip(); + this._strip(); }; - BN.prototype.ishrn = function ishrn (bits, hint, extended) { - // TODO(indutny): implement me - assert(this.negative === 0); - return this.iushrn(bits, hint, extended); - }; + function parseBase (str, start, end, mul) { + var r = 0; + var b = 0; + var len = Math.min(str.length, end); + for (var i = start; i < len; i++) { + var c = str.charCodeAt(i) - 48; - // Shift-left - BN.prototype.shln = function shln (bits) { - return this.clone().ishln(bits); - }; + r *= mul; - BN.prototype.ushln = function ushln (bits) { - return this.clone().iushln(bits); - }; + // 'a' + if (c >= 49) { + b = c - 49 + 0xa; - // Shift-right - BN.prototype.shrn = function shrn (bits) { - return this.clone().ishrn(bits); - }; - - BN.prototype.ushrn = function ushrn (bits) { - return this.clone().iushrn(bits); - }; - - // Test if n bit is set - BN.prototype.testn = function testn (bit) { - assert(typeof bit === 'number' && bit >= 0); - var r = bit % 26; - var s = (bit - r) / 26; - var q = 1 << r; - - // Fast case: bit is much higher than all existing words - if (this.length <= s) return false; - - // Check bit and return - var w = this.words[s]; - - return !!(w & q); - }; - - // Return only lowers bits of number (in-place) - BN.prototype.imaskn = function imaskn (bits) { - assert(typeof bits === 'number' && bits >= 0); - var r = bits % 26; - var s = (bits - r) / 26; - - assert(this.negative === 0, 'imaskn works only with positive numbers'); + // 'A' + } else if (c >= 17) { + b = c - 17 + 0xa; - if (this.length <= s) { - return this; + // '0' - '9' + } else { + b = c; + } + assert(c >= 0 && b < mul, 'Invalid character'); + r += b; } + return r; + } - if (r !== 0) { - s++; - } - this.length = Math.min(s, this.length); + BN.prototype._parseBase = function _parseBase (number, base, start) { + // Initialize as zero + this.words = [0]; + this.length = 1; - if (r !== 0) { - var mask = 0x3ffffff ^ ((0x3ffffff >>> r) << r); - this.words[this.length - 1] &= mask; + // Find length of limb in base + for (var limbLen = 0, limbPow = 1; limbPow <= 0x3ffffff; limbPow *= base) { + limbLen++; } + limbLen--; + limbPow = (limbPow / base) | 0; - return this._strip(); - }; - - // Return only lowers bits of number - BN.prototype.maskn = function maskn (bits) { - return this.clone().imaskn(bits); - }; + var total = number.length - start; + var mod = total % limbLen; + var end = Math.min(total, total - mod) + start; - // Add plain number `num` to `this` - BN.prototype.iaddn = function iaddn (num) { - assert(typeof num === 'number'); - assert(num < 0x4000000); - if (num < 0) return this.isubn(-num); + var word = 0; + for (var i = start; i < end; i += limbLen) { + word = parseBase(number, i, i + limbLen, base); - // Possible sign change - if (this.negative !== 0) { - if (this.length === 1 && (this.words[0] | 0) <= num) { - this.words[0] = num - (this.words[0] | 0); - this.negative = 0; - return this; + this.imuln(limbPow); + if (this.words[0] + word < 0x4000000) { + this.words[0] += word; + } else { + this._iaddn(word); } - - this.negative = 0; - this.isubn(num); - this.negative = 1; - return this; } - // Add without checks - return this._iaddn(num); - }; + if (mod !== 0) { + var pow = 1; + word = parseBase(number, i, number.length, base); - BN.prototype._iaddn = function _iaddn (num) { - this.words[0] += num; + for (i = 0; i < mod; i++) { + pow *= base; + } - // Carry - for (var i = 0; i < this.length && this.words[i] >= 0x4000000; i++) { - this.words[i] -= 0x4000000; - if (i === this.length - 1) { - this.words[i + 1] = 1; + this.imuln(pow); + if (this.words[0] + word < 0x4000000) { + this.words[0] += word; } else { - this.words[i + 1]++; + this._iaddn(word); } } - this.length = Math.max(this.length, i + 1); - return this; + this._strip(); }; - // Subtract plain number `num` from `this` - BN.prototype.isubn = function isubn (num) { - assert(typeof num === 'number'); - assert(num < 0x4000000); - if (num < 0) return this.iaddn(-num); - - if (this.negative !== 0) { - this.negative = 0; - this.iaddn(num); - this.negative = 1; - return this; + BN.prototype.copy = function copy (dest) { + dest.words = new Array(this.length); + for (var i = 0; i < this.length; i++) { + dest.words[i] = this.words[i]; } + dest.length = this.length; + dest.negative = this.negative; + dest.red = this.red; + }; - this.words[0] -= num; - - if (this.length === 1 && this.words[0] < 0) { - this.words[0] = -this.words[0]; - this.negative = 1; - } else { - // Carry - for (var i = 0; i < this.length && this.words[i] < 0; i++) { - this.words[i] += 0x4000000; - this.words[i + 1] -= 1; - } - } + function move (dest, src) { + dest.words = src.words; + dest.length = src.length; + dest.negative = src.negative; + dest.red = src.red; + } - return this._strip(); + BN.prototype._move = function _move (dest) { + move(dest, this); }; - BN.prototype.addn = function addn (num) { - return this.clone().iaddn(num); + BN.prototype.clone = function clone () { + var r = new BN(null); + this.copy(r); + return r; }; - BN.prototype.subn = function subn (num) { - return this.clone().isubn(num); + BN.prototype._expand = function _expand (size) { + while (this.length < size) { + this.words[this.length++] = 0; + } + return this; }; - BN.prototype.iabs = function iabs () { - this.negative = 0; - - return this; + // Remove leading `0` from `this` + BN.prototype._strip = function strip () { + while (this.length > 1 && this.words[this.length - 1] === 0) { + this.length--; + } + return this._normSign(); }; - BN.prototype.abs = function abs () { - return this.clone().iabs(); + BN.prototype._normSign = function _normSign () { + // -0 = 0 + if (this.length === 1 && this.words[0] === 0) { + this.negative = 0; + } + return this; }; - BN.prototype._ishlnsubmul = function _ishlnsubmul (num, mul, shift) { - var len = num.length + shift; - var i; + // Check Symbol.for because not everywhere where Symbol defined + // See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol#Browser_compatibility + if (typeof Symbol !== 'undefined' && typeof Symbol.for === 'function') { + try { + BN.prototype[Symbol.for('nodejs.util.inspect.custom')] = inspect; + } catch (e) { + BN.prototype.inspect = inspect; + } + } else { + BN.prototype.inspect = inspect; + } - this._expand(len); + function inspect () { + return (this.red ? ''; + } - var w; - var carry = 0; - for (i = 0; i < num.length; i++) { - w = (this.words[i + shift] | 0) + carry; - var right = (num.words[i] | 0) * mul; - w -= right & 0x3ffffff; - carry = (w >> 26) - ((right / 0x4000000) | 0); - this.words[i + shift] = w & 0x3ffffff; - } - for (; i < this.length - shift; i++) { - w = (this.words[i + shift] | 0) + carry; - carry = w >> 26; - this.words[i + shift] = w & 0x3ffffff; - } + /* - if (carry === 0) return this._strip(); + var zeros = []; + var groupSizes = []; + var groupBases = []; - // Subtraction overflow - assert(carry === -1); - carry = 0; - for (i = 0; i < this.length; i++) { - w = -(this.words[i] | 0) + carry; - carry = w >> 26; - this.words[i] = w & 0x3ffffff; + var s = ''; + var i = -1; + while (++i < BN.wordSize) { + zeros[i] = s; + s += '0'; + } + groupSizes[0] = 0; + groupSizes[1] = 0; + groupBases[0] = 0; + groupBases[1] = 0; + var base = 2 - 1; + while (++base < 36 + 1) { + var groupSize = 0; + var groupBase = 1; + while (groupBase < (1 << BN.wordSize) / base) { + groupBase *= base; + groupSize += 1; } - this.negative = 1; + groupSizes[base] = groupSize; + groupBases[base] = groupBase; + } - return this._strip(); - }; + */ - BN.prototype._wordDiv = function _wordDiv (num, mode) { - var shift = this.length - num.length; + var zeros = [ + '', + '0', + '00', + '000', + '0000', + '00000', + '000000', + '0000000', + '00000000', + '000000000', + '0000000000', + '00000000000', + '000000000000', + '0000000000000', + '00000000000000', + '000000000000000', + '0000000000000000', + '00000000000000000', + '000000000000000000', + '0000000000000000000', + '00000000000000000000', + '000000000000000000000', + '0000000000000000000000', + '00000000000000000000000', + '000000000000000000000000', + '0000000000000000000000000' + ]; - var a = this.clone(); - var b = num; + var groupSizes = [ + 0, 0, + 25, 16, 12, 11, 10, 9, 8, + 8, 7, 7, 7, 7, 6, 6, + 6, 6, 6, 6, 6, 5, 5, + 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5 + ]; - // Normalize - var bhi = b.words[b.length - 1] | 0; - var bhiBits = this._countBits(bhi); - shift = 26 - bhiBits; - if (shift !== 0) { - b = b.ushln(shift); - a.iushln(shift); - bhi = b.words[b.length - 1] | 0; - } + var groupBases = [ + 0, 0, + 33554432, 43046721, 16777216, 48828125, 60466176, 40353607, 16777216, + 43046721, 10000000, 19487171, 35831808, 62748517, 7529536, 11390625, + 16777216, 24137569, 34012224, 47045881, 64000000, 4084101, 5153632, + 6436343, 7962624, 9765625, 11881376, 14348907, 17210368, 20511149, + 24300000, 28629151, 33554432, 39135393, 45435424, 52521875, 60466176 + ]; - // Initialize quotient - var m = a.length - b.length; - var q; + BN.prototype.toString = function toString (base, padding) { + base = base || 10; + padding = padding | 0 || 1; - if (mode !== 'mod') { - q = new BN(null); - q.length = m + 1; - q.words = new Array(q.length); - for (var i = 0; i < q.length; i++) { - q.words[i] = 0; + var out; + if (base === 16 || base === 'hex') { + out = ''; + var off = 0; + var carry = 0; + for (var i = 0; i < this.length; i++) { + var w = this.words[i]; + var word = (((w << off) | carry) & 0xffffff).toString(16); + carry = (w >>> (24 - off)) & 0xffffff; + off += 2; + if (off >= 26) { + off -= 26; + i--; + } + if (carry !== 0 || i !== this.length - 1) { + out = zeros[6 - word.length] + word + out; + } else { + out = word + out; + } } - } - - var diff = a.clone()._ishlnsubmul(b, 1, m); - if (diff.negative === 0) { - a = diff; - if (q) { - q.words[m] = 1; + if (carry !== 0) { + out = carry.toString(16) + out; + } + while (out.length % padding !== 0) { + out = '0' + out; } + if (this.negative !== 0) { + out = '-' + out; + } + return out; } - for (var j = m - 1; j >= 0; j--) { - var qj = (a.words[b.length + j] | 0) * 0x4000000 + - (a.words[b.length + j - 1] | 0); - - // NOTE: (qj / bhi) is (0x3ffffff * 0x4000000 + 0x3ffffff) / 0x2000000 max - // (0x7ffffff) - qj = Math.min((qj / bhi) | 0, 0x3ffffff); + if (base === (base | 0) && base >= 2 && base <= 36) { + // var groupSize = Math.floor(BN.wordSize * Math.LN2 / Math.log(base)); + var groupSize = groupSizes[base]; + // var groupBase = Math.pow(base, groupSize); + var groupBase = groupBases[base]; + out = ''; + var c = this.clone(); + c.negative = 0; + while (!c.isZero()) { + var r = c.modrn(groupBase).toString(base); + c = c.idivn(groupBase); - a._ishlnsubmul(b, qj, j); - while (a.negative !== 0) { - qj--; - a.negative = 0; - a._ishlnsubmul(b, 1, j); - if (!a.isZero()) { - a.negative ^= 1; + if (!c.isZero()) { + out = zeros[groupSize - r.length] + r + out; + } else { + out = r + out; } } - if (q) { - q.words[j] = qj; + if (this.isZero()) { + out = '0' + out; } + while (out.length % padding !== 0) { + out = '0' + out; + } + if (this.negative !== 0) { + out = '-' + out; + } + return out; } - if (q) { - q._strip(); - } - a._strip(); - // Denormalize - if (mode !== 'div' && shift !== 0) { - a.iushrn(shift); + assert(false, 'Base should be between 2 and 36'); + }; + + BN.prototype.toNumber = function toNumber () { + var ret = this.words[0]; + if (this.length === 2) { + ret += this.words[1] * 0x4000000; + } else if (this.length === 3 && this.words[2] === 0x01) { + // NOTE: at this stage it is known that the top bit is set + ret += 0x10000000000000 + (this.words[1] * 0x4000000); + } else if (this.length > 2) { + assert(false, 'Number can only safely store up to 53 bits'); } + return (this.negative !== 0) ? -ret : ret; + }; - return { - div: q || null, - mod: a - }; + BN.prototype.toJSON = function toJSON () { + return this.toString(16, 2); }; - // NOTE: 1) `mode` can be set to `mod` to request mod only, - // to `div` to request div only, or be absent to - // request both div & mod - // 2) `positive` is true if unsigned mod is requested - BN.prototype.divmod = function divmod (num, mode, positive) { - assert(!num.isZero()); + if (Buffer) { + BN.prototype.toBuffer = function toBuffer (endian, length) { + return this.toArrayLike(Buffer, endian, length); + }; + } - if (this.isZero()) { - return { - div: new BN(0), - mod: new BN(0) - }; + BN.prototype.toArray = function toArray (endian, length) { + return this.toArrayLike(Array, endian, length); + }; + + var allocate = function allocate (ArrayType, size) { + if (ArrayType.allocUnsafe) { + return ArrayType.allocUnsafe(size); } + return new ArrayType(size); + }; - var div, mod, res; - if (this.negative !== 0 && num.negative === 0) { - res = this.neg().divmod(num, mode); + BN.prototype.toArrayLike = function toArrayLike (ArrayType, endian, length) { + this._strip(); - if (mode !== 'mod') { - div = res.div.neg(); + var byteLength = this.byteLength(); + var reqLength = length || Math.max(1, byteLength); + assert(byteLength <= reqLength, 'byte array longer than desired length'); + assert(reqLength > 0, 'Requested array length <= 0'); + + var res = allocate(ArrayType, reqLength); + var postfix = endian === 'le' ? 'LE' : 'BE'; + this['_toArrayLike' + postfix](res, byteLength); + return res; + }; + + BN.prototype._toArrayLikeLE = function _toArrayLikeLE (res, byteLength) { + var position = 0; + var carry = 0; + + for (var i = 0, shift = 0; i < this.length; i++) { + var word = (this.words[i] << shift) | carry; + + res[position++] = word & 0xff; + if (position < res.length) { + res[position++] = (word >> 8) & 0xff; + } + if (position < res.length) { + res[position++] = (word >> 16) & 0xff; } - if (mode !== 'div') { - mod = res.mod.neg(); - if (positive && mod.negative !== 0) { - mod.iadd(num); + if (shift === 6) { + if (position < res.length) { + res[position++] = (word >> 24) & 0xff; } + carry = 0; + shift = 0; + } else { + carry = word >>> 24; + shift += 2; } - - return { - div: div, - mod: mod - }; } - if (this.negative === 0 && num.negative !== 0) { - res = this.divmod(num.neg(), mode); + if (position < res.length) { + res[position++] = carry; - if (mode !== 'mod') { - div = res.div.neg(); + while (position < res.length) { + res[position++] = 0; } + } + }; - return { - div: div, - mod: res.mod - }; - } + BN.prototype._toArrayLikeBE = function _toArrayLikeBE (res, byteLength) { + var position = res.length - 1; + var carry = 0; - if ((this.negative & num.negative) !== 0) { - res = this.neg().divmod(num.neg(), mode); + for (var i = 0, shift = 0; i < this.length; i++) { + var word = (this.words[i] << shift) | carry; - if (mode !== 'div') { - mod = res.mod.neg(); - if (positive && mod.negative !== 0) { - mod.isub(num); - } + res[position--] = word & 0xff; + if (position >= 0) { + res[position--] = (word >> 8) & 0xff; + } + if (position >= 0) { + res[position--] = (word >> 16) & 0xff; } - return { - div: res.div, - mod: mod - }; + if (shift === 6) { + if (position >= 0) { + res[position--] = (word >> 24) & 0xff; + } + carry = 0; + shift = 0; + } else { + carry = word >>> 24; + shift += 2; + } } - // Both numbers are positive at this point + if (position >= 0) { + res[position--] = carry; - // Strip both numbers to approximate shift value - if (num.length > this.length || this.cmp(num) < 0) { - return { - div: new BN(0), - mod: this - }; + while (position >= 0) { + res[position--] = 0; + } } + }; - // Very short reduction - if (num.length === 1) { - if (mode === 'div') { - return { - div: this.divn(num.words[0]), - mod: null - }; + if (Math.clz32) { + BN.prototype._countBits = function _countBits (w) { + return 32 - Math.clz32(w); + }; + } else { + BN.prototype._countBits = function _countBits (w) { + var t = w; + var r = 0; + if (t >= 0x1000) { + r += 13; + t >>>= 13; } - - if (mode === 'mod') { - return { - div: null, - mod: new BN(this.modrn(num.words[0])) - }; + if (t >= 0x40) { + r += 7; + t >>>= 7; } + if (t >= 0x8) { + r += 4; + t >>>= 4; + } + if (t >= 0x02) { + r += 2; + t >>>= 2; + } + return r + t; + }; + } - return { - div: this.divn(num.words[0]), - mod: new BN(this.modrn(num.words[0])) - }; - } - - return this._wordDiv(num, mode); - }; - - // Find `this` / `num` - BN.prototype.div = function div (num) { - return this.divmod(num, 'div', false).div; - }; + BN.prototype._zeroBits = function _zeroBits (w) { + // Short-cut + if (w === 0) return 26; - // Find `this` % `num` - BN.prototype.mod = function mod (num) { - return this.divmod(num, 'mod', false).mod; + var t = w; + var r = 0; + if ((t & 0x1fff) === 0) { + r += 13; + t >>>= 13; + } + if ((t & 0x7f) === 0) { + r += 7; + t >>>= 7; + } + if ((t & 0xf) === 0) { + r += 4; + t >>>= 4; + } + if ((t & 0x3) === 0) { + r += 2; + t >>>= 2; + } + if ((t & 0x1) === 0) { + r++; + } + return r; }; - BN.prototype.umod = function umod (num) { - return this.divmod(num, 'mod', true).mod; + // Return number of used bits in a BN + BN.prototype.bitLength = function bitLength () { + var w = this.words[this.length - 1]; + var hi = this._countBits(w); + return (this.length - 1) * 26 + hi; }; - // Find Round(`this` / `num`) - BN.prototype.divRound = function divRound (num) { - var dm = this.divmod(num); + function toBitArray (num) { + var w = new Array(num.bitLength()); - // Fast case - exact division - if (dm.mod.isZero()) return dm.div; + for (var bit = 0; bit < w.length; bit++) { + var off = (bit / 26) | 0; + var wbit = bit % 26; - var mod = dm.div.negative !== 0 ? dm.mod.isub(num) : dm.mod; + w[bit] = (num.words[off] >>> wbit) & 0x01; + } - var half = num.ushrn(1); - var r2 = num.andln(1); - var cmp = mod.cmp(half); + return w; + } - // Round down - if (cmp < 0 || (r2 === 1 && cmp === 0)) return dm.div; + // Number of trailing zero bits + BN.prototype.zeroBits = function zeroBits () { + if (this.isZero()) return 0; - // Round up - return dm.div.negative !== 0 ? dm.div.isubn(1) : dm.div.iaddn(1); + var r = 0; + for (var i = 0; i < this.length; i++) { + var b = this._zeroBits(this.words[i]); + r += b; + if (b !== 26) break; + } + return r; }; - BN.prototype.modrn = function modrn (num) { - var isNegNum = num < 0; - if (isNegNum) num = -num; + BN.prototype.byteLength = function byteLength () { + return Math.ceil(this.bitLength() / 8); + }; - assert(num <= 0x3ffffff); - var p = (1 << 26) % num; + BN.prototype.toTwos = function toTwos (width) { + if (this.negative !== 0) { + return this.abs().inotn(width).iaddn(1); + } + return this.clone(); + }; - var acc = 0; - for (var i = this.length - 1; i >= 0; i--) { - acc = (p * acc + (this.words[i] | 0)) % num; + BN.prototype.fromTwos = function fromTwos (width) { + if (this.testn(width - 1)) { + return this.notn(width).iaddn(1).ineg(); } + return this.clone(); + }; - return isNegNum ? -acc : acc; + BN.prototype.isNeg = function isNeg () { + return this.negative !== 0; }; - // WARNING: DEPRECATED - BN.prototype.modn = function modn (num) { - return this.modrn(num); + // Return negative clone of `this` + BN.prototype.neg = function neg () { + return this.clone().ineg(); }; - // In-place division by number - BN.prototype.idivn = function idivn (num) { - var isNegNum = num < 0; - if (isNegNum) num = -num; + BN.prototype.ineg = function ineg () { + if (!this.isZero()) { + this.negative ^= 1; + } - assert(num <= 0x3ffffff); + return this; + }; - var carry = 0; - for (var i = this.length - 1; i >= 0; i--) { - var w = (this.words[i] | 0) + carry * 0x4000000; - this.words[i] = (w / num) | 0; - carry = w % num; + // Or `num` with `this` in-place + BN.prototype.iuor = function iuor (num) { + while (this.length < num.length) { + this.words[this.length++] = 0; } - this._strip(); - return isNegNum ? this.ineg() : this; + for (var i = 0; i < num.length; i++) { + this.words[i] = this.words[i] | num.words[i]; + } + + return this._strip(); }; - BN.prototype.divn = function divn (num) { - return this.clone().idivn(num); + BN.prototype.ior = function ior (num) { + assert((this.negative | num.negative) === 0); + return this.iuor(num); }; - BN.prototype.egcd = function egcd (p) { - assert(p.negative === 0); - assert(!p.isZero()); + // Or `num` with `this` + BN.prototype.or = function or (num) { + if (this.length > num.length) return this.clone().ior(num); + return num.clone().ior(this); + }; - var x = this; - var y = p.clone(); + BN.prototype.uor = function uor (num) { + if (this.length > num.length) return this.clone().iuor(num); + return num.clone().iuor(this); + }; - if (x.negative !== 0) { - x = x.umod(p); + // And `num` with `this` in-place + BN.prototype.iuand = function iuand (num) { + // b = min-length(num, this) + var b; + if (this.length > num.length) { + b = num; } else { - x = x.clone(); + b = this; } - // A * x + B * y = x - var A = new BN(1); - var B = new BN(0); - - // C * x + D * y = y - var C = new BN(0); - var D = new BN(1); - - var g = 0; - - while (x.isEven() && y.isEven()) { - x.iushrn(1); - y.iushrn(1); - ++g; + for (var i = 0; i < b.length; i++) { + this.words[i] = this.words[i] & num.words[i]; } - var yp = y.clone(); - var xp = x.clone(); + this.length = b.length; - while (!x.isZero()) { - for (var i = 0, im = 1; (x.words[0] & im) === 0 && i < 26; ++i, im <<= 1); - if (i > 0) { - x.iushrn(i); - while (i-- > 0) { - if (A.isOdd() || B.isOdd()) { - A.iadd(yp); - B.isub(xp); - } + return this._strip(); + }; - A.iushrn(1); - B.iushrn(1); - } - } + BN.prototype.iand = function iand (num) { + assert((this.negative | num.negative) === 0); + return this.iuand(num); + }; - for (var j = 0, jm = 1; (y.words[0] & jm) === 0 && j < 26; ++j, jm <<= 1); - if (j > 0) { - y.iushrn(j); - while (j-- > 0) { - if (C.isOdd() || D.isOdd()) { - C.iadd(yp); - D.isub(xp); - } + // And `num` with `this` + BN.prototype.and = function and (num) { + if (this.length > num.length) return this.clone().iand(num); + return num.clone().iand(this); + }; - C.iushrn(1); - D.iushrn(1); - } - } + BN.prototype.uand = function uand (num) { + if (this.length > num.length) return this.clone().iuand(num); + return num.clone().iuand(this); + }; - if (x.cmp(y) >= 0) { - x.isub(y); - A.isub(C); - B.isub(D); - } else { - y.isub(x); - C.isub(A); - D.isub(B); - } + // Xor `num` with `this` in-place + BN.prototype.iuxor = function iuxor (num) { + // a.length > b.length + var a; + var b; + if (this.length > num.length) { + a = this; + b = num; + } else { + a = num; + b = this; } - return { - a: C, - b: D, - gcd: y.iushln(g) - }; - }; + for (var i = 0; i < b.length; i++) { + this.words[i] = a.words[i] ^ b.words[i]; + } - // This is reduced incarnation of the binary EEA - // above, designated to invert members of the - // _prime_ fields F(p) at a maximal speed - BN.prototype._invmp = function _invmp (p) { - assert(p.negative === 0); - assert(!p.isZero()); + if (this !== a) { + for (; i < a.length; i++) { + this.words[i] = a.words[i]; + } + } - var a = this; - var b = p.clone(); + this.length = a.length; - if (a.negative !== 0) { - a = a.umod(p); - } else { - a = a.clone(); - } + return this._strip(); + }; - var x1 = new BN(1); - var x2 = new BN(0); + BN.prototype.ixor = function ixor (num) { + assert((this.negative | num.negative) === 0); + return this.iuxor(num); + }; - var delta = b.clone(); + // Xor `num` with `this` + BN.prototype.xor = function xor (num) { + if (this.length > num.length) return this.clone().ixor(num); + return num.clone().ixor(this); + }; - while (a.cmpn(1) > 0 && b.cmpn(1) > 0) { - for (var i = 0, im = 1; (a.words[0] & im) === 0 && i < 26; ++i, im <<= 1); - if (i > 0) { - a.iushrn(i); - while (i-- > 0) { - if (x1.isOdd()) { - x1.iadd(delta); - } + BN.prototype.uxor = function uxor (num) { + if (this.length > num.length) return this.clone().iuxor(num); + return num.clone().iuxor(this); + }; - x1.iushrn(1); - } - } + // Not ``this`` with ``width`` bitwidth + BN.prototype.inotn = function inotn (width) { + assert(typeof width === 'number' && width >= 0); - for (var j = 0, jm = 1; (b.words[0] & jm) === 0 && j < 26; ++j, jm <<= 1); - if (j > 0) { - b.iushrn(j); - while (j-- > 0) { - if (x2.isOdd()) { - x2.iadd(delta); - } + var bytesNeeded = Math.ceil(width / 26) | 0; + var bitsLeft = width % 26; - x2.iushrn(1); - } - } + // Extend the buffer with leading zeroes + this._expand(bytesNeeded); - if (a.cmp(b) >= 0) { - a.isub(b); - x1.isub(x2); - } else { - b.isub(a); - x2.isub(x1); - } + if (bitsLeft > 0) { + bytesNeeded--; } - var res; - if (a.cmpn(1) === 0) { - res = x1; - } else { - res = x2; + // Handle complete words + for (var i = 0; i < bytesNeeded; i++) { + this.words[i] = ~this.words[i] & 0x3ffffff; } - if (res.cmpn(0) < 0) { - res.iadd(p); + // Handle the residue + if (bitsLeft > 0) { + this.words[i] = ~this.words[i] & (0x3ffffff >> (26 - bitsLeft)); } - return res; + // And remove leading zeroes + return this._strip(); }; - BN.prototype.gcd = function gcd (num) { - if (this.isZero()) return num.abs(); - if (num.isZero()) return this.abs(); - - var a = this.clone(); - var b = num.clone(); - a.negative = 0; - b.negative = 0; - - // Remove common factor of two - for (var shift = 0; a.isEven() && b.isEven(); shift++) { - a.iushrn(1); - b.iushrn(1); - } + BN.prototype.notn = function notn (width) { + return this.clone().inotn(width); + }; - do { - while (a.isEven()) { - a.iushrn(1); - } - while (b.isEven()) { - b.iushrn(1); - } + // Set `bit` of `this` + BN.prototype.setn = function setn (bit, val) { + assert(typeof bit === 'number' && bit >= 0); - var r = a.cmp(b); - if (r < 0) { - // Swap `a` and `b` to make `a` always bigger than `b` - var t = a; - a = b; - b = t; - } else if (r === 0 || b.cmpn(1) === 0) { - break; - } + var off = (bit / 26) | 0; + var wbit = bit % 26; - a.isub(b); - } while (true); + this._expand(off + 1); - return b.iushln(shift); - }; + if (val) { + this.words[off] = this.words[off] | (1 << wbit); + } else { + this.words[off] = this.words[off] & ~(1 << wbit); + } - // Invert number in the field F(num) - BN.prototype.invm = function invm (num) { - return this.egcd(num).a.umod(num); + return this._strip(); }; - BN.prototype.isEven = function isEven () { - return (this.words[0] & 1) === 0; - }; + // Add `num` to `this` in-place + BN.prototype.iadd = function iadd (num) { + var r; - BN.prototype.isOdd = function isOdd () { - return (this.words[0] & 1) === 1; - }; + // negative + positive + if (this.negative !== 0 && num.negative === 0) { + this.negative = 0; + r = this.isub(num); + this.negative ^= 1; + return this._normSign(); - // And first word and num - BN.prototype.andln = function andln (num) { - return this.words[0] & num; - }; + // positive + negative + } else if (this.negative === 0 && num.negative !== 0) { + num.negative = 0; + r = this.isub(num); + num.negative = 1; + return r._normSign(); + } - // Increment at the bit position in-line - BN.prototype.bincn = function bincn (bit) { - assert(typeof bit === 'number'); - var r = bit % 26; - var s = (bit - r) / 26; - var q = 1 << r; - - // Fast case: bit is much higher than all existing words - if (this.length <= s) { - this._expand(s + 1); - this.words[s] |= q; - return this; + // a.length > b.length + var a, b; + if (this.length > num.length) { + a = this; + b = num; + } else { + a = num; + b = this; } - // Add bit and propagate, if needed - var carry = q; - for (var i = s; carry !== 0 && i < this.length; i++) { - var w = this.words[i] | 0; - w += carry; - carry = w >>> 26; - w &= 0x3ffffff; - this.words[i] = w; + var carry = 0; + for (var i = 0; i < b.length; i++) { + r = (a.words[i] | 0) + (b.words[i] | 0) + carry; + this.words[i] = r & 0x3ffffff; + carry = r >>> 26; + } + for (; carry !== 0 && i < a.length; i++) { + r = (a.words[i] | 0) + carry; + this.words[i] = r & 0x3ffffff; + carry = r >>> 26; } + + this.length = a.length; if (carry !== 0) { - this.words[i] = carry; + this.words[this.length] = carry; this.length++; + // Copy the rest of the words + } else if (a !== this) { + for (; i < a.length; i++) { + this.words[i] = a.words[i]; + } } - return this; - }; - BN.prototype.isZero = function isZero () { - return this.length === 1 && this.words[0] === 0; + return this; }; - BN.prototype.cmpn = function cmpn (num) { - var negative = num < 0; - - if (this.negative !== 0 && !negative) return -1; - if (this.negative === 0 && negative) return 1; - - this._strip(); - + // Add `num` to `this` + BN.prototype.add = function add (num) { var res; - if (this.length > 1) { - res = 1; - } else { - if (negative) { - num = -num; - } - - assert(num <= 0x3ffffff, 'Number is too big'); - - var w = this.words[0] | 0; - res = w === num ? 0 : w < num ? -1 : 1; + if (num.negative !== 0 && this.negative === 0) { + num.negative = 0; + res = this.sub(num); + num.negative ^= 1; + return res; + } else if (num.negative === 0 && this.negative !== 0) { + this.negative = 0; + res = num.sub(this); + this.negative = 1; + return res; } - if (this.negative !== 0) return -res | 0; - return res; - }; - // Compare two numbers and return: - // 1 - if `this` > `num` - // 0 - if `this` == `num` - // -1 - if `this` < `num` - BN.prototype.cmp = function cmp (num) { - if (this.negative !== 0 && num.negative === 0) return -1; - if (this.negative === 0 && num.negative !== 0) return 1; + if (this.length > num.length) return this.clone().iadd(num); - var res = this.ucmp(num); - if (this.negative !== 0) return -res | 0; - return res; + return num.clone().iadd(this); }; - // Unsigned comparison - BN.prototype.ucmp = function ucmp (num) { - // At this point both numbers have the same sign - if (this.length > num.length) return 1; - if (this.length < num.length) return -1; - - var res = 0; - for (var i = this.length - 1; i >= 0; i--) { - var a = this.words[i] | 0; - var b = num.words[i] | 0; + // Subtract `num` from `this` in-place + BN.prototype.isub = function isub (num) { + // this - (-num) = this + num + if (num.negative !== 0) { + num.negative = 0; + var r = this.iadd(num); + num.negative = 1; + return r._normSign(); - if (a === b) continue; - if (a < b) { - res = -1; - } else if (a > b) { - res = 1; - } - break; + // -this - num = -(this + num) + } else if (this.negative !== 0) { + this.negative = 0; + this.iadd(num); + this.negative = 1; + return this._normSign(); } - return res; - }; - - BN.prototype.gtn = function gtn (num) { - return this.cmpn(num) === 1; - }; - - BN.prototype.gt = function gt (num) { - return this.cmp(num) === 1; - }; - - BN.prototype.gten = function gten (num) { - return this.cmpn(num) >= 0; - }; - - BN.prototype.gte = function gte (num) { - return this.cmp(num) >= 0; - }; - - BN.prototype.ltn = function ltn (num) { - return this.cmpn(num) === -1; - }; - - BN.prototype.lt = function lt (num) { - return this.cmp(num) === -1; - }; - - BN.prototype.lten = function lten (num) { - return this.cmpn(num) <= 0; - }; - - BN.prototype.lte = function lte (num) { - return this.cmp(num) <= 0; - }; - - BN.prototype.eqn = function eqn (num) { - return this.cmpn(num) === 0; - }; - - BN.prototype.eq = function eq (num) { - return this.cmp(num) === 0; - }; - - // - // A reduce context, could be using montgomery or something better, depending - // on the `m` itself. - // - BN.red = function red (num) { - return new Red(num); - }; - - BN.prototype.toRed = function toRed (ctx) { - assert(!this.red, 'Already a number in reduction context'); - assert(this.negative === 0, 'red works only with positives'); - return ctx.convertTo(this)._forceRed(ctx); - }; - - BN.prototype.fromRed = function fromRed () { - assert(this.red, 'fromRed works only with numbers in reduction context'); - return this.red.convertFrom(this); - }; - - BN.prototype._forceRed = function _forceRed (ctx) { - this.red = ctx; - return this; - }; - - BN.prototype.forceRed = function forceRed (ctx) { - assert(!this.red, 'Already a number in reduction context'); - return this._forceRed(ctx); - }; - - BN.prototype.redAdd = function redAdd (num) { - assert(this.red, 'redAdd works only with red numbers'); - return this.red.add(this, num); - }; - - BN.prototype.redIAdd = function redIAdd (num) { - assert(this.red, 'redIAdd works only with red numbers'); - return this.red.iadd(this, num); - }; - - BN.prototype.redSub = function redSub (num) { - assert(this.red, 'redSub works only with red numbers'); - return this.red.sub(this, num); - }; - - BN.prototype.redISub = function redISub (num) { - assert(this.red, 'redISub works only with red numbers'); - return this.red.isub(this, num); - }; - - BN.prototype.redShl = function redShl (num) { - assert(this.red, 'redShl works only with red numbers'); - return this.red.shl(this, num); - }; - - BN.prototype.redMul = function redMul (num) { - assert(this.red, 'redMul works only with red numbers'); - this.red._verify2(this, num); - return this.red.mul(this, num); - }; - - BN.prototype.redIMul = function redIMul (num) { - assert(this.red, 'redMul works only with red numbers'); - this.red._verify2(this, num); - return this.red.imul(this, num); - }; - - BN.prototype.redSqr = function redSqr () { - assert(this.red, 'redSqr works only with red numbers'); - this.red._verify1(this); - return this.red.sqr(this); - }; - - BN.prototype.redISqr = function redISqr () { - assert(this.red, 'redISqr works only with red numbers'); - this.red._verify1(this); - return this.red.isqr(this); - }; - - // Square root over p - BN.prototype.redSqrt = function redSqrt () { - assert(this.red, 'redSqrt works only with red numbers'); - this.red._verify1(this); - return this.red.sqrt(this); - }; - - BN.prototype.redInvm = function redInvm () { - assert(this.red, 'redInvm works only with red numbers'); - this.red._verify1(this); - return this.red.invm(this); - }; - - // Return negative clone of `this` % `red modulo` - BN.prototype.redNeg = function redNeg () { - assert(this.red, 'redNeg works only with red numbers'); - this.red._verify1(this); - return this.red.neg(this); - }; - - BN.prototype.redPow = function redPow (num) { - assert(this.red && !num.red, 'redPow(normalNum)'); - this.red._verify1(this); - return this.red.pow(this, num); - }; - - // Prime numbers with efficient reduction - var primes = { - k256: null, - p224: null, - p192: null, - p25519: null - }; - - // Pseudo-Mersenne prime - function MPrime (name, p) { - // P = 2 ^ N - K - this.name = name; - this.p = new BN(p, 16); - this.n = this.p.bitLength(); - this.k = new BN(1).iushln(this.n).isub(this.p); - this.tmp = this._tmp(); - } - - MPrime.prototype._tmp = function _tmp () { - var tmp = new BN(null); - tmp.words = new Array(Math.ceil(this.n / 13)); - return tmp; - }; - - MPrime.prototype.ireduce = function ireduce (num) { - // Assumes that `num` is less than `P^2` - // num = HI * (2 ^ N - K) + HI * K + LO = HI * K + LO (mod P) - var r = num; - var rlen; - - do { - this.split(r, this.tmp); - r = this.imulK(r); - r = r.iadd(this.tmp); - rlen = r.bitLength(); - } while (rlen > this.n); + // At this point both numbers are positive + var cmp = this.cmp(num); - var cmp = rlen < this.n ? -1 : r.ucmp(this.p); + // Optimization - zeroify if (cmp === 0) { - r.words[0] = 0; - r.length = 1; - } else if (cmp > 0) { - r.isub(this.p); - } else { - if (r.strip !== undefined) { - // r is a BN v4 instance - r.strip(); - } else { - // r is a BN v5 instance - r._strip(); - } + this.negative = 0; + this.length = 1; + this.words[0] = 0; + return this; } - return r; - }; - - MPrime.prototype.split = function split (input, out) { - input.iushrn(this.n, 0, out); - }; - - MPrime.prototype.imulK = function imulK (num) { - return num.imul(this.k); - }; - - function K256 () { - MPrime.call( - this, - 'k256', - 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe fffffc2f'); - } - inherits(K256, MPrime); - - K256.prototype.split = function split (input, output) { - // 256 = 9 * 26 + 22 - var mask = 0x3fffff; - - var outLen = Math.min(input.length, 9); - for (var i = 0; i < outLen; i++) { - output.words[i] = input.words[i]; + // a > b + var a, b; + if (cmp > 0) { + a = this; + b = num; + } else { + a = num; + b = this; } - output.length = outLen; - if (input.length <= 9) { - input.words[0] = 0; - input.length = 1; - return; + var carry = 0; + for (var i = 0; i < b.length; i++) { + r = (a.words[i] | 0) - (b.words[i] | 0) + carry; + carry = r >> 26; + this.words[i] = r & 0x3ffffff; } - - // Shift by 9 limbs - var prev = input.words[9]; - output.words[output.length++] = prev & mask; - - for (i = 10; i < input.length; i++) { - var next = input.words[i] | 0; - input.words[i - 10] = ((next & mask) << 4) | (prev >>> 22); - prev = next; + for (; carry !== 0 && i < a.length; i++) { + r = (a.words[i] | 0) + carry; + carry = r >> 26; + this.words[i] = r & 0x3ffffff; } - prev >>>= 22; - input.words[i - 10] = prev; - if (prev === 0 && input.length > 10) { - input.length -= 10; - } else { - input.length -= 9; + + // Copy rest of the words + if (carry === 0 && i < a.length && a !== this) { + for (; i < a.length; i++) { + this.words[i] = a.words[i]; + } } - }; - K256.prototype.imulK = function imulK (num) { - // K = 0x1000003d1 = [ 0x40, 0x3d1 ] - num.words[num.length] = 0; - num.words[num.length + 1] = 0; - num.length += 2; + this.length = Math.max(this.length, i); - // bounded at: 0x40 * 0x3ffffff + 0x3d0 = 0x100000390 - var lo = 0; - for (var i = 0; i < num.length; i++) { - var w = num.words[i] | 0; - lo += w * 0x3d1; - num.words[i] = lo & 0x3ffffff; - lo = w * 0x40 + ((lo / 0x4000000) | 0); + if (a !== this) { + this.negative = 1; } - // Fast length reduction - if (num.words[num.length - 1] === 0) { - num.length--; - if (num.words[num.length - 1] === 0) { - num.length--; - } - } - return num; + return this._strip(); }; - function P224 () { - MPrime.call( - this, - 'p224', - 'ffffffff ffffffff ffffffff ffffffff 00000000 00000000 00000001'); - } - inherits(P224, MPrime); + // Subtract `num` from `this` + BN.prototype.sub = function sub (num) { + return this.clone().isub(num); + }; - function P192 () { - MPrime.call( - this, - 'p192', - 'ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff'); - } - inherits(P192, MPrime); + function smallMulTo (self, num, out) { + out.negative = num.negative ^ self.negative; + var len = (self.length + num.length) | 0; + out.length = len; + len = (len - 1) | 0; - function P25519 () { - // 2 ^ 255 - 19 - MPrime.call( - this, - '25519', - '7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed'); - } - inherits(P25519, MPrime); + // Peel one iteration (compiler can't do it, because of code complexity) + var a = self.words[0] | 0; + var b = num.words[0] | 0; + var r = a * b; - P25519.prototype.imulK = function imulK (num) { - // K = 0x13 - var carry = 0; - for (var i = 0; i < num.length; i++) { - var hi = (num.words[i] | 0) * 0x13 + carry; - var lo = hi & 0x3ffffff; - hi >>>= 26; + var lo = r & 0x3ffffff; + var carry = (r / 0x4000000) | 0; + out.words[0] = lo; - num.words[i] = lo; - carry = hi; + for (var k = 1; k < len; k++) { + // Sum all words with the same `i + j = k` and accumulate `ncarry`, + // note that ncarry could be >= 0x3ffffff + var ncarry = carry >>> 26; + var rword = carry & 0x3ffffff; + var maxJ = Math.min(k, num.length - 1); + for (var j = Math.max(0, k - self.length + 1); j <= maxJ; j++) { + var i = (k - j) | 0; + a = self.words[i] | 0; + b = num.words[j] | 0; + r = a * b + rword; + ncarry += (r / 0x4000000) | 0; + rword = r & 0x3ffffff; + } + out.words[k] = rword | 0; + carry = ncarry | 0; } if (carry !== 0) { - num.words[num.length++] = carry; - } - return num; - }; - - // Exported mostly for testing purposes, use plain name instead - BN._prime = function prime (name) { - // Cached version of prime - if (primes[name]) return primes[name]; - - var prime; - if (name === 'k256') { - prime = new K256(); - } else if (name === 'p224') { - prime = new P224(); - } else if (name === 'p192') { - prime = new P192(); - } else if (name === 'p25519') { - prime = new P25519(); + out.words[k] = carry | 0; } else { - throw new Error('Unknown prime ' + name); + out.length--; } - primes[name] = prime; - - return prime; - }; - // - // Base reduction engine - // - function Red (m) { - if (typeof m === 'string') { - var prime = BN._prime(m); - this.m = prime.p; - this.prime = prime; - } else { - assert(m.gtn(1), 'modulus must be greater than 1'); - this.m = m; - this.prime = null; - } - } - - Red.prototype._verify1 = function _verify1 (a) { - assert(a.negative === 0, 'red works only with positives'); - assert(a.red, 'red works only with red numbers'); - }; - - Red.prototype._verify2 = function _verify2 (a, b) { - assert((a.negative | b.negative) === 0, 'red works only with positives'); - assert(a.red && a.red === b.red, - 'red works only with red numbers'); - }; - - Red.prototype.imod = function imod (a) { - if (this.prime) return this.prime.ireduce(a)._forceRed(this); - - move(a, a.umod(this.m)._forceRed(this)); - return a; - }; - - Red.prototype.neg = function neg (a) { - if (a.isZero()) { - return a.clone(); - } - - return this.m.sub(a)._forceRed(this); - }; - - Red.prototype.add = function add (a, b) { - this._verify2(a, b); - - var res = a.add(b); - if (res.cmp(this.m) >= 0) { - res.isub(this.m); - } - return res._forceRed(this); - }; - - Red.prototype.iadd = function iadd (a, b) { - this._verify2(a, b); - - var res = a.iadd(b); - if (res.cmp(this.m) >= 0) { - res.isub(this.m); - } - return res; - }; - - Red.prototype.sub = function sub (a, b) { - this._verify2(a, b); - - var res = a.sub(b); - if (res.cmpn(0) < 0) { - res.iadd(this.m); - } - return res._forceRed(this); - }; - - Red.prototype.isub = function isub (a, b) { - this._verify2(a, b); - - var res = a.isub(b); - if (res.cmpn(0) < 0) { - res.iadd(this.m); - } - return res; - }; - - Red.prototype.shl = function shl (a, num) { - this._verify1(a); - return this.imod(a.ushln(num)); - }; - - Red.prototype.imul = function imul (a, b) { - this._verify2(a, b); - return this.imod(a.imul(b)); - }; - - Red.prototype.mul = function mul (a, b) { - this._verify2(a, b); - return this.imod(a.mul(b)); - }; - - Red.prototype.isqr = function isqr (a) { - return this.imul(a, a.clone()); - }; - - Red.prototype.sqr = function sqr (a) { - return this.mul(a, a); - }; - - Red.prototype.sqrt = function sqrt (a) { - if (a.isZero()) return a.clone(); - - var mod3 = this.m.andln(3); - assert(mod3 % 2 === 1); - - // Fast case - if (mod3 === 3) { - var pow = this.m.add(new BN(1)).iushrn(2); - return this.pow(a, pow); - } - - // Tonelli-Shanks algorithm (Totally unoptimized and slow) - // - // Find Q and S, that Q * 2 ^ S = (P - 1) - var q = this.m.subn(1); - var s = 0; - while (!q.isZero() && q.andln(1) === 0) { - s++; - q.iushrn(1); - } - assert(!q.isZero()); - - var one = new BN(1).toRed(this); - var nOne = one.redNeg(); - - // Find quadratic non-residue - // NOTE: Max is such because of generalized Riemann hypothesis. - var lpow = this.m.subn(1).iushrn(1); - var z = this.m.bitLength(); - z = new BN(2 * z * z).toRed(this); - - while (this.pow(z, lpow).cmp(nOne) !== 0) { - z.redIAdd(nOne); - } - - var c = this.pow(z, q); - var r = this.pow(a, q.addn(1).iushrn(1)); - var t = this.pow(a, q); - var m = s; - while (t.cmp(one) !== 0) { - var tmp = t; - for (var i = 0; tmp.cmp(one) !== 0; i++) { - tmp = tmp.redSqr(); - } - assert(i < m); - var b = this.pow(c, new BN(1).iushln(m - i - 1)); - - r = r.redMul(b); - c = b.redSqr(); - t = t.redMul(c); - m = i; - } - - return r; - }; - - Red.prototype.invm = function invm (a) { - var inv = a._invmp(this.m); - if (inv.negative !== 0) { - inv.negative = 0; - return this.imod(inv).redNeg(); - } else { - return this.imod(inv); - } - }; - - Red.prototype.pow = function pow (a, num) { - if (num.isZero()) return new BN(1).toRed(this); - if (num.cmpn(1) === 0) return a.clone(); - - var windowSize = 4; - var wnd = new Array(1 << windowSize); - wnd[0] = new BN(1).toRed(this); - wnd[1] = a; - for (var i = 2; i < wnd.length; i++) { - wnd[i] = this.mul(wnd[i - 1], a); - } - - var res = wnd[0]; - var current = 0; - var currentLen = 0; - var start = num.bitLength() % 26; - if (start === 0) { - start = 26; - } - - for (i = num.length - 1; i >= 0; i--) { - var word = num.words[i]; - for (var j = start - 1; j >= 0; j--) { - var bit = (word >> j) & 1; - if (res !== wnd[0]) { - res = this.sqr(res); - } - - if (bit === 0 && current === 0) { - currentLen = 0; - continue; - } - - current <<= 1; - current |= bit; - currentLen++; - if (currentLen !== windowSize && (i !== 0 || j !== 0)) continue; - - res = this.mul(res, wnd[current]); - currentLen = 0; - current = 0; - } - start = 26; - } - - return res; - }; - - Red.prototype.convertTo = function convertTo (num) { - var r = num.umod(this.m); - - return r === num ? r.clone() : r; - }; - - Red.prototype.convertFrom = function convertFrom (num) { - var res = num.clone(); - res.red = null; - return res; - }; - - // - // Montgomery method engine - // - - BN.mont = function mont (num) { - return new Mont(num); - }; - - function Mont (m) { - Red.call(this, m); - - this.shift = this.m.bitLength(); - if (this.shift % 26 !== 0) { - this.shift += 26 - (this.shift % 26); - } - - this.r = new BN(1).iushln(this.shift); - this.r2 = this.imod(this.r.sqr()); - this.rinv = this.r._invmp(this.m); - - this.minv = this.rinv.mul(this.r).isubn(1).div(this.m); - this.minv = this.minv.umod(this.r); - this.minv = this.r.sub(this.minv); - } - inherits(Mont, Red); - - Mont.prototype.convertTo = function convertTo (num) { - return this.imod(num.ushln(this.shift)); - }; - - Mont.prototype.convertFrom = function convertFrom (num) { - var r = this.imod(num.mul(this.rinv)); - r.red = null; - return r; - }; - - Mont.prototype.imul = function imul (a, b) { - if (a.isZero() || b.isZero()) { - a.words[0] = 0; - a.length = 1; - return a; - } - - var t = a.imul(b); - var c = t.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m); - var u = t.isub(c).iushrn(this.shift); - var res = u; - - if (u.cmp(this.m) >= 0) { - res = u.isub(this.m); - } else if (u.cmpn(0) < 0) { - res = u.iadd(this.m); - } - - return res._forceRed(this); - }; - - Mont.prototype.mul = function mul (a, b) { - if (a.isZero() || b.isZero()) return new BN(0)._forceRed(this); - - var t = a.mul(b); - var c = t.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m); - var u = t.isub(c).iushrn(this.shift); - var res = u; - if (u.cmp(this.m) >= 0) { - res = u.isub(this.m); - } else if (u.cmpn(0) < 0) { - res = u.iadd(this.m); - } - - return res._forceRed(this); - }; - - Mont.prototype.invm = function invm (a) { - // (AR)^-1 * R^2 = (A^-1 * R^-1) * R^2 = A^-1 * R - var res = this.imod(a._invmp(this.m).mul(this.r2)); - return res._forceRed(this); - }; -})(typeof module === 'undefined' || module, this); - -},{"buffer":93}],92:[function(require,module,exports){ -var r; - -module.exports = function rand(len) { - if (!r) - r = new Rand(null); - - return r.generate(len); -}; - -function Rand(rand) { - this.rand = rand; -} -module.exports.Rand = Rand; - -Rand.prototype.generate = function generate(len) { - return this._rand(len); -}; - -// Emulate crypto API using randy -Rand.prototype._rand = function _rand(n) { - if (this.rand.getBytes) - return this.rand.getBytes(n); - - var res = new Uint8Array(n); - for (var i = 0; i < res.length; i++) - res[i] = this.rand.getByte(); - return res; -}; - -if (typeof self === 'object') { - if (self.crypto && self.crypto.getRandomValues) { - // Modern browsers - Rand.prototype._rand = function _rand(n) { - var arr = new Uint8Array(n); - self.crypto.getRandomValues(arr); - return arr; - }; - } else if (self.msCrypto && self.msCrypto.getRandomValues) { - // IE - Rand.prototype._rand = function _rand(n) { - var arr = new Uint8Array(n); - self.msCrypto.getRandomValues(arr); - return arr; - }; - - // Safari's WebWorkers do not have `crypto` - } else if (typeof window === 'object') { - // Old junk - Rand.prototype._rand = function() { - throw new Error('Not implemented yet'); - }; - } -} else { - // Node.js or Web worker with no crypto support - try { - var crypto = require('crypto'); - if (typeof crypto.randomBytes !== 'function') - throw new Error('Not supported'); - - Rand.prototype._rand = function _rand(n) { - return crypto.randomBytes(n); - }; - } catch (e) { - } -} - -},{"crypto":93}],93:[function(require,module,exports){ - -},{}],94:[function(require,module,exports){ -// based on the aes implimentation in triple sec -// https://github.com/keybase/triplesec -// which is in turn based on the one from crypto-js -// https://code.google.com/p/crypto-js/ - -var Buffer = require('safe-buffer').Buffer - -function asUInt32Array (buf) { - if (!Buffer.isBuffer(buf)) buf = Buffer.from(buf) - - var len = (buf.length / 4) | 0 - var out = new Array(len) - - for (var i = 0; i < len; i++) { - out[i] = buf.readUInt32BE(i * 4) - } - - return out -} - -function scrubVec (v) { - for (var i = 0; i < v.length; v++) { - v[i] = 0 - } -} - -function cryptBlock (M, keySchedule, SUB_MIX, SBOX, nRounds) { - var SUB_MIX0 = SUB_MIX[0] - var SUB_MIX1 = SUB_MIX[1] - var SUB_MIX2 = SUB_MIX[2] - var SUB_MIX3 = SUB_MIX[3] - - var s0 = M[0] ^ keySchedule[0] - var s1 = M[1] ^ keySchedule[1] - var s2 = M[2] ^ keySchedule[2] - var s3 = M[3] ^ keySchedule[3] - var t0, t1, t2, t3 - var ksRow = 4 - - for (var round = 1; round < nRounds; round++) { - t0 = SUB_MIX0[s0 >>> 24] ^ SUB_MIX1[(s1 >>> 16) & 0xff] ^ SUB_MIX2[(s2 >>> 8) & 0xff] ^ SUB_MIX3[s3 & 0xff] ^ keySchedule[ksRow++] - t1 = SUB_MIX0[s1 >>> 24] ^ SUB_MIX1[(s2 >>> 16) & 0xff] ^ SUB_MIX2[(s3 >>> 8) & 0xff] ^ SUB_MIX3[s0 & 0xff] ^ keySchedule[ksRow++] - t2 = SUB_MIX0[s2 >>> 24] ^ SUB_MIX1[(s3 >>> 16) & 0xff] ^ SUB_MIX2[(s0 >>> 8) & 0xff] ^ SUB_MIX3[s1 & 0xff] ^ keySchedule[ksRow++] - t3 = SUB_MIX0[s3 >>> 24] ^ SUB_MIX1[(s0 >>> 16) & 0xff] ^ SUB_MIX2[(s1 >>> 8) & 0xff] ^ SUB_MIX3[s2 & 0xff] ^ keySchedule[ksRow++] - s0 = t0 - s1 = t1 - s2 = t2 - s3 = t3 + return out._strip(); } - t0 = ((SBOX[s0 >>> 24] << 24) | (SBOX[(s1 >>> 16) & 0xff] << 16) | (SBOX[(s2 >>> 8) & 0xff] << 8) | SBOX[s3 & 0xff]) ^ keySchedule[ksRow++] - t1 = ((SBOX[s1 >>> 24] << 24) | (SBOX[(s2 >>> 16) & 0xff] << 16) | (SBOX[(s3 >>> 8) & 0xff] << 8) | SBOX[s0 & 0xff]) ^ keySchedule[ksRow++] - t2 = ((SBOX[s2 >>> 24] << 24) | (SBOX[(s3 >>> 16) & 0xff] << 16) | (SBOX[(s0 >>> 8) & 0xff] << 8) | SBOX[s1 & 0xff]) ^ keySchedule[ksRow++] - t3 = ((SBOX[s3 >>> 24] << 24) | (SBOX[(s0 >>> 16) & 0xff] << 16) | (SBOX[(s1 >>> 8) & 0xff] << 8) | SBOX[s2 & 0xff]) ^ keySchedule[ksRow++] - t0 = t0 >>> 0 - t1 = t1 >>> 0 - t2 = t2 >>> 0 - t3 = t3 >>> 0 - - return [t0, t1, t2, t3] -} + // TODO(indutny): it may be reasonable to omit it for users who don't need + // to work with 256-bit numbers, otherwise it gives 20% improvement for 256-bit + // multiplication (like elliptic secp256k1). + var comb10MulTo = function comb10MulTo (self, num, out) { + var a = self.words; + var b = num.words; + var o = out.words; + var c = 0; + var lo; + var mid; + var hi; + var a0 = a[0] | 0; + var al0 = a0 & 0x1fff; + var ah0 = a0 >>> 13; + var a1 = a[1] | 0; + var al1 = a1 & 0x1fff; + var ah1 = a1 >>> 13; + var a2 = a[2] | 0; + var al2 = a2 & 0x1fff; + var ah2 = a2 >>> 13; + var a3 = a[3] | 0; + var al3 = a3 & 0x1fff; + var ah3 = a3 >>> 13; + var a4 = a[4] | 0; + var al4 = a4 & 0x1fff; + var ah4 = a4 >>> 13; + var a5 = a[5] | 0; + var al5 = a5 & 0x1fff; + var ah5 = a5 >>> 13; + var a6 = a[6] | 0; + var al6 = a6 & 0x1fff; + var ah6 = a6 >>> 13; + var a7 = a[7] | 0; + var al7 = a7 & 0x1fff; + var ah7 = a7 >>> 13; + var a8 = a[8] | 0; + var al8 = a8 & 0x1fff; + var ah8 = a8 >>> 13; + var a9 = a[9] | 0; + var al9 = a9 & 0x1fff; + var ah9 = a9 >>> 13; + var b0 = b[0] | 0; + var bl0 = b0 & 0x1fff; + var bh0 = b0 >>> 13; + var b1 = b[1] | 0; + var bl1 = b1 & 0x1fff; + var bh1 = b1 >>> 13; + var b2 = b[2] | 0; + var bl2 = b2 & 0x1fff; + var bh2 = b2 >>> 13; + var b3 = b[3] | 0; + var bl3 = b3 & 0x1fff; + var bh3 = b3 >>> 13; + var b4 = b[4] | 0; + var bl4 = b4 & 0x1fff; + var bh4 = b4 >>> 13; + var b5 = b[5] | 0; + var bl5 = b5 & 0x1fff; + var bh5 = b5 >>> 13; + var b6 = b[6] | 0; + var bl6 = b6 & 0x1fff; + var bh6 = b6 >>> 13; + var b7 = b[7] | 0; + var bl7 = b7 & 0x1fff; + var bh7 = b7 >>> 13; + var b8 = b[8] | 0; + var bl8 = b8 & 0x1fff; + var bh8 = b8 >>> 13; + var b9 = b[9] | 0; + var bl9 = b9 & 0x1fff; + var bh9 = b9 >>> 13; -// AES constants -var RCON = [0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36] -var G = (function () { - // Compute double table - var d = new Array(256) - for (var j = 0; j < 256; j++) { - if (j < 128) { - d[j] = j << 1 - } else { - d[j] = (j << 1) ^ 0x11b + out.negative = self.negative ^ num.negative; + out.length = 19; + /* k = 0 */ + lo = Math.imul(al0, bl0); + mid = Math.imul(al0, bh0); + mid = (mid + Math.imul(ah0, bl0)) | 0; + hi = Math.imul(ah0, bh0); + var w0 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w0 >>> 26)) | 0; + w0 &= 0x3ffffff; + /* k = 1 */ + lo = Math.imul(al1, bl0); + mid = Math.imul(al1, bh0); + mid = (mid + Math.imul(ah1, bl0)) | 0; + hi = Math.imul(ah1, bh0); + lo = (lo + Math.imul(al0, bl1)) | 0; + mid = (mid + Math.imul(al0, bh1)) | 0; + mid = (mid + Math.imul(ah0, bl1)) | 0; + hi = (hi + Math.imul(ah0, bh1)) | 0; + var w1 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w1 >>> 26)) | 0; + w1 &= 0x3ffffff; + /* k = 2 */ + lo = Math.imul(al2, bl0); + mid = Math.imul(al2, bh0); + mid = (mid + Math.imul(ah2, bl0)) | 0; + hi = Math.imul(ah2, bh0); + lo = (lo + Math.imul(al1, bl1)) | 0; + mid = (mid + Math.imul(al1, bh1)) | 0; + mid = (mid + Math.imul(ah1, bl1)) | 0; + hi = (hi + Math.imul(ah1, bh1)) | 0; + lo = (lo + Math.imul(al0, bl2)) | 0; + mid = (mid + Math.imul(al0, bh2)) | 0; + mid = (mid + Math.imul(ah0, bl2)) | 0; + hi = (hi + Math.imul(ah0, bh2)) | 0; + var w2 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w2 >>> 26)) | 0; + w2 &= 0x3ffffff; + /* k = 3 */ + lo = Math.imul(al3, bl0); + mid = Math.imul(al3, bh0); + mid = (mid + Math.imul(ah3, bl0)) | 0; + hi = Math.imul(ah3, bh0); + lo = (lo + Math.imul(al2, bl1)) | 0; + mid = (mid + Math.imul(al2, bh1)) | 0; + mid = (mid + Math.imul(ah2, bl1)) | 0; + hi = (hi + Math.imul(ah2, bh1)) | 0; + lo = (lo + Math.imul(al1, bl2)) | 0; + mid = (mid + Math.imul(al1, bh2)) | 0; + mid = (mid + Math.imul(ah1, bl2)) | 0; + hi = (hi + Math.imul(ah1, bh2)) | 0; + lo = (lo + Math.imul(al0, bl3)) | 0; + mid = (mid + Math.imul(al0, bh3)) | 0; + mid = (mid + Math.imul(ah0, bl3)) | 0; + hi = (hi + Math.imul(ah0, bh3)) | 0; + var w3 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w3 >>> 26)) | 0; + w3 &= 0x3ffffff; + /* k = 4 */ + lo = Math.imul(al4, bl0); + mid = Math.imul(al4, bh0); + mid = (mid + Math.imul(ah4, bl0)) | 0; + hi = Math.imul(ah4, bh0); + lo = (lo + Math.imul(al3, bl1)) | 0; + mid = (mid + Math.imul(al3, bh1)) | 0; + mid = (mid + Math.imul(ah3, bl1)) | 0; + hi = (hi + Math.imul(ah3, bh1)) | 0; + lo = (lo + Math.imul(al2, bl2)) | 0; + mid = (mid + Math.imul(al2, bh2)) | 0; + mid = (mid + Math.imul(ah2, bl2)) | 0; + hi = (hi + Math.imul(ah2, bh2)) | 0; + lo = (lo + Math.imul(al1, bl3)) | 0; + mid = (mid + Math.imul(al1, bh3)) | 0; + mid = (mid + Math.imul(ah1, bl3)) | 0; + hi = (hi + Math.imul(ah1, bh3)) | 0; + lo = (lo + Math.imul(al0, bl4)) | 0; + mid = (mid + Math.imul(al0, bh4)) | 0; + mid = (mid + Math.imul(ah0, bl4)) | 0; + hi = (hi + Math.imul(ah0, bh4)) | 0; + var w4 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w4 >>> 26)) | 0; + w4 &= 0x3ffffff; + /* k = 5 */ + lo = Math.imul(al5, bl0); + mid = Math.imul(al5, bh0); + mid = (mid + Math.imul(ah5, bl0)) | 0; + hi = Math.imul(ah5, bh0); + lo = (lo + Math.imul(al4, bl1)) | 0; + mid = (mid + Math.imul(al4, bh1)) | 0; + mid = (mid + Math.imul(ah4, bl1)) | 0; + hi = (hi + Math.imul(ah4, bh1)) | 0; + lo = (lo + Math.imul(al3, bl2)) | 0; + mid = (mid + Math.imul(al3, bh2)) | 0; + mid = (mid + Math.imul(ah3, bl2)) | 0; + hi = (hi + Math.imul(ah3, bh2)) | 0; + lo = (lo + Math.imul(al2, bl3)) | 0; + mid = (mid + Math.imul(al2, bh3)) | 0; + mid = (mid + Math.imul(ah2, bl3)) | 0; + hi = (hi + Math.imul(ah2, bh3)) | 0; + lo = (lo + Math.imul(al1, bl4)) | 0; + mid = (mid + Math.imul(al1, bh4)) | 0; + mid = (mid + Math.imul(ah1, bl4)) | 0; + hi = (hi + Math.imul(ah1, bh4)) | 0; + lo = (lo + Math.imul(al0, bl5)) | 0; + mid = (mid + Math.imul(al0, bh5)) | 0; + mid = (mid + Math.imul(ah0, bl5)) | 0; + hi = (hi + Math.imul(ah0, bh5)) | 0; + var w5 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w5 >>> 26)) | 0; + w5 &= 0x3ffffff; + /* k = 6 */ + lo = Math.imul(al6, bl0); + mid = Math.imul(al6, bh0); + mid = (mid + Math.imul(ah6, bl0)) | 0; + hi = Math.imul(ah6, bh0); + lo = (lo + Math.imul(al5, bl1)) | 0; + mid = (mid + Math.imul(al5, bh1)) | 0; + mid = (mid + Math.imul(ah5, bl1)) | 0; + hi = (hi + Math.imul(ah5, bh1)) | 0; + lo = (lo + Math.imul(al4, bl2)) | 0; + mid = (mid + Math.imul(al4, bh2)) | 0; + mid = (mid + Math.imul(ah4, bl2)) | 0; + hi = (hi + Math.imul(ah4, bh2)) | 0; + lo = (lo + Math.imul(al3, bl3)) | 0; + mid = (mid + Math.imul(al3, bh3)) | 0; + mid = (mid + Math.imul(ah3, bl3)) | 0; + hi = (hi + Math.imul(ah3, bh3)) | 0; + lo = (lo + Math.imul(al2, bl4)) | 0; + mid = (mid + Math.imul(al2, bh4)) | 0; + mid = (mid + Math.imul(ah2, bl4)) | 0; + hi = (hi + Math.imul(ah2, bh4)) | 0; + lo = (lo + Math.imul(al1, bl5)) | 0; + mid = (mid + Math.imul(al1, bh5)) | 0; + mid = (mid + Math.imul(ah1, bl5)) | 0; + hi = (hi + Math.imul(ah1, bh5)) | 0; + lo = (lo + Math.imul(al0, bl6)) | 0; + mid = (mid + Math.imul(al0, bh6)) | 0; + mid = (mid + Math.imul(ah0, bl6)) | 0; + hi = (hi + Math.imul(ah0, bh6)) | 0; + var w6 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w6 >>> 26)) | 0; + w6 &= 0x3ffffff; + /* k = 7 */ + lo = Math.imul(al7, bl0); + mid = Math.imul(al7, bh0); + mid = (mid + Math.imul(ah7, bl0)) | 0; + hi = Math.imul(ah7, bh0); + lo = (lo + Math.imul(al6, bl1)) | 0; + mid = (mid + Math.imul(al6, bh1)) | 0; + mid = (mid + Math.imul(ah6, bl1)) | 0; + hi = (hi + Math.imul(ah6, bh1)) | 0; + lo = (lo + Math.imul(al5, bl2)) | 0; + mid = (mid + Math.imul(al5, bh2)) | 0; + mid = (mid + Math.imul(ah5, bl2)) | 0; + hi = (hi + Math.imul(ah5, bh2)) | 0; + lo = (lo + Math.imul(al4, bl3)) | 0; + mid = (mid + Math.imul(al4, bh3)) | 0; + mid = (mid + Math.imul(ah4, bl3)) | 0; + hi = (hi + Math.imul(ah4, bh3)) | 0; + lo = (lo + Math.imul(al3, bl4)) | 0; + mid = (mid + Math.imul(al3, bh4)) | 0; + mid = (mid + Math.imul(ah3, bl4)) | 0; + hi = (hi + Math.imul(ah3, bh4)) | 0; + lo = (lo + Math.imul(al2, bl5)) | 0; + mid = (mid + Math.imul(al2, bh5)) | 0; + mid = (mid + Math.imul(ah2, bl5)) | 0; + hi = (hi + Math.imul(ah2, bh5)) | 0; + lo = (lo + Math.imul(al1, bl6)) | 0; + mid = (mid + Math.imul(al1, bh6)) | 0; + mid = (mid + Math.imul(ah1, bl6)) | 0; + hi = (hi + Math.imul(ah1, bh6)) | 0; + lo = (lo + Math.imul(al0, bl7)) | 0; + mid = (mid + Math.imul(al0, bh7)) | 0; + mid = (mid + Math.imul(ah0, bl7)) | 0; + hi = (hi + Math.imul(ah0, bh7)) | 0; + var w7 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w7 >>> 26)) | 0; + w7 &= 0x3ffffff; + /* k = 8 */ + lo = Math.imul(al8, bl0); + mid = Math.imul(al8, bh0); + mid = (mid + Math.imul(ah8, bl0)) | 0; + hi = Math.imul(ah8, bh0); + lo = (lo + Math.imul(al7, bl1)) | 0; + mid = (mid + Math.imul(al7, bh1)) | 0; + mid = (mid + Math.imul(ah7, bl1)) | 0; + hi = (hi + Math.imul(ah7, bh1)) | 0; + lo = (lo + Math.imul(al6, bl2)) | 0; + mid = (mid + Math.imul(al6, bh2)) | 0; + mid = (mid + Math.imul(ah6, bl2)) | 0; + hi = (hi + Math.imul(ah6, bh2)) | 0; + lo = (lo + Math.imul(al5, bl3)) | 0; + mid = (mid + Math.imul(al5, bh3)) | 0; + mid = (mid + Math.imul(ah5, bl3)) | 0; + hi = (hi + Math.imul(ah5, bh3)) | 0; + lo = (lo + Math.imul(al4, bl4)) | 0; + mid = (mid + Math.imul(al4, bh4)) | 0; + mid = (mid + Math.imul(ah4, bl4)) | 0; + hi = (hi + Math.imul(ah4, bh4)) | 0; + lo = (lo + Math.imul(al3, bl5)) | 0; + mid = (mid + Math.imul(al3, bh5)) | 0; + mid = (mid + Math.imul(ah3, bl5)) | 0; + hi = (hi + Math.imul(ah3, bh5)) | 0; + lo = (lo + Math.imul(al2, bl6)) | 0; + mid = (mid + Math.imul(al2, bh6)) | 0; + mid = (mid + Math.imul(ah2, bl6)) | 0; + hi = (hi + Math.imul(ah2, bh6)) | 0; + lo = (lo + Math.imul(al1, bl7)) | 0; + mid = (mid + Math.imul(al1, bh7)) | 0; + mid = (mid + Math.imul(ah1, bl7)) | 0; + hi = (hi + Math.imul(ah1, bh7)) | 0; + lo = (lo + Math.imul(al0, bl8)) | 0; + mid = (mid + Math.imul(al0, bh8)) | 0; + mid = (mid + Math.imul(ah0, bl8)) | 0; + hi = (hi + Math.imul(ah0, bh8)) | 0; + var w8 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w8 >>> 26)) | 0; + w8 &= 0x3ffffff; + /* k = 9 */ + lo = Math.imul(al9, bl0); + mid = Math.imul(al9, bh0); + mid = (mid + Math.imul(ah9, bl0)) | 0; + hi = Math.imul(ah9, bh0); + lo = (lo + Math.imul(al8, bl1)) | 0; + mid = (mid + Math.imul(al8, bh1)) | 0; + mid = (mid + Math.imul(ah8, bl1)) | 0; + hi = (hi + Math.imul(ah8, bh1)) | 0; + lo = (lo + Math.imul(al7, bl2)) | 0; + mid = (mid + Math.imul(al7, bh2)) | 0; + mid = (mid + Math.imul(ah7, bl2)) | 0; + hi = (hi + Math.imul(ah7, bh2)) | 0; + lo = (lo + Math.imul(al6, bl3)) | 0; + mid = (mid + Math.imul(al6, bh3)) | 0; + mid = (mid + Math.imul(ah6, bl3)) | 0; + hi = (hi + Math.imul(ah6, bh3)) | 0; + lo = (lo + Math.imul(al5, bl4)) | 0; + mid = (mid + Math.imul(al5, bh4)) | 0; + mid = (mid + Math.imul(ah5, bl4)) | 0; + hi = (hi + Math.imul(ah5, bh4)) | 0; + lo = (lo + Math.imul(al4, bl5)) | 0; + mid = (mid + Math.imul(al4, bh5)) | 0; + mid = (mid + Math.imul(ah4, bl5)) | 0; + hi = (hi + Math.imul(ah4, bh5)) | 0; + lo = (lo + Math.imul(al3, bl6)) | 0; + mid = (mid + Math.imul(al3, bh6)) | 0; + mid = (mid + Math.imul(ah3, bl6)) | 0; + hi = (hi + Math.imul(ah3, bh6)) | 0; + lo = (lo + Math.imul(al2, bl7)) | 0; + mid = (mid + Math.imul(al2, bh7)) | 0; + mid = (mid + Math.imul(ah2, bl7)) | 0; + hi = (hi + Math.imul(ah2, bh7)) | 0; + lo = (lo + Math.imul(al1, bl8)) | 0; + mid = (mid + Math.imul(al1, bh8)) | 0; + mid = (mid + Math.imul(ah1, bl8)) | 0; + hi = (hi + Math.imul(ah1, bh8)) | 0; + lo = (lo + Math.imul(al0, bl9)) | 0; + mid = (mid + Math.imul(al0, bh9)) | 0; + mid = (mid + Math.imul(ah0, bl9)) | 0; + hi = (hi + Math.imul(ah0, bh9)) | 0; + var w9 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w9 >>> 26)) | 0; + w9 &= 0x3ffffff; + /* k = 10 */ + lo = Math.imul(al9, bl1); + mid = Math.imul(al9, bh1); + mid = (mid + Math.imul(ah9, bl1)) | 0; + hi = Math.imul(ah9, bh1); + lo = (lo + Math.imul(al8, bl2)) | 0; + mid = (mid + Math.imul(al8, bh2)) | 0; + mid = (mid + Math.imul(ah8, bl2)) | 0; + hi = (hi + Math.imul(ah8, bh2)) | 0; + lo = (lo + Math.imul(al7, bl3)) | 0; + mid = (mid + Math.imul(al7, bh3)) | 0; + mid = (mid + Math.imul(ah7, bl3)) | 0; + hi = (hi + Math.imul(ah7, bh3)) | 0; + lo = (lo + Math.imul(al6, bl4)) | 0; + mid = (mid + Math.imul(al6, bh4)) | 0; + mid = (mid + Math.imul(ah6, bl4)) | 0; + hi = (hi + Math.imul(ah6, bh4)) | 0; + lo = (lo + Math.imul(al5, bl5)) | 0; + mid = (mid + Math.imul(al5, bh5)) | 0; + mid = (mid + Math.imul(ah5, bl5)) | 0; + hi = (hi + Math.imul(ah5, bh5)) | 0; + lo = (lo + Math.imul(al4, bl6)) | 0; + mid = (mid + Math.imul(al4, bh6)) | 0; + mid = (mid + Math.imul(ah4, bl6)) | 0; + hi = (hi + Math.imul(ah4, bh6)) | 0; + lo = (lo + Math.imul(al3, bl7)) | 0; + mid = (mid + Math.imul(al3, bh7)) | 0; + mid = (mid + Math.imul(ah3, bl7)) | 0; + hi = (hi + Math.imul(ah3, bh7)) | 0; + lo = (lo + Math.imul(al2, bl8)) | 0; + mid = (mid + Math.imul(al2, bh8)) | 0; + mid = (mid + Math.imul(ah2, bl8)) | 0; + hi = (hi + Math.imul(ah2, bh8)) | 0; + lo = (lo + Math.imul(al1, bl9)) | 0; + mid = (mid + Math.imul(al1, bh9)) | 0; + mid = (mid + Math.imul(ah1, bl9)) | 0; + hi = (hi + Math.imul(ah1, bh9)) | 0; + var w10 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w10 >>> 26)) | 0; + w10 &= 0x3ffffff; + /* k = 11 */ + lo = Math.imul(al9, bl2); + mid = Math.imul(al9, bh2); + mid = (mid + Math.imul(ah9, bl2)) | 0; + hi = Math.imul(ah9, bh2); + lo = (lo + Math.imul(al8, bl3)) | 0; + mid = (mid + Math.imul(al8, bh3)) | 0; + mid = (mid + Math.imul(ah8, bl3)) | 0; + hi = (hi + Math.imul(ah8, bh3)) | 0; + lo = (lo + Math.imul(al7, bl4)) | 0; + mid = (mid + Math.imul(al7, bh4)) | 0; + mid = (mid + Math.imul(ah7, bl4)) | 0; + hi = (hi + Math.imul(ah7, bh4)) | 0; + lo = (lo + Math.imul(al6, bl5)) | 0; + mid = (mid + Math.imul(al6, bh5)) | 0; + mid = (mid + Math.imul(ah6, bl5)) | 0; + hi = (hi + Math.imul(ah6, bh5)) | 0; + lo = (lo + Math.imul(al5, bl6)) | 0; + mid = (mid + Math.imul(al5, bh6)) | 0; + mid = (mid + Math.imul(ah5, bl6)) | 0; + hi = (hi + Math.imul(ah5, bh6)) | 0; + lo = (lo + Math.imul(al4, bl7)) | 0; + mid = (mid + Math.imul(al4, bh7)) | 0; + mid = (mid + Math.imul(ah4, bl7)) | 0; + hi = (hi + Math.imul(ah4, bh7)) | 0; + lo = (lo + Math.imul(al3, bl8)) | 0; + mid = (mid + Math.imul(al3, bh8)) | 0; + mid = (mid + Math.imul(ah3, bl8)) | 0; + hi = (hi + Math.imul(ah3, bh8)) | 0; + lo = (lo + Math.imul(al2, bl9)) | 0; + mid = (mid + Math.imul(al2, bh9)) | 0; + mid = (mid + Math.imul(ah2, bl9)) | 0; + hi = (hi + Math.imul(ah2, bh9)) | 0; + var w11 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w11 >>> 26)) | 0; + w11 &= 0x3ffffff; + /* k = 12 */ + lo = Math.imul(al9, bl3); + mid = Math.imul(al9, bh3); + mid = (mid + Math.imul(ah9, bl3)) | 0; + hi = Math.imul(ah9, bh3); + lo = (lo + Math.imul(al8, bl4)) | 0; + mid = (mid + Math.imul(al8, bh4)) | 0; + mid = (mid + Math.imul(ah8, bl4)) | 0; + hi = (hi + Math.imul(ah8, bh4)) | 0; + lo = (lo + Math.imul(al7, bl5)) | 0; + mid = (mid + Math.imul(al7, bh5)) | 0; + mid = (mid + Math.imul(ah7, bl5)) | 0; + hi = (hi + Math.imul(ah7, bh5)) | 0; + lo = (lo + Math.imul(al6, bl6)) | 0; + mid = (mid + Math.imul(al6, bh6)) | 0; + mid = (mid + Math.imul(ah6, bl6)) | 0; + hi = (hi + Math.imul(ah6, bh6)) | 0; + lo = (lo + Math.imul(al5, bl7)) | 0; + mid = (mid + Math.imul(al5, bh7)) | 0; + mid = (mid + Math.imul(ah5, bl7)) | 0; + hi = (hi + Math.imul(ah5, bh7)) | 0; + lo = (lo + Math.imul(al4, bl8)) | 0; + mid = (mid + Math.imul(al4, bh8)) | 0; + mid = (mid + Math.imul(ah4, bl8)) | 0; + hi = (hi + Math.imul(ah4, bh8)) | 0; + lo = (lo + Math.imul(al3, bl9)) | 0; + mid = (mid + Math.imul(al3, bh9)) | 0; + mid = (mid + Math.imul(ah3, bl9)) | 0; + hi = (hi + Math.imul(ah3, bh9)) | 0; + var w12 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w12 >>> 26)) | 0; + w12 &= 0x3ffffff; + /* k = 13 */ + lo = Math.imul(al9, bl4); + mid = Math.imul(al9, bh4); + mid = (mid + Math.imul(ah9, bl4)) | 0; + hi = Math.imul(ah9, bh4); + lo = (lo + Math.imul(al8, bl5)) | 0; + mid = (mid + Math.imul(al8, bh5)) | 0; + mid = (mid + Math.imul(ah8, bl5)) | 0; + hi = (hi + Math.imul(ah8, bh5)) | 0; + lo = (lo + Math.imul(al7, bl6)) | 0; + mid = (mid + Math.imul(al7, bh6)) | 0; + mid = (mid + Math.imul(ah7, bl6)) | 0; + hi = (hi + Math.imul(ah7, bh6)) | 0; + lo = (lo + Math.imul(al6, bl7)) | 0; + mid = (mid + Math.imul(al6, bh7)) | 0; + mid = (mid + Math.imul(ah6, bl7)) | 0; + hi = (hi + Math.imul(ah6, bh7)) | 0; + lo = (lo + Math.imul(al5, bl8)) | 0; + mid = (mid + Math.imul(al5, bh8)) | 0; + mid = (mid + Math.imul(ah5, bl8)) | 0; + hi = (hi + Math.imul(ah5, bh8)) | 0; + lo = (lo + Math.imul(al4, bl9)) | 0; + mid = (mid + Math.imul(al4, bh9)) | 0; + mid = (mid + Math.imul(ah4, bl9)) | 0; + hi = (hi + Math.imul(ah4, bh9)) | 0; + var w13 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w13 >>> 26)) | 0; + w13 &= 0x3ffffff; + /* k = 14 */ + lo = Math.imul(al9, bl5); + mid = Math.imul(al9, bh5); + mid = (mid + Math.imul(ah9, bl5)) | 0; + hi = Math.imul(ah9, bh5); + lo = (lo + Math.imul(al8, bl6)) | 0; + mid = (mid + Math.imul(al8, bh6)) | 0; + mid = (mid + Math.imul(ah8, bl6)) | 0; + hi = (hi + Math.imul(ah8, bh6)) | 0; + lo = (lo + Math.imul(al7, bl7)) | 0; + mid = (mid + Math.imul(al7, bh7)) | 0; + mid = (mid + Math.imul(ah7, bl7)) | 0; + hi = (hi + Math.imul(ah7, bh7)) | 0; + lo = (lo + Math.imul(al6, bl8)) | 0; + mid = (mid + Math.imul(al6, bh8)) | 0; + mid = (mid + Math.imul(ah6, bl8)) | 0; + hi = (hi + Math.imul(ah6, bh8)) | 0; + lo = (lo + Math.imul(al5, bl9)) | 0; + mid = (mid + Math.imul(al5, bh9)) | 0; + mid = (mid + Math.imul(ah5, bl9)) | 0; + hi = (hi + Math.imul(ah5, bh9)) | 0; + var w14 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w14 >>> 26)) | 0; + w14 &= 0x3ffffff; + /* k = 15 */ + lo = Math.imul(al9, bl6); + mid = Math.imul(al9, bh6); + mid = (mid + Math.imul(ah9, bl6)) | 0; + hi = Math.imul(ah9, bh6); + lo = (lo + Math.imul(al8, bl7)) | 0; + mid = (mid + Math.imul(al8, bh7)) | 0; + mid = (mid + Math.imul(ah8, bl7)) | 0; + hi = (hi + Math.imul(ah8, bh7)) | 0; + lo = (lo + Math.imul(al7, bl8)) | 0; + mid = (mid + Math.imul(al7, bh8)) | 0; + mid = (mid + Math.imul(ah7, bl8)) | 0; + hi = (hi + Math.imul(ah7, bh8)) | 0; + lo = (lo + Math.imul(al6, bl9)) | 0; + mid = (mid + Math.imul(al6, bh9)) | 0; + mid = (mid + Math.imul(ah6, bl9)) | 0; + hi = (hi + Math.imul(ah6, bh9)) | 0; + var w15 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w15 >>> 26)) | 0; + w15 &= 0x3ffffff; + /* k = 16 */ + lo = Math.imul(al9, bl7); + mid = Math.imul(al9, bh7); + mid = (mid + Math.imul(ah9, bl7)) | 0; + hi = Math.imul(ah9, bh7); + lo = (lo + Math.imul(al8, bl8)) | 0; + mid = (mid + Math.imul(al8, bh8)) | 0; + mid = (mid + Math.imul(ah8, bl8)) | 0; + hi = (hi + Math.imul(ah8, bh8)) | 0; + lo = (lo + Math.imul(al7, bl9)) | 0; + mid = (mid + Math.imul(al7, bh9)) | 0; + mid = (mid + Math.imul(ah7, bl9)) | 0; + hi = (hi + Math.imul(ah7, bh9)) | 0; + var w16 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w16 >>> 26)) | 0; + w16 &= 0x3ffffff; + /* k = 17 */ + lo = Math.imul(al9, bl8); + mid = Math.imul(al9, bh8); + mid = (mid + Math.imul(ah9, bl8)) | 0; + hi = Math.imul(ah9, bh8); + lo = (lo + Math.imul(al8, bl9)) | 0; + mid = (mid + Math.imul(al8, bh9)) | 0; + mid = (mid + Math.imul(ah8, bl9)) | 0; + hi = (hi + Math.imul(ah8, bh9)) | 0; + var w17 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w17 >>> 26)) | 0; + w17 &= 0x3ffffff; + /* k = 18 */ + lo = Math.imul(al9, bl9); + mid = Math.imul(al9, bh9); + mid = (mid + Math.imul(ah9, bl9)) | 0; + hi = Math.imul(ah9, bh9); + var w18 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w18 >>> 26)) | 0; + w18 &= 0x3ffffff; + o[0] = w0; + o[1] = w1; + o[2] = w2; + o[3] = w3; + o[4] = w4; + o[5] = w5; + o[6] = w6; + o[7] = w7; + o[8] = w8; + o[9] = w9; + o[10] = w10; + o[11] = w11; + o[12] = w12; + o[13] = w13; + o[14] = w14; + o[15] = w15; + o[16] = w16; + o[17] = w17; + o[18] = w18; + if (c !== 0) { + o[19] = c; + out.length++; } - } + return out; + }; - var SBOX = [] - var INV_SBOX = [] - var SUB_MIX = [[], [], [], []] - var INV_SUB_MIX = [[], [], [], []] - - // Walk GF(2^8) - var x = 0 - var xi = 0 - for (var i = 0; i < 256; ++i) { - // Compute sbox - var sx = xi ^ (xi << 1) ^ (xi << 2) ^ (xi << 3) ^ (xi << 4) - sx = (sx >>> 8) ^ (sx & 0xff) ^ 0x63 - SBOX[x] = sx - INV_SBOX[sx] = x + // Polyfill comb + if (!Math.imul) { + comb10MulTo = smallMulTo; + } - // Compute multiplication - var x2 = d[x] - var x4 = d[x2] - var x8 = d[x4] + function bigMulTo (self, num, out) { + out.negative = num.negative ^ self.negative; + out.length = self.length + num.length; - // Compute sub bytes, mix columns tables - var t = (d[sx] * 0x101) ^ (sx * 0x1010100) - SUB_MIX[0][x] = (t << 24) | (t >>> 8) - SUB_MIX[1][x] = (t << 16) | (t >>> 16) - SUB_MIX[2][x] = (t << 8) | (t >>> 24) - SUB_MIX[3][x] = t + var carry = 0; + var hncarry = 0; + for (var k = 0; k < out.length - 1; k++) { + // Sum all words with the same `i + j = k` and accumulate `ncarry`, + // note that ncarry could be >= 0x3ffffff + var ncarry = hncarry; + hncarry = 0; + var rword = carry & 0x3ffffff; + var maxJ = Math.min(k, num.length - 1); + for (var j = Math.max(0, k - self.length + 1); j <= maxJ; j++) { + var i = k - j; + var a = self.words[i] | 0; + var b = num.words[j] | 0; + var r = a * b; - // Compute inv sub bytes, inv mix columns tables - t = (x8 * 0x1010101) ^ (x4 * 0x10001) ^ (x2 * 0x101) ^ (x * 0x1010100) - INV_SUB_MIX[0][sx] = (t << 24) | (t >>> 8) - INV_SUB_MIX[1][sx] = (t << 16) | (t >>> 16) - INV_SUB_MIX[2][sx] = (t << 8) | (t >>> 24) - INV_SUB_MIX[3][sx] = t + var lo = r & 0x3ffffff; + ncarry = (ncarry + ((r / 0x4000000) | 0)) | 0; + lo = (lo + rword) | 0; + rword = lo & 0x3ffffff; + ncarry = (ncarry + (lo >>> 26)) | 0; - if (x === 0) { - x = xi = 1 + hncarry += ncarry >>> 26; + ncarry &= 0x3ffffff; + } + out.words[k] = rword; + carry = ncarry; + ncarry = hncarry; + } + if (carry !== 0) { + out.words[k] = carry; } else { - x = x2 ^ d[d[d[x8 ^ x2]]] - xi ^= d[d[xi]] + out.length--; } + + return out._strip(); } - return { - SBOX: SBOX, - INV_SBOX: INV_SBOX, - SUB_MIX: SUB_MIX, - INV_SUB_MIX: INV_SUB_MIX + function jumboMulTo (self, num, out) { + // Temporary disable, see https://github.com/indutny/bn.js/issues/211 + // var fftm = new FFTM(); + // return fftm.mulp(self, num, out); + return bigMulTo(self, num, out); } -})() -function AES (key) { - this._key = asUInt32Array(key) - this._reset() -} + BN.prototype.mulTo = function mulTo (num, out) { + var res; + var len = this.length + num.length; + if (this.length === 10 && num.length === 10) { + res = comb10MulTo(this, num, out); + } else if (len < 63) { + res = smallMulTo(this, num, out); + } else if (len < 1024) { + res = bigMulTo(this, num, out); + } else { + res = jumboMulTo(this, num, out); + } -AES.blockSize = 4 * 4 -AES.keySize = 256 / 8 -AES.prototype.blockSize = AES.blockSize -AES.prototype.keySize = AES.keySize -AES.prototype._reset = function () { - var keyWords = this._key - var keySize = keyWords.length - var nRounds = keySize + 6 - var ksRows = (nRounds + 1) * 4 + return res; + }; - var keySchedule = [] - for (var k = 0; k < keySize; k++) { - keySchedule[k] = keyWords[k] + // Cooley-Tukey algorithm for FFT + // slightly revisited to rely on looping instead of recursion + + function FFTM (x, y) { + this.x = x; + this.y = y; } - for (k = keySize; k < ksRows; k++) { - var t = keySchedule[k - 1] + FFTM.prototype.makeRBT = function makeRBT (N) { + var t = new Array(N); + var l = BN.prototype._countBits(N) - 1; + for (var i = 0; i < N; i++) { + t[i] = this.revBin(i, l, N); + } - if (k % keySize === 0) { - t = (t << 8) | (t >>> 24) - t = - (G.SBOX[t >>> 24] << 24) | - (G.SBOX[(t >>> 16) & 0xff] << 16) | - (G.SBOX[(t >>> 8) & 0xff] << 8) | - (G.SBOX[t & 0xff]) + return t; + }; - t ^= RCON[(k / keySize) | 0] << 24 - } else if (keySize > 6 && k % keySize === 4) { - t = - (G.SBOX[t >>> 24] << 24) | - (G.SBOX[(t >>> 16) & 0xff] << 16) | - (G.SBOX[(t >>> 8) & 0xff] << 8) | - (G.SBOX[t & 0xff]) - } + // Returns binary-reversed representation of `x` + FFTM.prototype.revBin = function revBin (x, l, N) { + if (x === 0 || x === N - 1) return x; - keySchedule[k] = keySchedule[k - keySize] ^ t - } + var rb = 0; + for (var i = 0; i < l; i++) { + rb |= (x & 1) << (l - i - 1); + x >>= 1; + } - var invKeySchedule = [] - for (var ik = 0; ik < ksRows; ik++) { - var ksR = ksRows - ik - var tt = keySchedule[ksR - (ik % 4 ? 0 : 4)] + return rb; + }; - if (ik < 4 || ksR <= 4) { - invKeySchedule[ik] = tt - } else { - invKeySchedule[ik] = - G.INV_SUB_MIX[0][G.SBOX[tt >>> 24]] ^ - G.INV_SUB_MIX[1][G.SBOX[(tt >>> 16) & 0xff]] ^ - G.INV_SUB_MIX[2][G.SBOX[(tt >>> 8) & 0xff]] ^ - G.INV_SUB_MIX[3][G.SBOX[tt & 0xff]] + // Performs "tweedling" phase, therefore 'emulating' + // behaviour of the recursive algorithm + FFTM.prototype.permute = function permute (rbt, rws, iws, rtws, itws, N) { + for (var i = 0; i < N; i++) { + rtws[i] = rws[rbt[i]]; + itws[i] = iws[rbt[i]]; } - } + }; - this._nRounds = nRounds - this._keySchedule = keySchedule - this._invKeySchedule = invKeySchedule -} + FFTM.prototype.transform = function transform (rws, iws, rtws, itws, N, rbt) { + this.permute(rbt, rws, iws, rtws, itws, N); -AES.prototype.encryptBlockRaw = function (M) { - M = asUInt32Array(M) - return cryptBlock(M, this._keySchedule, G.SUB_MIX, G.SBOX, this._nRounds) -} + for (var s = 1; s < N; s <<= 1) { + var l = s << 1; -AES.prototype.encryptBlock = function (M) { - var out = this.encryptBlockRaw(M) - var buf = Buffer.allocUnsafe(16) - buf.writeUInt32BE(out[0], 0) - buf.writeUInt32BE(out[1], 4) - buf.writeUInt32BE(out[2], 8) - buf.writeUInt32BE(out[3], 12) - return buf -} + var rtwdf = Math.cos(2 * Math.PI / l); + var itwdf = Math.sin(2 * Math.PI / l); -AES.prototype.decryptBlock = function (M) { - M = asUInt32Array(M) + for (var p = 0; p < N; p += l) { + var rtwdf_ = rtwdf; + var itwdf_ = itwdf; - // swap - var m1 = M[1] - M[1] = M[3] - M[3] = m1 + for (var j = 0; j < s; j++) { + var re = rtws[p + j]; + var ie = itws[p + j]; - var out = cryptBlock(M, this._invKeySchedule, G.INV_SUB_MIX, G.INV_SBOX, this._nRounds) - var buf = Buffer.allocUnsafe(16) - buf.writeUInt32BE(out[0], 0) - buf.writeUInt32BE(out[3], 4) - buf.writeUInt32BE(out[2], 8) - buf.writeUInt32BE(out[1], 12) - return buf -} + var ro = rtws[p + j + s]; + var io = itws[p + j + s]; -AES.prototype.scrub = function () { - scrubVec(this._keySchedule) - scrubVec(this._invKeySchedule) - scrubVec(this._key) -} + var rx = rtwdf_ * ro - itwdf_ * io; -module.exports.AES = AES + io = rtwdf_ * io + itwdf_ * ro; + ro = rx; -},{"safe-buffer":404}],95:[function(require,module,exports){ -var aes = require('./aes') -var Buffer = require('safe-buffer').Buffer -var Transform = require('cipher-base') -var inherits = require('inherits') -var GHASH = require('./ghash') -var xor = require('buffer-xor') -var incr32 = require('./incr32') + rtws[p + j] = re + ro; + itws[p + j] = ie + io; -function xorTest (a, b) { - var out = 0 - if (a.length !== b.length) out++ + rtws[p + j + s] = re - ro; + itws[p + j + s] = ie - io; - var len = Math.min(a.length, b.length) - for (var i = 0; i < len; ++i) { - out += (a[i] ^ b[i]) - } + /* jshint maxdepth : false */ + if (j !== l) { + rx = rtwdf * rtwdf_ - itwdf * itwdf_; - return out -} + itwdf_ = rtwdf * itwdf_ + itwdf * rtwdf_; + rtwdf_ = rx; + } + } + } + } + }; -function calcIv (self, iv, ck) { - if (iv.length === 12) { - self._finID = Buffer.concat([iv, Buffer.from([0, 0, 0, 1])]) - return Buffer.concat([iv, Buffer.from([0, 0, 0, 2])]) - } - var ghash = new GHASH(ck) - var len = iv.length - var toPad = len % 16 - ghash.update(iv) - if (toPad) { - toPad = 16 - toPad - ghash.update(Buffer.alloc(toPad, 0)) - } - ghash.update(Buffer.alloc(8, 0)) - var ivBits = len * 8 - var tail = Buffer.alloc(8) - tail.writeUIntBE(ivBits, 0, 8) - ghash.update(tail) - self._finID = ghash.state - var out = Buffer.from(self._finID) - incr32(out) - return out -} -function StreamCipher (mode, key, iv, decrypt) { - Transform.call(this) + FFTM.prototype.guessLen13b = function guessLen13b (n, m) { + var N = Math.max(m, n) | 1; + var odd = N & 1; + var i = 0; + for (N = N / 2 | 0; N; N = N >>> 1) { + i++; + } - var h = Buffer.alloc(4, 0) + return 1 << i + 1 + odd; + }; - this._cipher = new aes.AES(key) - var ck = this._cipher.encryptBlock(h) - this._ghash = new GHASH(ck) - iv = calcIv(this, iv, ck) + FFTM.prototype.conjugate = function conjugate (rws, iws, N) { + if (N <= 1) return; - this._prev = Buffer.from(iv) - this._cache = Buffer.allocUnsafe(0) - this._secCache = Buffer.allocUnsafe(0) - this._decrypt = decrypt - this._alen = 0 - this._len = 0 - this._mode = mode + for (var i = 0; i < N / 2; i++) { + var t = rws[i]; - this._authTag = null - this._called = false -} + rws[i] = rws[N - i - 1]; + rws[N - i - 1] = t; -inherits(StreamCipher, Transform) + t = iws[i]; -StreamCipher.prototype._update = function (chunk) { - if (!this._called && this._alen) { - var rump = 16 - (this._alen % 16) - if (rump < 16) { - rump = Buffer.alloc(rump, 0) - this._ghash.update(rump) + iws[i] = -iws[N - i - 1]; + iws[N - i - 1] = -t; } - } + }; - this._called = true - var out = this._mode.encrypt(this, chunk) - if (this._decrypt) { - this._ghash.update(chunk) - } else { - this._ghash.update(out) - } - this._len += chunk.length - return out -} + FFTM.prototype.normalize13b = function normalize13b (ws, N) { + var carry = 0; + for (var i = 0; i < N / 2; i++) { + var w = Math.round(ws[2 * i + 1] / N) * 0x2000 + + Math.round(ws[2 * i] / N) + + carry; -StreamCipher.prototype._final = function () { - if (this._decrypt && !this._authTag) throw new Error('Unsupported state or unable to authenticate data') + ws[i] = w & 0x3ffffff; - var tag = xor(this._ghash.final(this._alen * 8, this._len * 8), this._cipher.encryptBlock(this._finID)) - if (this._decrypt && xorTest(tag, this._authTag)) throw new Error('Unsupported state or unable to authenticate data') + if (w < 0x4000000) { + carry = 0; + } else { + carry = w / 0x4000000 | 0; + } + } - this._authTag = tag - this._cipher.scrub() -} + return ws; + }; -StreamCipher.prototype.getAuthTag = function getAuthTag () { - if (this._decrypt || !Buffer.isBuffer(this._authTag)) throw new Error('Attempting to get auth tag in unsupported state') + FFTM.prototype.convert13b = function convert13b (ws, len, rws, N) { + var carry = 0; + for (var i = 0; i < len; i++) { + carry = carry + (ws[i] | 0); - return this._authTag -} + rws[2 * i] = carry & 0x1fff; carry = carry >>> 13; + rws[2 * i + 1] = carry & 0x1fff; carry = carry >>> 13; + } -StreamCipher.prototype.setAuthTag = function setAuthTag (tag) { - if (!this._decrypt) throw new Error('Attempting to set auth tag in unsupported state') + // Pad with zeroes + for (i = 2 * len; i < N; ++i) { + rws[i] = 0; + } - this._authTag = tag -} + assert(carry === 0); + assert((carry & ~0x1fff) === 0); + }; -StreamCipher.prototype.setAAD = function setAAD (buf) { - if (this._called) throw new Error('Attempting to set AAD in unsupported state') + FFTM.prototype.stub = function stub (N) { + var ph = new Array(N); + for (var i = 0; i < N; i++) { + ph[i] = 0; + } - this._ghash.update(buf) - this._alen += buf.length -} + return ph; + }; -module.exports = StreamCipher + FFTM.prototype.mulp = function mulp (x, y, out) { + var N = 2 * this.guessLen13b(x.length, y.length); -},{"./aes":94,"./ghash":99,"./incr32":100,"buffer-xor":156,"cipher-base":161,"inherits":256,"safe-buffer":404}],96:[function(require,module,exports){ -var ciphers = require('./encrypter') -var deciphers = require('./decrypter') -var modes = require('./modes/list.json') + var rbt = this.makeRBT(N); -function getCiphers () { - return Object.keys(modes) -} + var _ = this.stub(N); -exports.createCipher = exports.Cipher = ciphers.createCipher -exports.createCipheriv = exports.Cipheriv = ciphers.createCipheriv -exports.createDecipher = exports.Decipher = deciphers.createDecipher -exports.createDecipheriv = exports.Decipheriv = deciphers.createDecipheriv -exports.listCiphers = exports.getCiphers = getCiphers + var rws = new Array(N); + var rwst = new Array(N); + var iwst = new Array(N); -},{"./decrypter":97,"./encrypter":98,"./modes/list.json":108}],97:[function(require,module,exports){ -var AuthCipher = require('./authCipher') -var Buffer = require('safe-buffer').Buffer -var MODES = require('./modes') -var StreamCipher = require('./streamCipher') -var Transform = require('cipher-base') -var aes = require('./aes') -var ebtk = require('evp_bytestokey') -var inherits = require('inherits') + var nrws = new Array(N); + var nrwst = new Array(N); + var niwst = new Array(N); -function Decipher (mode, key, iv) { - Transform.call(this) + var rmws = out.words; + rmws.length = N; - this._cache = new Splitter() - this._last = void 0 - this._cipher = new aes.AES(key) - this._prev = Buffer.from(iv) - this._mode = mode - this._autopadding = true -} + this.convert13b(x.words, x.length, rws, N); + this.convert13b(y.words, y.length, nrws, N); -inherits(Decipher, Transform) + this.transform(rws, _, rwst, iwst, N, rbt); + this.transform(nrws, _, nrwst, niwst, N, rbt); -Decipher.prototype._update = function (data) { - this._cache.add(data) - var chunk - var thing - var out = [] - while ((chunk = this._cache.get(this._autopadding))) { - thing = this._mode.decrypt(this, chunk) - out.push(thing) - } - return Buffer.concat(out) -} + for (var i = 0; i < N; i++) { + var rx = rwst[i] * nrwst[i] - iwst[i] * niwst[i]; + iwst[i] = rwst[i] * niwst[i] + iwst[i] * nrwst[i]; + rwst[i] = rx; + } -Decipher.prototype._final = function () { - var chunk = this._cache.flush() - if (this._autopadding) { - return unpad(this._mode.decrypt(this, chunk)) - } else if (chunk) { - throw new Error('data not multiple of block length') - } -} + this.conjugate(rwst, iwst, N); + this.transform(rwst, iwst, rmws, _, N, rbt); + this.conjugate(rmws, _, N); + this.normalize13b(rmws, N); -Decipher.prototype.setAutoPadding = function (setTo) { - this._autopadding = !!setTo - return this -} + out.negative = x.negative ^ y.negative; + out.length = x.length + y.length; + return out._strip(); + }; -function Splitter () { - this.cache = Buffer.allocUnsafe(0) -} + // Multiply `this` by `num` + BN.prototype.mul = function mul (num) { + var out = new BN(null); + out.words = new Array(this.length + num.length); + return this.mulTo(num, out); + }; -Splitter.prototype.add = function (data) { - this.cache = Buffer.concat([this.cache, data]) -} + // Multiply employing FFT + BN.prototype.mulf = function mulf (num) { + var out = new BN(null); + out.words = new Array(this.length + num.length); + return jumboMulTo(this, num, out); + }; -Splitter.prototype.get = function (autoPadding) { - var out - if (autoPadding) { - if (this.cache.length > 16) { - out = this.cache.slice(0, 16) - this.cache = this.cache.slice(16) - return out - } - } else { - if (this.cache.length >= 16) { - out = this.cache.slice(0, 16) - this.cache = this.cache.slice(16) - return out - } - } + // In-place Multiplication + BN.prototype.imul = function imul (num) { + return this.clone().mulTo(num, this); + }; - return null -} + BN.prototype.imuln = function imuln (num) { + var isNegNum = num < 0; + if (isNegNum) num = -num; -Splitter.prototype.flush = function () { - if (this.cache.length) return this.cache -} + assert(typeof num === 'number'); + assert(num < 0x4000000); -function unpad (last) { - var padded = last[15] - if (padded < 1 || padded > 16) { - throw new Error('unable to decrypt data') - } - var i = -1 - while (++i < padded) { - if (last[(i + (16 - padded))] !== padded) { - throw new Error('unable to decrypt data') + // Carry + var carry = 0; + for (var i = 0; i < this.length; i++) { + var w = (this.words[i] | 0) * num; + var lo = (w & 0x3ffffff) + (carry & 0x3ffffff); + carry >>= 26; + carry += (w / 0x4000000) | 0; + // NOTE: lo is 27bit maximum + carry += lo >>> 26; + this.words[i] = lo & 0x3ffffff; } - } - if (padded === 16) return - return last.slice(0, 16 - padded) -} + if (carry !== 0) { + this.words[i] = carry; + this.length++; + } -function createDecipheriv (suite, password, iv) { - var config = MODES[suite.toLowerCase()] - if (!config) throw new TypeError('invalid suite type') + return isNegNum ? this.ineg() : this; + }; - if (typeof iv === 'string') iv = Buffer.from(iv) - if (config.mode !== 'GCM' && iv.length !== config.iv) throw new TypeError('invalid iv length ' + iv.length) + BN.prototype.muln = function muln (num) { + return this.clone().imuln(num); + }; - if (typeof password === 'string') password = Buffer.from(password) - if (password.length !== config.key / 8) throw new TypeError('invalid key length ' + password.length) + // `this` * `this` + BN.prototype.sqr = function sqr () { + return this.mul(this); + }; - if (config.type === 'stream') { - return new StreamCipher(config.module, password, iv, true) - } else if (config.type === 'auth') { - return new AuthCipher(config.module, password, iv, true) - } + // `this` * `this` in-place + BN.prototype.isqr = function isqr () { + return this.imul(this.clone()); + }; - return new Decipher(config.module, password, iv) -} + // Math.pow(`this`, `num`) + BN.prototype.pow = function pow (num) { + var w = toBitArray(num); + if (w.length === 0) return new BN(1); -function createDecipher (suite, password) { - var config = MODES[suite.toLowerCase()] - if (!config) throw new TypeError('invalid suite type') + // Skip leading zeroes + var res = this; + for (var i = 0; i < w.length; i++, res = res.sqr()) { + if (w[i] !== 0) break; + } - var keys = ebtk(password, false, config.key, config.iv) - return createDecipheriv(suite, keys.key, keys.iv) -} + if (++i < w.length) { + for (var q = res.sqr(); i < w.length; i++, q = q.sqr()) { + if (w[i] === 0) continue; -exports.createDecipher = createDecipher -exports.createDecipheriv = createDecipheriv + res = res.mul(q); + } + } -},{"./aes":94,"./authCipher":95,"./modes":107,"./streamCipher":110,"cipher-base":161,"evp_bytestokey":212,"inherits":256,"safe-buffer":404}],98:[function(require,module,exports){ -var MODES = require('./modes') -var AuthCipher = require('./authCipher') -var Buffer = require('safe-buffer').Buffer -var StreamCipher = require('./streamCipher') -var Transform = require('cipher-base') -var aes = require('./aes') -var ebtk = require('evp_bytestokey') -var inherits = require('inherits') + return res; + }; -function Cipher (mode, key, iv) { - Transform.call(this) + // Shift-left in-place + BN.prototype.iushln = function iushln (bits) { + assert(typeof bits === 'number' && bits >= 0); + var r = bits % 26; + var s = (bits - r) / 26; + var carryMask = (0x3ffffff >>> (26 - r)) << (26 - r); + var i; - this._cache = new Splitter() - this._cipher = new aes.AES(key) - this._prev = Buffer.from(iv) - this._mode = mode - this._autopadding = true -} + if (r !== 0) { + var carry = 0; -inherits(Cipher, Transform) + for (i = 0; i < this.length; i++) { + var newCarry = this.words[i] & carryMask; + var c = ((this.words[i] | 0) - newCarry) << r; + this.words[i] = c | carry; + carry = newCarry >>> (26 - r); + } -Cipher.prototype._update = function (data) { - this._cache.add(data) - var chunk - var thing - var out = [] + if (carry) { + this.words[i] = carry; + this.length++; + } + } - while ((chunk = this._cache.get())) { - thing = this._mode.encrypt(this, chunk) - out.push(thing) - } + if (s !== 0) { + for (i = this.length - 1; i >= 0; i--) { + this.words[i + s] = this.words[i]; + } - return Buffer.concat(out) -} + for (i = 0; i < s; i++) { + this.words[i] = 0; + } -var PADDING = Buffer.alloc(16, 0x10) + this.length += s; + } -Cipher.prototype._final = function () { - var chunk = this._cache.flush() - if (this._autopadding) { - chunk = this._mode.encrypt(this, chunk) - this._cipher.scrub() - return chunk - } + return this._strip(); + }; - if (!chunk.equals(PADDING)) { - this._cipher.scrub() - throw new Error('data not multiple of block length') - } -} + BN.prototype.ishln = function ishln (bits) { + // TODO(indutny): implement me + assert(this.negative === 0); + return this.iushln(bits); + }; -Cipher.prototype.setAutoPadding = function (setTo) { - this._autopadding = !!setTo - return this -} + // Shift-right in-place + // NOTE: `hint` is a lowest bit before trailing zeroes + // NOTE: if `extended` is present - it will be filled with destroyed bits + BN.prototype.iushrn = function iushrn (bits, hint, extended) { + assert(typeof bits === 'number' && bits >= 0); + var h; + if (hint) { + h = (hint - (hint % 26)) / 26; + } else { + h = 0; + } -function Splitter () { - this.cache = Buffer.allocUnsafe(0) -} + var r = bits % 26; + var s = Math.min((bits - r) / 26, this.length); + var mask = 0x3ffffff ^ ((0x3ffffff >>> r) << r); + var maskedWords = extended; -Splitter.prototype.add = function (data) { - this.cache = Buffer.concat([this.cache, data]) -} + h -= s; + h = Math.max(0, h); -Splitter.prototype.get = function () { - if (this.cache.length > 15) { - var out = this.cache.slice(0, 16) - this.cache = this.cache.slice(16) - return out - } - return null -} + // Extended mode, copy masked part + if (maskedWords) { + for (var i = 0; i < s; i++) { + maskedWords.words[i] = this.words[i]; + } + maskedWords.length = s; + } -Splitter.prototype.flush = function () { - var len = 16 - this.cache.length - var padBuff = Buffer.allocUnsafe(len) + if (s === 0) { + // No-op, we should not move anything at all + } else if (this.length > s) { + this.length -= s; + for (i = 0; i < this.length; i++) { + this.words[i] = this.words[i + s]; + } + } else { + this.words[0] = 0; + this.length = 1; + } - var i = -1 - while (++i < len) { - padBuff.writeUInt8(len, i) - } + var carry = 0; + for (i = this.length - 1; i >= 0 && (carry !== 0 || i >= h); i--) { + var word = this.words[i] | 0; + this.words[i] = (carry << (26 - r)) | (word >>> r); + carry = word & mask; + } - return Buffer.concat([this.cache, padBuff]) -} + // Push carried bits as a mask + if (maskedWords && carry !== 0) { + maskedWords.words[maskedWords.length++] = carry; + } -function createCipheriv (suite, password, iv) { - var config = MODES[suite.toLowerCase()] - if (!config) throw new TypeError('invalid suite type') + if (this.length === 0) { + this.words[0] = 0; + this.length = 1; + } - if (typeof password === 'string') password = Buffer.from(password) - if (password.length !== config.key / 8) throw new TypeError('invalid key length ' + password.length) + return this._strip(); + }; - if (typeof iv === 'string') iv = Buffer.from(iv) - if (config.mode !== 'GCM' && iv.length !== config.iv) throw new TypeError('invalid iv length ' + iv.length) + BN.prototype.ishrn = function ishrn (bits, hint, extended) { + // TODO(indutny): implement me + assert(this.negative === 0); + return this.iushrn(bits, hint, extended); + }; - if (config.type === 'stream') { - return new StreamCipher(config.module, password, iv) - } else if (config.type === 'auth') { - return new AuthCipher(config.module, password, iv) - } + // Shift-left + BN.prototype.shln = function shln (bits) { + return this.clone().ishln(bits); + }; - return new Cipher(config.module, password, iv) -} + BN.prototype.ushln = function ushln (bits) { + return this.clone().iushln(bits); + }; -function createCipher (suite, password) { - var config = MODES[suite.toLowerCase()] - if (!config) throw new TypeError('invalid suite type') + // Shift-right + BN.prototype.shrn = function shrn (bits) { + return this.clone().ishrn(bits); + }; - var keys = ebtk(password, false, config.key, config.iv) - return createCipheriv(suite, keys.key, keys.iv) -} + BN.prototype.ushrn = function ushrn (bits) { + return this.clone().iushrn(bits); + }; -exports.createCipheriv = createCipheriv -exports.createCipher = createCipher + // Test if n bit is set + BN.prototype.testn = function testn (bit) { + assert(typeof bit === 'number' && bit >= 0); + var r = bit % 26; + var s = (bit - r) / 26; + var q = 1 << r; -},{"./aes":94,"./authCipher":95,"./modes":107,"./streamCipher":110,"cipher-base":161,"evp_bytestokey":212,"inherits":256,"safe-buffer":404}],99:[function(require,module,exports){ -var Buffer = require('safe-buffer').Buffer -var ZEROES = Buffer.alloc(16, 0) + // Fast case: bit is much higher than all existing words + if (this.length <= s) return false; -function toArray (buf) { - return [ - buf.readUInt32BE(0), - buf.readUInt32BE(4), - buf.readUInt32BE(8), - buf.readUInt32BE(12) - ] -} + // Check bit and return + var w = this.words[s]; -function fromArray (out) { - var buf = Buffer.allocUnsafe(16) - buf.writeUInt32BE(out[0] >>> 0, 0) - buf.writeUInt32BE(out[1] >>> 0, 4) - buf.writeUInt32BE(out[2] >>> 0, 8) - buf.writeUInt32BE(out[3] >>> 0, 12) - return buf -} + return !!(w & q); + }; -function GHASH (key) { - this.h = key - this.state = Buffer.alloc(16, 0) - this.cache = Buffer.allocUnsafe(0) -} + // Return only lowers bits of number (in-place) + BN.prototype.imaskn = function imaskn (bits) { + assert(typeof bits === 'number' && bits >= 0); + var r = bits % 26; + var s = (bits - r) / 26; -// from http://bitwiseshiftleft.github.io/sjcl/doc/symbols/src/core_gcm.js.html -// by Juho Vähä-Herttua -GHASH.prototype.ghash = function (block) { - var i = -1 - while (++i < block.length) { - this.state[i] ^= block[i] - } - this._multiply() -} + assert(this.negative === 0, 'imaskn works only with positive numbers'); -GHASH.prototype._multiply = function () { - var Vi = toArray(this.h) - var Zi = [0, 0, 0, 0] - var j, xi, lsbVi - var i = -1 - while (++i < 128) { - xi = (this.state[~~(i / 8)] & (1 << (7 - (i % 8)))) !== 0 - if (xi) { - // Z_i+1 = Z_i ^ V_i - Zi[0] ^= Vi[0] - Zi[1] ^= Vi[1] - Zi[2] ^= Vi[2] - Zi[3] ^= Vi[3] + if (this.length <= s) { + return this; } - // Store the value of LSB(V_i) - lsbVi = (Vi[3] & 1) !== 0 - - // V_i+1 = V_i >> 1 - for (j = 3; j > 0; j--) { - Vi[j] = (Vi[j] >>> 1) | ((Vi[j - 1] & 1) << 31) + if (r !== 0) { + s++; } - Vi[0] = Vi[0] >>> 1 + this.length = Math.min(s, this.length); - // If LSB(V_i) is 1, V_i+1 = (V_i >> 1) ^ R - if (lsbVi) { - Vi[0] = Vi[0] ^ (0xe1 << 24) + if (r !== 0) { + var mask = 0x3ffffff ^ ((0x3ffffff >>> r) << r); + this.words[this.length - 1] &= mask; } - } - this.state = fromArray(Zi) -} -GHASH.prototype.update = function (buf) { - this.cache = Buffer.concat([this.cache, buf]) - var chunk - while (this.cache.length >= 16) { - chunk = this.cache.slice(0, 16) - this.cache = this.cache.slice(16) - this.ghash(chunk) - } -} + return this._strip(); + }; -GHASH.prototype.final = function (abl, bl) { - if (this.cache.length) { - this.ghash(Buffer.concat([this.cache, ZEROES], 16)) - } + // Return only lowers bits of number + BN.prototype.maskn = function maskn (bits) { + return this.clone().imaskn(bits); + }; - this.ghash(fromArray([0, abl, 0, bl])) - return this.state -} + // Add plain number `num` to `this` + BN.prototype.iaddn = function iaddn (num) { + assert(typeof num === 'number'); + assert(num < 0x4000000); + if (num < 0) return this.isubn(-num); -module.exports = GHASH + // Possible sign change + if (this.negative !== 0) { + if (this.length === 1 && (this.words[0] | 0) <= num) { + this.words[0] = num - (this.words[0] | 0); + this.negative = 0; + return this; + } -},{"safe-buffer":404}],100:[function(require,module,exports){ -function incr32 (iv) { - var len = iv.length - var item - while (len--) { - item = iv.readUInt8(len) - if (item === 255) { - iv.writeUInt8(0, len) - } else { - item++ - iv.writeUInt8(item, len) - break + this.negative = 0; + this.isubn(num); + this.negative = 1; + return this; } - } -} -module.exports = incr32 -},{}],101:[function(require,module,exports){ -var xor = require('buffer-xor') + // Add without checks + return this._iaddn(num); + }; -exports.encrypt = function (self, block) { - var data = xor(block, self._prev) + BN.prototype._iaddn = function _iaddn (num) { + this.words[0] += num; - self._prev = self._cipher.encryptBlock(data) - return self._prev -} + // Carry + for (var i = 0; i < this.length && this.words[i] >= 0x4000000; i++) { + this.words[i] -= 0x4000000; + if (i === this.length - 1) { + this.words[i + 1] = 1; + } else { + this.words[i + 1]++; + } + } + this.length = Math.max(this.length, i + 1); -exports.decrypt = function (self, block) { - var pad = self._prev + return this; + }; - self._prev = block - var out = self._cipher.decryptBlock(block) + // Subtract plain number `num` from `this` + BN.prototype.isubn = function isubn (num) { + assert(typeof num === 'number'); + assert(num < 0x4000000); + if (num < 0) return this.iaddn(-num); - return xor(out, pad) -} + if (this.negative !== 0) { + this.negative = 0; + this.iaddn(num); + this.negative = 1; + return this; + } -},{"buffer-xor":156}],102:[function(require,module,exports){ -var Buffer = require('safe-buffer').Buffer -var xor = require('buffer-xor') + this.words[0] -= num; -function encryptStart (self, data, decrypt) { - var len = data.length - var out = xor(data, self._cache) - self._cache = self._cache.slice(len) - self._prev = Buffer.concat([self._prev, decrypt ? data : out]) - return out -} + if (this.length === 1 && this.words[0] < 0) { + this.words[0] = -this.words[0]; + this.negative = 1; + } else { + // Carry + for (var i = 0; i < this.length && this.words[i] < 0; i++) { + this.words[i] += 0x4000000; + this.words[i + 1] -= 1; + } + } -exports.encrypt = function (self, data, decrypt) { - var out = Buffer.allocUnsafe(0) - var len + return this._strip(); + }; - while (data.length) { - if (self._cache.length === 0) { - self._cache = self._cipher.encryptBlock(self._prev) - self._prev = Buffer.allocUnsafe(0) - } + BN.prototype.addn = function addn (num) { + return this.clone().iaddn(num); + }; - if (self._cache.length <= data.length) { - len = self._cache.length - out = Buffer.concat([out, encryptStart(self, data.slice(0, len), decrypt)]) - data = data.slice(len) - } else { - out = Buffer.concat([out, encryptStart(self, data, decrypt)]) - break - } - } + BN.prototype.subn = function subn (num) { + return this.clone().isubn(num); + }; - return out -} + BN.prototype.iabs = function iabs () { + this.negative = 0; -},{"buffer-xor":156,"safe-buffer":404}],103:[function(require,module,exports){ -var Buffer = require('safe-buffer').Buffer + return this; + }; -function encryptByte (self, byteParam, decrypt) { - var pad - var i = -1 - var len = 8 - var out = 0 - var bit, value - while (++i < len) { - pad = self._cipher.encryptBlock(self._prev) - bit = (byteParam & (1 << (7 - i))) ? 0x80 : 0 - value = pad[0] ^ bit - out += ((value & 0x80) >> (i % 8)) - self._prev = shiftIn(self._prev, decrypt ? bit : value) - } - return out -} + BN.prototype.abs = function abs () { + return this.clone().iabs(); + }; -function shiftIn (buffer, value) { - var len = buffer.length - var i = -1 - var out = Buffer.allocUnsafe(buffer.length) - buffer = Buffer.concat([buffer, Buffer.from([value])]) + BN.prototype._ishlnsubmul = function _ishlnsubmul (num, mul, shift) { + var len = num.length + shift; + var i; - while (++i < len) { - out[i] = buffer[i] << 1 | buffer[i + 1] >> (7) - } + this._expand(len); - return out -} + var w; + var carry = 0; + for (i = 0; i < num.length; i++) { + w = (this.words[i + shift] | 0) + carry; + var right = (num.words[i] | 0) * mul; + w -= right & 0x3ffffff; + carry = (w >> 26) - ((right / 0x4000000) | 0); + this.words[i + shift] = w & 0x3ffffff; + } + for (; i < this.length - shift; i++) { + w = (this.words[i + shift] | 0) + carry; + carry = w >> 26; + this.words[i + shift] = w & 0x3ffffff; + } -exports.encrypt = function (self, chunk, decrypt) { - var len = chunk.length - var out = Buffer.allocUnsafe(len) - var i = -1 + if (carry === 0) return this._strip(); - while (++i < len) { - out[i] = encryptByte(self, chunk[i], decrypt) - } + // Subtraction overflow + assert(carry === -1); + carry = 0; + for (i = 0; i < this.length; i++) { + w = -(this.words[i] | 0) + carry; + carry = w >> 26; + this.words[i] = w & 0x3ffffff; + } + this.negative = 1; - return out -} + return this._strip(); + }; -},{"safe-buffer":404}],104:[function(require,module,exports){ -var Buffer = require('safe-buffer').Buffer + BN.prototype._wordDiv = function _wordDiv (num, mode) { + var shift = this.length - num.length; -function encryptByte (self, byteParam, decrypt) { - var pad = self._cipher.encryptBlock(self._prev) - var out = pad[0] ^ byteParam + var a = this.clone(); + var b = num; - self._prev = Buffer.concat([ - self._prev.slice(1), - Buffer.from([decrypt ? byteParam : out]) - ]) + // Normalize + var bhi = b.words[b.length - 1] | 0; + var bhiBits = this._countBits(bhi); + shift = 26 - bhiBits; + if (shift !== 0) { + b = b.ushln(shift); + a.iushln(shift); + bhi = b.words[b.length - 1] | 0; + } - return out -} + // Initialize quotient + var m = a.length - b.length; + var q; -exports.encrypt = function (self, chunk, decrypt) { - var len = chunk.length - var out = Buffer.allocUnsafe(len) - var i = -1 + if (mode !== 'mod') { + q = new BN(null); + q.length = m + 1; + q.words = new Array(q.length); + for (var i = 0; i < q.length; i++) { + q.words[i] = 0; + } + } - while (++i < len) { - out[i] = encryptByte(self, chunk[i], decrypt) - } + var diff = a.clone()._ishlnsubmul(b, 1, m); + if (diff.negative === 0) { + a = diff; + if (q) { + q.words[m] = 1; + } + } - return out -} + for (var j = m - 1; j >= 0; j--) { + var qj = (a.words[b.length + j] | 0) * 0x4000000 + + (a.words[b.length + j - 1] | 0); -},{"safe-buffer":404}],105:[function(require,module,exports){ -var xor = require('buffer-xor') -var Buffer = require('safe-buffer').Buffer -var incr32 = require('../incr32') + // NOTE: (qj / bhi) is (0x3ffffff * 0x4000000 + 0x3ffffff) / 0x2000000 max + // (0x7ffffff) + qj = Math.min((qj / bhi) | 0, 0x3ffffff); -function getBlock (self) { - var out = self._cipher.encryptBlockRaw(self._prev) - incr32(self._prev) - return out -} + a._ishlnsubmul(b, qj, j); + while (a.negative !== 0) { + qj--; + a.negative = 0; + a._ishlnsubmul(b, 1, j); + if (!a.isZero()) { + a.negative ^= 1; + } + } + if (q) { + q.words[j] = qj; + } + } + if (q) { + q._strip(); + } + a._strip(); -var blockSize = 16 -exports.encrypt = function (self, chunk) { - var chunkNum = Math.ceil(chunk.length / blockSize) - var start = self._cache.length - self._cache = Buffer.concat([ - self._cache, - Buffer.allocUnsafe(chunkNum * blockSize) - ]) - for (var i = 0; i < chunkNum; i++) { - var out = getBlock(self) - var offset = start + i * blockSize - self._cache.writeUInt32BE(out[0], offset + 0) - self._cache.writeUInt32BE(out[1], offset + 4) - self._cache.writeUInt32BE(out[2], offset + 8) - self._cache.writeUInt32BE(out[3], offset + 12) - } - var pad = self._cache.slice(0, chunk.length) - self._cache = self._cache.slice(chunk.length) - return xor(chunk, pad) -} + // Denormalize + if (mode !== 'div' && shift !== 0) { + a.iushrn(shift); + } -},{"../incr32":100,"buffer-xor":156,"safe-buffer":404}],106:[function(require,module,exports){ -exports.encrypt = function (self, block) { - return self._cipher.encryptBlock(block) -} + return { + div: q || null, + mod: a + }; + }; -exports.decrypt = function (self, block) { - return self._cipher.decryptBlock(block) -} + // NOTE: 1) `mode` can be set to `mod` to request mod only, + // to `div` to request div only, or be absent to + // request both div & mod + // 2) `positive` is true if unsigned mod is requested + BN.prototype.divmod = function divmod (num, mode, positive) { + assert(!num.isZero()); -},{}],107:[function(require,module,exports){ -var modeModules = { - ECB: require('./ecb'), - CBC: require('./cbc'), - CFB: require('./cfb'), - CFB8: require('./cfb8'), - CFB1: require('./cfb1'), - OFB: require('./ofb'), - CTR: require('./ctr'), - GCM: require('./ctr') -} + if (this.isZero()) { + return { + div: new BN(0), + mod: new BN(0) + }; + } -var modes = require('./list.json') + var div, mod, res; + if (this.negative !== 0 && num.negative === 0) { + res = this.neg().divmod(num, mode); -for (var key in modes) { - modes[key].module = modeModules[modes[key].mode] -} + if (mode !== 'mod') { + div = res.div.neg(); + } -module.exports = modes + if (mode !== 'div') { + mod = res.mod.neg(); + if (positive && mod.negative !== 0) { + mod.iadd(num); + } + } -},{"./cbc":101,"./cfb":102,"./cfb1":103,"./cfb8":104,"./ctr":105,"./ecb":106,"./list.json":108,"./ofb":109}],108:[function(require,module,exports){ -module.exports={ - "aes-128-ecb": { - "cipher": "AES", - "key": 128, - "iv": 0, - "mode": "ECB", - "type": "block" - }, - "aes-192-ecb": { - "cipher": "AES", - "key": 192, - "iv": 0, - "mode": "ECB", - "type": "block" - }, - "aes-256-ecb": { - "cipher": "AES", - "key": 256, - "iv": 0, - "mode": "ECB", - "type": "block" - }, - "aes-128-cbc": { - "cipher": "AES", - "key": 128, - "iv": 16, - "mode": "CBC", - "type": "block" - }, - "aes-192-cbc": { - "cipher": "AES", - "key": 192, - "iv": 16, - "mode": "CBC", - "type": "block" - }, - "aes-256-cbc": { - "cipher": "AES", - "key": 256, - "iv": 16, - "mode": "CBC", - "type": "block" - }, - "aes128": { - "cipher": "AES", - "key": 128, - "iv": 16, - "mode": "CBC", - "type": "block" - }, - "aes192": { - "cipher": "AES", - "key": 192, - "iv": 16, - "mode": "CBC", - "type": "block" - }, - "aes256": { - "cipher": "AES", - "key": 256, - "iv": 16, - "mode": "CBC", - "type": "block" - }, - "aes-128-cfb": { - "cipher": "AES", - "key": 128, - "iv": 16, - "mode": "CFB", - "type": "stream" - }, - "aes-192-cfb": { - "cipher": "AES", - "key": 192, - "iv": 16, - "mode": "CFB", - "type": "stream" - }, - "aes-256-cfb": { - "cipher": "AES", - "key": 256, - "iv": 16, - "mode": "CFB", - "type": "stream" - }, - "aes-128-cfb8": { - "cipher": "AES", - "key": 128, - "iv": 16, - "mode": "CFB8", - "type": "stream" - }, - "aes-192-cfb8": { - "cipher": "AES", - "key": 192, - "iv": 16, - "mode": "CFB8", - "type": "stream" - }, - "aes-256-cfb8": { - "cipher": "AES", - "key": 256, - "iv": 16, - "mode": "CFB8", - "type": "stream" - }, - "aes-128-cfb1": { - "cipher": "AES", - "key": 128, - "iv": 16, - "mode": "CFB1", - "type": "stream" - }, - "aes-192-cfb1": { - "cipher": "AES", - "key": 192, - "iv": 16, - "mode": "CFB1", - "type": "stream" - }, - "aes-256-cfb1": { - "cipher": "AES", - "key": 256, - "iv": 16, - "mode": "CFB1", - "type": "stream" - }, - "aes-128-ofb": { - "cipher": "AES", - "key": 128, - "iv": 16, - "mode": "OFB", - "type": "stream" - }, - "aes-192-ofb": { - "cipher": "AES", - "key": 192, - "iv": 16, - "mode": "OFB", - "type": "stream" - }, - "aes-256-ofb": { - "cipher": "AES", - "key": 256, - "iv": 16, - "mode": "OFB", - "type": "stream" - }, - "aes-128-ctr": { - "cipher": "AES", - "key": 128, - "iv": 16, - "mode": "CTR", - "type": "stream" - }, - "aes-192-ctr": { - "cipher": "AES", - "key": 192, - "iv": 16, - "mode": "CTR", - "type": "stream" - }, - "aes-256-ctr": { - "cipher": "AES", - "key": 256, - "iv": 16, - "mode": "CTR", - "type": "stream" - }, - "aes-128-gcm": { - "cipher": "AES", - "key": 128, - "iv": 12, - "mode": "GCM", - "type": "auth" - }, - "aes-192-gcm": { - "cipher": "AES", - "key": 192, - "iv": 12, - "mode": "GCM", - "type": "auth" - }, - "aes-256-gcm": { - "cipher": "AES", - "key": 256, - "iv": 12, - "mode": "GCM", - "type": "auth" - } -} + return { + div: div, + mod: mod + }; + } -},{}],109:[function(require,module,exports){ -(function (Buffer){(function (){ -var xor = require('buffer-xor') + if (this.negative === 0 && num.negative !== 0) { + res = this.divmod(num.neg(), mode); -function getBlock (self) { - self._prev = self._cipher.encryptBlock(self._prev) - return self._prev -} + if (mode !== 'mod') { + div = res.div.neg(); + } -exports.encrypt = function (self, chunk) { - while (self._cache.length < chunk.length) { - self._cache = Buffer.concat([self._cache, getBlock(self)]) - } + return { + div: div, + mod: res.mod + }; + } - var pad = self._cache.slice(0, chunk.length) - self._cache = self._cache.slice(chunk.length) - return xor(chunk, pad) -} + if ((this.negative & num.negative) !== 0) { + res = this.neg().divmod(num.neg(), mode); -}).call(this)}).call(this,require("buffer").Buffer) -},{"buffer":137,"buffer-xor":156}],110:[function(require,module,exports){ -var aes = require('./aes') -var Buffer = require('safe-buffer').Buffer -var Transform = require('cipher-base') -var inherits = require('inherits') + if (mode !== 'div') { + mod = res.mod.neg(); + if (positive && mod.negative !== 0) { + mod.isub(num); + } + } -function StreamCipher (mode, key, iv, decrypt) { - Transform.call(this) + return { + div: res.div, + mod: mod + }; + } - this._cipher = new aes.AES(key) - this._prev = Buffer.from(iv) - this._cache = Buffer.allocUnsafe(0) - this._secCache = Buffer.allocUnsafe(0) - this._decrypt = decrypt - this._mode = mode -} + // Both numbers are positive at this point -inherits(StreamCipher, Transform) + // Strip both numbers to approximate shift value + if (num.length > this.length || this.cmp(num) < 0) { + return { + div: new BN(0), + mod: this + }; + } -StreamCipher.prototype._update = function (chunk) { - return this._mode.encrypt(this, chunk, this._decrypt) -} + // Very short reduction + if (num.length === 1) { + if (mode === 'div') { + return { + div: this.divn(num.words[0]), + mod: null + }; + } -StreamCipher.prototype._final = function () { - this._cipher.scrub() -} + if (mode === 'mod') { + return { + div: null, + mod: new BN(this.modrn(num.words[0])) + }; + } -module.exports = StreamCipher + return { + div: this.divn(num.words[0]), + mod: new BN(this.modrn(num.words[0])) + }; + } -},{"./aes":94,"cipher-base":161,"inherits":256,"safe-buffer":404}],111:[function(require,module,exports){ -var DES = require('browserify-des') -var aes = require('browserify-aes/browser') -var aesModes = require('browserify-aes/modes') -var desModes = require('browserify-des/modes') -var ebtk = require('evp_bytestokey') + return this._wordDiv(num, mode); + }; -function createCipher (suite, password) { - suite = suite.toLowerCase() - - var keyLen, ivLen - if (aesModes[suite]) { - keyLen = aesModes[suite].key - ivLen = aesModes[suite].iv - } else if (desModes[suite]) { - keyLen = desModes[suite].key * 8 - ivLen = desModes[suite].iv - } else { - throw new TypeError('invalid suite type') - } + // Find `this` / `num` + BN.prototype.div = function div (num) { + return this.divmod(num, 'div', false).div; + }; - var keys = ebtk(password, false, keyLen, ivLen) - return createCipheriv(suite, keys.key, keys.iv) -} + // Find `this` % `num` + BN.prototype.mod = function mod (num) { + return this.divmod(num, 'mod', false).mod; + }; -function createDecipher (suite, password) { - suite = suite.toLowerCase() + BN.prototype.umod = function umod (num) { + return this.divmod(num, 'mod', true).mod; + }; - var keyLen, ivLen - if (aesModes[suite]) { - keyLen = aesModes[suite].key - ivLen = aesModes[suite].iv - } else if (desModes[suite]) { - keyLen = desModes[suite].key * 8 - ivLen = desModes[suite].iv - } else { - throw new TypeError('invalid suite type') - } + // Find Round(`this` / `num`) + BN.prototype.divRound = function divRound (num) { + var dm = this.divmod(num); - var keys = ebtk(password, false, keyLen, ivLen) - return createDecipheriv(suite, keys.key, keys.iv) -} + // Fast case - exact division + if (dm.mod.isZero()) return dm.div; -function createCipheriv (suite, key, iv) { - suite = suite.toLowerCase() - if (aesModes[suite]) return aes.createCipheriv(suite, key, iv) - if (desModes[suite]) return new DES({ key: key, iv: iv, mode: suite }) + var mod = dm.div.negative !== 0 ? dm.mod.isub(num) : dm.mod; - throw new TypeError('invalid suite type') -} + var half = num.ushrn(1); + var r2 = num.andln(1); + var cmp = mod.cmp(half); -function createDecipheriv (suite, key, iv) { - suite = suite.toLowerCase() - if (aesModes[suite]) return aes.createDecipheriv(suite, key, iv) - if (desModes[suite]) return new DES({ key: key, iv: iv, mode: suite, decrypt: true }) + // Round down + if (cmp < 0 || (r2 === 1 && cmp === 0)) return dm.div; - throw new TypeError('invalid suite type') -} + // Round up + return dm.div.negative !== 0 ? dm.div.isubn(1) : dm.div.iaddn(1); + }; -function getCiphers () { - return Object.keys(desModes).concat(aes.getCiphers()) -} + BN.prototype.modrn = function modrn (num) { + var isNegNum = num < 0; + if (isNegNum) num = -num; -exports.createCipher = exports.Cipher = createCipher -exports.createCipheriv = exports.Cipheriv = createCipheriv -exports.createDecipher = exports.Decipher = createDecipher -exports.createDecipheriv = exports.Decipheriv = createDecipheriv -exports.listCiphers = exports.getCiphers = getCiphers + assert(num <= 0x3ffffff); + var p = (1 << 26) % num; -},{"browserify-aes/browser":96,"browserify-aes/modes":107,"browserify-des":112,"browserify-des/modes":113,"evp_bytestokey":212}],112:[function(require,module,exports){ -var CipherBase = require('cipher-base') -var des = require('des.js') -var inherits = require('inherits') -var Buffer = require('safe-buffer').Buffer + var acc = 0; + for (var i = this.length - 1; i >= 0; i--) { + acc = (p * acc + (this.words[i] | 0)) % num; + } -var modes = { - 'des-ede3-cbc': des.CBC.instantiate(des.EDE), - 'des-ede3': des.EDE, - 'des-ede-cbc': des.CBC.instantiate(des.EDE), - 'des-ede': des.EDE, - 'des-cbc': des.CBC.instantiate(des.DES), - 'des-ecb': des.DES -} -modes.des = modes['des-cbc'] -modes.des3 = modes['des-ede3-cbc'] -module.exports = DES -inherits(DES, CipherBase) -function DES (opts) { - CipherBase.call(this) - var modeName = opts.mode.toLowerCase() - var mode = modes[modeName] - var type - if (opts.decrypt) { - type = 'decrypt' - } else { - type = 'encrypt' - } - var key = opts.key - if (!Buffer.isBuffer(key)) { - key = Buffer.from(key) - } - if (modeName === 'des-ede' || modeName === 'des-ede-cbc') { - key = Buffer.concat([key, key.slice(0, 8)]) - } - var iv = opts.iv - if (!Buffer.isBuffer(iv)) { - iv = Buffer.from(iv) - } - this._des = mode.create({ - key: key, - iv: iv, - type: type - }) -} -DES.prototype._update = function (data) { - return Buffer.from(this._des.update(data)) -} -DES.prototype._final = function () { - return Buffer.from(this._des.final()) -} + return isNegNum ? -acc : acc; + }; -},{"cipher-base":161,"des.js":174,"inherits":256,"safe-buffer":404}],113:[function(require,module,exports){ -exports['des-ecb'] = { - key: 8, - iv: 0 -} -exports['des-cbc'] = exports.des = { - key: 8, - iv: 8 -} -exports['des-ede3-cbc'] = exports.des3 = { - key: 24, - iv: 8 -} -exports['des-ede3'] = { - key: 24, - iv: 0 -} -exports['des-ede-cbc'] = { - key: 16, - iv: 8 -} -exports['des-ede'] = { - key: 16, - iv: 0 -} + // WARNING: DEPRECATED + BN.prototype.modn = function modn (num) { + return this.modrn(num); + }; -},{}],114:[function(require,module,exports){ -(function (Buffer){(function (){ -var BN = require('bn.js') -var randomBytes = require('randombytes') + // In-place division by number + BN.prototype.idivn = function idivn (num) { + var isNegNum = num < 0; + if (isNegNum) num = -num; -function blind (priv) { - var r = getr(priv) - var blinder = r.toRed(BN.mont(priv.modulus)).redPow(new BN(priv.publicExponent)).fromRed() - return { blinder: blinder, unblinder: r.invm(priv.modulus) } -} + assert(num <= 0x3ffffff); -function getr (priv) { - var len = priv.modulus.byteLength() - var r - do { - r = new BN(randomBytes(len)) - } while (r.cmp(priv.modulus) >= 0 || !r.umod(priv.prime1) || !r.umod(priv.prime2)) - return r -} + var carry = 0; + for (var i = this.length - 1; i >= 0; i--) { + var w = (this.words[i] | 0) + carry * 0x4000000; + this.words[i] = (w / num) | 0; + carry = w % num; + } -function crt (msg, priv) { - var blinds = blind(priv) - var len = priv.modulus.byteLength() - var blinded = new BN(msg).mul(blinds.blinder).umod(priv.modulus) - var c1 = blinded.toRed(BN.mont(priv.prime1)) - var c2 = blinded.toRed(BN.mont(priv.prime2)) - var qinv = priv.coefficient - var p = priv.prime1 - var q = priv.prime2 - var m1 = c1.redPow(priv.exponent1).fromRed() - var m2 = c2.redPow(priv.exponent2).fromRed() - var h = m1.isub(m2).imul(qinv).umod(p).imul(q) - return m2.iadd(h).imul(blinds.unblinder).umod(priv.modulus).toArrayLike(Buffer, 'be', len) -} -crt.getr = getr + this._strip(); + return isNegNum ? this.ineg() : this; + }; -module.exports = crt + BN.prototype.divn = function divn (num) { + return this.clone().idivn(num); + }; -}).call(this)}).call(this,require("buffer").Buffer) -},{"bn.js":91,"buffer":137,"randombytes":400}],115:[function(require,module,exports){ -module.exports = require('./browser/algorithms.json') + BN.prototype.egcd = function egcd (p) { + assert(p.negative === 0); + assert(!p.isZero()); -},{"./browser/algorithms.json":116}],116:[function(require,module,exports){ -module.exports={ - "sha224WithRSAEncryption": { - "sign": "rsa", - "hash": "sha224", - "id": "302d300d06096086480165030402040500041c" - }, - "RSA-SHA224": { - "sign": "ecdsa/rsa", - "hash": "sha224", - "id": "302d300d06096086480165030402040500041c" - }, - "sha256WithRSAEncryption": { - "sign": "rsa", - "hash": "sha256", - "id": "3031300d060960864801650304020105000420" - }, - "RSA-SHA256": { - "sign": "ecdsa/rsa", - "hash": "sha256", - "id": "3031300d060960864801650304020105000420" - }, - "sha384WithRSAEncryption": { - "sign": "rsa", - "hash": "sha384", - "id": "3041300d060960864801650304020205000430" - }, - "RSA-SHA384": { - "sign": "ecdsa/rsa", - "hash": "sha384", - "id": "3041300d060960864801650304020205000430" - }, - "sha512WithRSAEncryption": { - "sign": "rsa", - "hash": "sha512", - "id": "3051300d060960864801650304020305000440" - }, - "RSA-SHA512": { - "sign": "ecdsa/rsa", - "hash": "sha512", - "id": "3051300d060960864801650304020305000440" - }, - "RSA-SHA1": { - "sign": "rsa", - "hash": "sha1", - "id": "3021300906052b0e03021a05000414" - }, - "ecdsa-with-SHA1": { - "sign": "ecdsa", - "hash": "sha1", - "id": "" - }, - "sha256": { - "sign": "ecdsa", - "hash": "sha256", - "id": "" - }, - "sha224": { - "sign": "ecdsa", - "hash": "sha224", - "id": "" - }, - "sha384": { - "sign": "ecdsa", - "hash": "sha384", - "id": "" - }, - "sha512": { - "sign": "ecdsa", - "hash": "sha512", - "id": "" - }, - "DSA-SHA": { - "sign": "dsa", - "hash": "sha1", - "id": "" - }, - "DSA-SHA1": { - "sign": "dsa", - "hash": "sha1", - "id": "" - }, - "DSA": { - "sign": "dsa", - "hash": "sha1", - "id": "" - }, - "DSA-WITH-SHA224": { - "sign": "dsa", - "hash": "sha224", - "id": "" - }, - "DSA-SHA224": { - "sign": "dsa", - "hash": "sha224", - "id": "" - }, - "DSA-WITH-SHA256": { - "sign": "dsa", - "hash": "sha256", - "id": "" - }, - "DSA-SHA256": { - "sign": "dsa", - "hash": "sha256", - "id": "" - }, - "DSA-WITH-SHA384": { - "sign": "dsa", - "hash": "sha384", - "id": "" - }, - "DSA-SHA384": { - "sign": "dsa", - "hash": "sha384", - "id": "" - }, - "DSA-WITH-SHA512": { - "sign": "dsa", - "hash": "sha512", - "id": "" - }, - "DSA-SHA512": { - "sign": "dsa", - "hash": "sha512", - "id": "" - }, - "DSA-RIPEMD160": { - "sign": "dsa", - "hash": "rmd160", - "id": "" - }, - "ripemd160WithRSA": { - "sign": "rsa", - "hash": "rmd160", - "id": "3021300906052b2403020105000414" - }, - "RSA-RIPEMD160": { - "sign": "rsa", - "hash": "rmd160", - "id": "3021300906052b2403020105000414" - }, - "md5WithRSAEncryption": { - "sign": "rsa", - "hash": "md5", - "id": "3020300c06082a864886f70d020505000410" - }, - "RSA-MD5": { - "sign": "rsa", - "hash": "md5", - "id": "3020300c06082a864886f70d020505000410" - } -} + var x = this; + var y = p.clone(); -},{}],117:[function(require,module,exports){ -module.exports={ - "1.3.132.0.10": "secp256k1", - "1.3.132.0.33": "p224", - "1.2.840.10045.3.1.1": "p192", - "1.2.840.10045.3.1.7": "p256", - "1.3.132.0.34": "p384", - "1.3.132.0.35": "p521" -} + if (x.negative !== 0) { + x = x.umod(p); + } else { + x = x.clone(); + } -},{}],118:[function(require,module,exports){ -var Buffer = require('safe-buffer').Buffer -var createHash = require('create-hash') -var stream = require('readable-stream') -var inherits = require('inherits') -var sign = require('./sign') -var verify = require('./verify') + // A * x + B * y = x + var A = new BN(1); + var B = new BN(0); -var algorithms = require('./algorithms.json') -Object.keys(algorithms).forEach(function (key) { - algorithms[key].id = Buffer.from(algorithms[key].id, 'hex') - algorithms[key.toLowerCase()] = algorithms[key] -}) + // C * x + D * y = y + var C = new BN(0); + var D = new BN(1); -function Sign (algorithm) { - stream.Writable.call(this) + var g = 0; - var data = algorithms[algorithm] - if (!data) throw new Error('Unknown message digest') + while (x.isEven() && y.isEven()) { + x.iushrn(1); + y.iushrn(1); + ++g; + } - this._hashType = data.hash - this._hash = createHash(data.hash) - this._tag = data.id - this._signType = data.sign -} -inherits(Sign, stream.Writable) + var yp = y.clone(); + var xp = x.clone(); -Sign.prototype._write = function _write (data, _, done) { - this._hash.update(data) - done() -} + while (!x.isZero()) { + for (var i = 0, im = 1; (x.words[0] & im) === 0 && i < 26; ++i, im <<= 1); + if (i > 0) { + x.iushrn(i); + while (i-- > 0) { + if (A.isOdd() || B.isOdd()) { + A.iadd(yp); + B.isub(xp); + } -Sign.prototype.update = function update (data, enc) { - if (typeof data === 'string') data = Buffer.from(data, enc) + A.iushrn(1); + B.iushrn(1); + } + } - this._hash.update(data) - return this -} + for (var j = 0, jm = 1; (y.words[0] & jm) === 0 && j < 26; ++j, jm <<= 1); + if (j > 0) { + y.iushrn(j); + while (j-- > 0) { + if (C.isOdd() || D.isOdd()) { + C.iadd(yp); + D.isub(xp); + } -Sign.prototype.sign = function signMethod (key, enc) { - this.end() - var hash = this._hash.digest() - var sig = sign(hash, key, this._hashType, this._signType, this._tag) + C.iushrn(1); + D.iushrn(1); + } + } - return enc ? sig.toString(enc) : sig -} + if (x.cmp(y) >= 0) { + x.isub(y); + A.isub(C); + B.isub(D); + } else { + y.isub(x); + C.isub(A); + D.isub(B); + } + } -function Verify (algorithm) { - stream.Writable.call(this) + return { + a: C, + b: D, + gcd: y.iushln(g) + }; + }; - var data = algorithms[algorithm] - if (!data) throw new Error('Unknown message digest') + // This is reduced incarnation of the binary EEA + // above, designated to invert members of the + // _prime_ fields F(p) at a maximal speed + BN.prototype._invmp = function _invmp (p) { + assert(p.negative === 0); + assert(!p.isZero()); - this._hash = createHash(data.hash) - this._tag = data.id - this._signType = data.sign -} -inherits(Verify, stream.Writable) + var a = this; + var b = p.clone(); -Verify.prototype._write = function _write (data, _, done) { - this._hash.update(data) - done() -} + if (a.negative !== 0) { + a = a.umod(p); + } else { + a = a.clone(); + } -Verify.prototype.update = function update (data, enc) { - if (typeof data === 'string') data = Buffer.from(data, enc) + var x1 = new BN(1); + var x2 = new BN(0); - this._hash.update(data) - return this -} + var delta = b.clone(); -Verify.prototype.verify = function verifyMethod (key, sig, enc) { - if (typeof sig === 'string') sig = Buffer.from(sig, enc) + while (a.cmpn(1) > 0 && b.cmpn(1) > 0) { + for (var i = 0, im = 1; (a.words[0] & im) === 0 && i < 26; ++i, im <<= 1); + if (i > 0) { + a.iushrn(i); + while (i-- > 0) { + if (x1.isOdd()) { + x1.iadd(delta); + } - this.end() - var hash = this._hash.digest() - return verify(sig, hash, key, this._signType, this._tag) -} + x1.iushrn(1); + } + } -function createSign (algorithm) { - return new Sign(algorithm) -} + for (var j = 0, jm = 1; (b.words[0] & jm) === 0 && j < 26; ++j, jm <<= 1); + if (j > 0) { + b.iushrn(j); + while (j-- > 0) { + if (x2.isOdd()) { + x2.iadd(delta); + } -function createVerify (algorithm) { - return new Verify(algorithm) -} + x2.iushrn(1); + } + } -module.exports = { - Sign: createSign, - Verify: createVerify, - createSign: createSign, - createVerify: createVerify -} + if (a.cmp(b) >= 0) { + a.isub(b); + x1.isub(x2); + } else { + b.isub(a); + x2.isub(x1); + } + } -},{"./algorithms.json":116,"./sign":119,"./verify":120,"create-hash":164,"inherits":256,"readable-stream":135,"safe-buffer":136}],119:[function(require,module,exports){ -// much of this based on https://github.com/indutny/self-signed/blob/gh-pages/lib/rsa.js -var Buffer = require('safe-buffer').Buffer -var createHmac = require('create-hmac') -var crt = require('browserify-rsa') -var EC = require('elliptic').ec -var BN = require('bn.js') -var parseKeys = require('parse-asn1') -var curves = require('./curves.json') - -function sign (hash, key, hashType, signType, tag) { - var priv = parseKeys(key) - if (priv.curve) { - // rsa keys can be interpreted as ecdsa ones in openssl - if (signType !== 'ecdsa' && signType !== 'ecdsa/rsa') throw new Error('wrong private key type') - return ecSign(hash, priv) - } else if (priv.type === 'dsa') { - if (signType !== 'dsa') throw new Error('wrong private key type') - return dsaSign(hash, priv, hashType) - } else { - if (signType !== 'rsa' && signType !== 'ecdsa/rsa') throw new Error('wrong private key type') - } - hash = Buffer.concat([tag, hash]) - var len = priv.modulus.byteLength() - var pad = [0, 1] - while (hash.length + pad.length + 1 < len) pad.push(0xff) - pad.push(0x00) - var i = -1 - while (++i < hash.length) pad.push(hash[i]) + var res; + if (a.cmpn(1) === 0) { + res = x1; + } else { + res = x2; + } - var out = crt(pad, priv) - return out -} + if (res.cmpn(0) < 0) { + res.iadd(p); + } -function ecSign (hash, priv) { - var curveId = curves[priv.curve.join('.')] - if (!curveId) throw new Error('unknown curve ' + priv.curve.join('.')) + return res; + }; - var curve = new EC(curveId) - var key = curve.keyFromPrivate(priv.privateKey) - var out = key.sign(hash) + BN.prototype.gcd = function gcd (num) { + if (this.isZero()) return num.abs(); + if (num.isZero()) return this.abs(); - return Buffer.from(out.toDER()) -} + var a = this.clone(); + var b = num.clone(); + a.negative = 0; + b.negative = 0; -function dsaSign (hash, priv, algo) { - var x = priv.params.priv_key - var p = priv.params.p - var q = priv.params.q - var g = priv.params.g - var r = new BN(0) - var k - var H = bits2int(hash, q).mod(q) - var s = false - var kv = getKey(x, q, hash, algo) - while (s === false) { - k = makeKey(q, kv, algo) - r = makeR(g, k, p, q) - s = k.invm(q).imul(H.add(x.mul(r))).mod(q) - if (s.cmpn(0) === 0) { - s = false - r = new BN(0) + // Remove common factor of two + for (var shift = 0; a.isEven() && b.isEven(); shift++) { + a.iushrn(1); + b.iushrn(1); } - } - return toDER(r, s) -} - -function toDER (r, s) { - r = r.toArray() - s = s.toArray() - - // Pad values - if (r[0] & 0x80) r = [0].concat(r) - if (s[0] & 0x80) s = [0].concat(s) - - var total = r.length + s.length + 4 - var res = [0x30, total, 0x02, r.length] - res = res.concat(r, [0x02, s.length], s) - return Buffer.from(res) -} -function getKey (x, q, hash, algo) { - x = Buffer.from(x.toArray()) - if (x.length < q.byteLength()) { - var zeros = Buffer.alloc(q.byteLength() - x.length) - x = Buffer.concat([zeros, x]) - } - var hlen = hash.length - var hbits = bits2octets(hash, q) - var v = Buffer.alloc(hlen) - v.fill(1) - var k = Buffer.alloc(hlen) - k = createHmac(algo, k).update(v).update(Buffer.from([0])).update(x).update(hbits).digest() - v = createHmac(algo, k).update(v).digest() - k = createHmac(algo, k).update(v).update(Buffer.from([1])).update(x).update(hbits).digest() - v = createHmac(algo, k).update(v).digest() - return { k: k, v: v } -} - -function bits2int (obits, q) { - var bits = new BN(obits) - var shift = (obits.length << 3) - q.bitLength() - if (shift > 0) bits.ishrn(shift) - return bits -} - -function bits2octets (bits, q) { - bits = bits2int(bits, q) - bits = bits.mod(q) - var out = Buffer.from(bits.toArray()) - if (out.length < q.byteLength()) { - var zeros = Buffer.alloc(q.byteLength() - out.length) - out = Buffer.concat([zeros, out]) - } - return out -} + do { + while (a.isEven()) { + a.iushrn(1); + } + while (b.isEven()) { + b.iushrn(1); + } -function makeKey (q, kv, algo) { - var t - var k + var r = a.cmp(b); + if (r < 0) { + // Swap `a` and `b` to make `a` always bigger than `b` + var t = a; + a = b; + b = t; + } else if (r === 0 || b.cmpn(1) === 0) { + break; + } - do { - t = Buffer.alloc(0) + a.isub(b); + } while (true); - while (t.length * 8 < q.bitLength()) { - kv.v = createHmac(algo, kv.k).update(kv.v).digest() - t = Buffer.concat([t, kv.v]) - } + return b.iushln(shift); + }; - k = bits2int(t, q) - kv.k = createHmac(algo, kv.k).update(kv.v).update(Buffer.from([0])).digest() - kv.v = createHmac(algo, kv.k).update(kv.v).digest() - } while (k.cmp(q) !== -1) + // Invert number in the field F(num) + BN.prototype.invm = function invm (num) { + return this.egcd(num).a.umod(num); + }; - return k -} + BN.prototype.isEven = function isEven () { + return (this.words[0] & 1) === 0; + }; -function makeR (g, k, p, q) { - return g.toRed(BN.mont(p)).redPow(k).fromRed().mod(q) -} + BN.prototype.isOdd = function isOdd () { + return (this.words[0] & 1) === 1; + }; -module.exports = sign -module.exports.getKey = getKey -module.exports.makeKey = makeKey + // And first word and num + BN.prototype.andln = function andln (num) { + return this.words[0] & num; + }; -},{"./curves.json":117,"bn.js":91,"browserify-rsa":114,"create-hmac":166,"elliptic":185,"parse-asn1":383,"safe-buffer":136}],120:[function(require,module,exports){ -// much of this based on https://github.com/indutny/self-signed/blob/gh-pages/lib/rsa.js -var Buffer = require('safe-buffer').Buffer -var BN = require('bn.js') -var EC = require('elliptic').ec -var parseKeys = require('parse-asn1') -var curves = require('./curves.json') + // Increment at the bit position in-line + BN.prototype.bincn = function bincn (bit) { + assert(typeof bit === 'number'); + var r = bit % 26; + var s = (bit - r) / 26; + var q = 1 << r; -function verify (sig, hash, key, signType, tag) { - var pub = parseKeys(key) - if (pub.type === 'ec') { - // rsa keys can be interpreted as ecdsa ones in openssl - if (signType !== 'ecdsa' && signType !== 'ecdsa/rsa') throw new Error('wrong public key type') - return ecVerify(sig, hash, pub) - } else if (pub.type === 'dsa') { - if (signType !== 'dsa') throw new Error('wrong public key type') - return dsaVerify(sig, hash, pub) - } else { - if (signType !== 'rsa' && signType !== 'ecdsa/rsa') throw new Error('wrong public key type') - } - hash = Buffer.concat([tag, hash]) - var len = pub.modulus.byteLength() - var pad = [1] - var padNum = 0 - while (hash.length + pad.length + 2 < len) { - pad.push(0xff) - padNum++ - } - pad.push(0x00) - var i = -1 - while (++i < hash.length) { - pad.push(hash[i]) - } - pad = Buffer.from(pad) - var red = BN.mont(pub.modulus) - sig = new BN(sig).toRed(red) + // Fast case: bit is much higher than all existing words + if (this.length <= s) { + this._expand(s + 1); + this.words[s] |= q; + return this; + } - sig = sig.redPow(new BN(pub.publicExponent)) - sig = Buffer.from(sig.fromRed().toArray()) - var out = padNum < 8 ? 1 : 0 - len = Math.min(sig.length, pad.length) - if (sig.length !== pad.length) out = 1 + // Add bit and propagate, if needed + var carry = q; + for (var i = s; carry !== 0 && i < this.length; i++) { + var w = this.words[i] | 0; + w += carry; + carry = w >>> 26; + w &= 0x3ffffff; + this.words[i] = w; + } + if (carry !== 0) { + this.words[i] = carry; + this.length++; + } + return this; + }; - i = -1 - while (++i < len) out |= sig[i] ^ pad[i] - return out === 0 -} + BN.prototype.isZero = function isZero () { + return this.length === 1 && this.words[0] === 0; + }; -function ecVerify (sig, hash, pub) { - var curveId = curves[pub.data.algorithm.curve.join('.')] - if (!curveId) throw new Error('unknown curve ' + pub.data.algorithm.curve.join('.')) + BN.prototype.cmpn = function cmpn (num) { + var negative = num < 0; - var curve = new EC(curveId) - var pubkey = pub.data.subjectPrivateKey.data + if (this.negative !== 0 && !negative) return -1; + if (this.negative === 0 && negative) return 1; - return curve.verify(hash, sig, pubkey) -} + this._strip(); -function dsaVerify (sig, hash, pub) { - var p = pub.data.p - var q = pub.data.q - var g = pub.data.g - var y = pub.data.pub_key - var unpacked = parseKeys.signature.decode(sig, 'der') - var s = unpacked.s - var r = unpacked.r - checkValue(s, q) - checkValue(r, q) - var montp = BN.mont(p) - var w = s.invm(q) - var v = g.toRed(montp) - .redPow(new BN(hash).mul(w).mod(q)) - .fromRed() - .mul(y.toRed(montp).redPow(r.mul(w).mod(q)).fromRed()) - .mod(p) - .mod(q) - return v.cmp(r) === 0 -} + var res; + if (this.length > 1) { + res = 1; + } else { + if (negative) { + num = -num; + } -function checkValue (b, q) { - if (b.cmpn(0) <= 0) throw new Error('invalid sig') - if (b.cmp(q) >= q) throw new Error('invalid sig') -} + assert(num <= 0x3ffffff, 'Number is too big'); -module.exports = verify + var w = this.words[0] | 0; + res = w === num ? 0 : w < num ? -1 : 1; + } + if (this.negative !== 0) return -res | 0; + return res; + }; -},{"./curves.json":117,"bn.js":91,"elliptic":185,"parse-asn1":383,"safe-buffer":136}],121:[function(require,module,exports){ -'use strict'; + // Compare two numbers and return: + // 1 - if `this` > `num` + // 0 - if `this` == `num` + // -1 - if `this` < `num` + BN.prototype.cmp = function cmp (num) { + if (this.negative !== 0 && num.negative === 0) return -1; + if (this.negative === 0 && num.negative !== 0) return 1; -function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; subClass.__proto__ = superClass; } + var res = this.ucmp(num); + if (this.negative !== 0) return -res | 0; + return res; + }; -var codes = {}; + // Unsigned comparison + BN.prototype.ucmp = function ucmp (num) { + // At this point both numbers have the same sign + if (this.length > num.length) return 1; + if (this.length < num.length) return -1; -function createErrorType(code, message, Base) { - if (!Base) { - Base = Error; - } + var res = 0; + for (var i = this.length - 1; i >= 0; i--) { + var a = this.words[i] | 0; + var b = num.words[i] | 0; - function getMessage(arg1, arg2, arg3) { - if (typeof message === 'string') { - return message; - } else { - return message(arg1, arg2, arg3); + if (a === b) continue; + if (a < b) { + res = -1; + } else if (a > b) { + res = 1; + } + break; } - } + return res; + }; - var NodeError = - /*#__PURE__*/ - function (_Base) { - _inheritsLoose(NodeError, _Base); + BN.prototype.gtn = function gtn (num) { + return this.cmpn(num) === 1; + }; - function NodeError(arg1, arg2, arg3) { - return _Base.call(this, getMessage(arg1, arg2, arg3)) || this; - } + BN.prototype.gt = function gt (num) { + return this.cmp(num) === 1; + }; - return NodeError; - }(Base); + BN.prototype.gten = function gten (num) { + return this.cmpn(num) >= 0; + }; - NodeError.prototype.name = Base.name; - NodeError.prototype.code = code; - codes[code] = NodeError; -} // https://github.com/nodejs/node/blob/v10.8.0/lib/internal/errors.js + BN.prototype.gte = function gte (num) { + return this.cmp(num) >= 0; + }; + BN.prototype.ltn = function ltn (num) { + return this.cmpn(num) === -1; + }; -function oneOf(expected, thing) { - if (Array.isArray(expected)) { - var len = expected.length; - expected = expected.map(function (i) { - return String(i); - }); + BN.prototype.lt = function lt (num) { + return this.cmp(num) === -1; + }; - if (len > 2) { - return "one of ".concat(thing, " ").concat(expected.slice(0, len - 1).join(', '), ", or ") + expected[len - 1]; - } else if (len === 2) { - return "one of ".concat(thing, " ").concat(expected[0], " or ").concat(expected[1]); - } else { - return "of ".concat(thing, " ").concat(expected[0]); - } - } else { - return "of ".concat(thing, " ").concat(String(expected)); - } -} // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/startsWith + BN.prototype.lten = function lten (num) { + return this.cmpn(num) <= 0; + }; + BN.prototype.lte = function lte (num) { + return this.cmp(num) <= 0; + }; -function startsWith(str, search, pos) { - return str.substr(!pos || pos < 0 ? 0 : +pos, search.length) === search; -} // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/endsWith + BN.prototype.eqn = function eqn (num) { + return this.cmpn(num) === 0; + }; + BN.prototype.eq = function eq (num) { + return this.cmp(num) === 0; + }; -function endsWith(str, search, this_len) { - if (this_len === undefined || this_len > str.length) { - this_len = str.length; - } + // + // A reduce context, could be using montgomery or something better, depending + // on the `m` itself. + // + BN.red = function red (num) { + return new Red(num); + }; - return str.substring(this_len - search.length, this_len) === search; -} // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/includes + BN.prototype.toRed = function toRed (ctx) { + assert(!this.red, 'Already a number in reduction context'); + assert(this.negative === 0, 'red works only with positives'); + return ctx.convertTo(this)._forceRed(ctx); + }; + BN.prototype.fromRed = function fromRed () { + assert(this.red, 'fromRed works only with numbers in reduction context'); + return this.red.convertFrom(this); + }; -function includes(str, search, start) { - if (typeof start !== 'number') { - start = 0; - } + BN.prototype._forceRed = function _forceRed (ctx) { + this.red = ctx; + return this; + }; - if (start + search.length > str.length) { - return false; - } else { - return str.indexOf(search, start) !== -1; - } -} + BN.prototype.forceRed = function forceRed (ctx) { + assert(!this.red, 'Already a number in reduction context'); + return this._forceRed(ctx); + }; -createErrorType('ERR_INVALID_OPT_VALUE', function (name, value) { - return 'The value "' + value + '" is invalid for option "' + name + '"'; -}, TypeError); -createErrorType('ERR_INVALID_ARG_TYPE', function (name, expected, actual) { - // determiner: 'must be' or 'must not be' - var determiner; + BN.prototype.redAdd = function redAdd (num) { + assert(this.red, 'redAdd works only with red numbers'); + return this.red.add(this, num); + }; - if (typeof expected === 'string' && startsWith(expected, 'not ')) { - determiner = 'must not be'; - expected = expected.replace(/^not /, ''); - } else { - determiner = 'must be'; - } + BN.prototype.redIAdd = function redIAdd (num) { + assert(this.red, 'redIAdd works only with red numbers'); + return this.red.iadd(this, num); + }; - var msg; + BN.prototype.redSub = function redSub (num) { + assert(this.red, 'redSub works only with red numbers'); + return this.red.sub(this, num); + }; - if (endsWith(name, ' argument')) { - // For cases like 'first argument' - msg = "The ".concat(name, " ").concat(determiner, " ").concat(oneOf(expected, 'type')); - } else { - var type = includes(name, '.') ? 'property' : 'argument'; - msg = "The \"".concat(name, "\" ").concat(type, " ").concat(determiner, " ").concat(oneOf(expected, 'type')); - } + BN.prototype.redISub = function redISub (num) { + assert(this.red, 'redISub works only with red numbers'); + return this.red.isub(this, num); + }; - msg += ". Received type ".concat(typeof actual); - return msg; -}, TypeError); -createErrorType('ERR_STREAM_PUSH_AFTER_EOF', 'stream.push() after EOF'); -createErrorType('ERR_METHOD_NOT_IMPLEMENTED', function (name) { - return 'The ' + name + ' method is not implemented'; -}); -createErrorType('ERR_STREAM_PREMATURE_CLOSE', 'Premature close'); -createErrorType('ERR_STREAM_DESTROYED', function (name) { - return 'Cannot call ' + name + ' after a stream was destroyed'; -}); -createErrorType('ERR_MULTIPLE_CALLBACK', 'Callback called multiple times'); -createErrorType('ERR_STREAM_CANNOT_PIPE', 'Cannot pipe, not readable'); -createErrorType('ERR_STREAM_WRITE_AFTER_END', 'write after end'); -createErrorType('ERR_STREAM_NULL_VALUES', 'May not write null values to stream', TypeError); -createErrorType('ERR_UNKNOWN_ENCODING', function (arg) { - return 'Unknown encoding: ' + arg; -}, TypeError); -createErrorType('ERR_STREAM_UNSHIFT_AFTER_END_EVENT', 'stream.unshift() after end event'); -module.exports.codes = codes; + BN.prototype.redShl = function redShl (num) { + assert(this.red, 'redShl works only with red numbers'); + return this.red.shl(this, num); + }; -},{}],122:[function(require,module,exports){ -(function (process){(function (){ -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. -// a duplex stream is just a stream that is both readable and writable. -// Since JS doesn't have multiple prototypal inheritance, this class -// prototypally inherits from Readable, and then parasitically from -// Writable. -'use strict'; -/**/ + BN.prototype.redMul = function redMul (num) { + assert(this.red, 'redMul works only with red numbers'); + this.red._verify2(this, num); + return this.red.mul(this, num); + }; -var objectKeys = Object.keys || function (obj) { - var keys = []; + BN.prototype.redIMul = function redIMul (num) { + assert(this.red, 'redMul works only with red numbers'); + this.red._verify2(this, num); + return this.red.imul(this, num); + }; - for (var key in obj) { - keys.push(key); - } + BN.prototype.redSqr = function redSqr () { + assert(this.red, 'redSqr works only with red numbers'); + this.red._verify1(this); + return this.red.sqr(this); + }; - return keys; -}; -/**/ + BN.prototype.redISqr = function redISqr () { + assert(this.red, 'redISqr works only with red numbers'); + this.red._verify1(this); + return this.red.isqr(this); + }; + // Square root over p + BN.prototype.redSqrt = function redSqrt () { + assert(this.red, 'redSqrt works only with red numbers'); + this.red._verify1(this); + return this.red.sqrt(this); + }; -module.exports = Duplex; + BN.prototype.redInvm = function redInvm () { + assert(this.red, 'redInvm works only with red numbers'); + this.red._verify1(this); + return this.red.invm(this); + }; -var Readable = require('./_stream_readable'); + // Return negative clone of `this` % `red modulo` + BN.prototype.redNeg = function redNeg () { + assert(this.red, 'redNeg works only with red numbers'); + this.red._verify1(this); + return this.red.neg(this); + }; -var Writable = require('./_stream_writable'); + BN.prototype.redPow = function redPow (num) { + assert(this.red && !num.red, 'redPow(normalNum)'); + this.red._verify1(this); + return this.red.pow(this, num); + }; -require('inherits')(Duplex, Readable); + // Prime numbers with efficient reduction + var primes = { + k256: null, + p224: null, + p192: null, + p25519: null + }; -{ - // Allow the keys array to be GC'ed. - var keys = objectKeys(Writable.prototype); + // Pseudo-Mersenne prime + function MPrime (name, p) { + // P = 2 ^ N - K + this.name = name; + this.p = new BN(p, 16); + this.n = this.p.bitLength(); + this.k = new BN(1).iushln(this.n).isub(this.p); - for (var v = 0; v < keys.length; v++) { - var method = keys[v]; - if (!Duplex.prototype[method]) Duplex.prototype[method] = Writable.prototype[method]; + this.tmp = this._tmp(); } -} -function Duplex(options) { - if (!(this instanceof Duplex)) return new Duplex(options); - Readable.call(this, options); - Writable.call(this, options); - this.allowHalfOpen = true; + MPrime.prototype._tmp = function _tmp () { + var tmp = new BN(null); + tmp.words = new Array(Math.ceil(this.n / 13)); + return tmp; + }; - if (options) { - if (options.readable === false) this.readable = false; - if (options.writable === false) this.writable = false; + MPrime.prototype.ireduce = function ireduce (num) { + // Assumes that `num` is less than `P^2` + // num = HI * (2 ^ N - K) + HI * K + LO = HI * K + LO (mod P) + var r = num; + var rlen; - if (options.allowHalfOpen === false) { - this.allowHalfOpen = false; - this.once('end', onend); - } - } -} + do { + this.split(r, this.tmp); + r = this.imulK(r); + r = r.iadd(this.tmp); + rlen = r.bitLength(); + } while (rlen > this.n); -Object.defineProperty(Duplex.prototype, 'writableHighWaterMark', { - // making it explicit this property is not enumerable - // because otherwise some prototype manipulation in - // userland will fail - enumerable: false, - get: function get() { - return this._writableState.highWaterMark; - } -}); -Object.defineProperty(Duplex.prototype, 'writableBuffer', { - // making it explicit this property is not enumerable - // because otherwise some prototype manipulation in - // userland will fail - enumerable: false, - get: function get() { - return this._writableState && this._writableState.getBuffer(); - } -}); -Object.defineProperty(Duplex.prototype, 'writableLength', { - // making it explicit this property is not enumerable - // because otherwise some prototype manipulation in - // userland will fail - enumerable: false, - get: function get() { - return this._writableState.length; - } -}); // the no-half-open enforcer + var cmp = rlen < this.n ? -1 : r.ucmp(this.p); + if (cmp === 0) { + r.words[0] = 0; + r.length = 1; + } else if (cmp > 0) { + r.isub(this.p); + } else { + if (r.strip !== undefined) { + // r is a BN v4 instance + r.strip(); + } else { + // r is a BN v5 instance + r._strip(); + } + } -function onend() { - // If the writable side ended, then we're ok. - if (this._writableState.ended) return; // no more data can be written. - // But allow more writes to happen in this tick. + return r; + }; - process.nextTick(onEndNT, this); -} + MPrime.prototype.split = function split (input, out) { + input.iushrn(this.n, 0, out); + }; -function onEndNT(self) { - self.end(); -} + MPrime.prototype.imulK = function imulK (num) { + return num.imul(this.k); + }; -Object.defineProperty(Duplex.prototype, 'destroyed', { - // making it explicit this property is not enumerable - // because otherwise some prototype manipulation in - // userland will fail - enumerable: false, - get: function get() { - if (this._readableState === undefined || this._writableState === undefined) { - return false; + function K256 () { + MPrime.call( + this, + 'k256', + 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe fffffc2f'); + } + inherits(K256, MPrime); + + K256.prototype.split = function split (input, output) { + // 256 = 9 * 26 + 22 + var mask = 0x3fffff; + + var outLen = Math.min(input.length, 9); + for (var i = 0; i < outLen; i++) { + output.words[i] = input.words[i]; } + output.length = outLen; - return this._readableState.destroyed && this._writableState.destroyed; - }, - set: function set(value) { - // we ignore the value if the stream - // has not been initialized yet - if (this._readableState === undefined || this._writableState === undefined) { + if (input.length <= 9) { + input.words[0] = 0; + input.length = 1; return; - } // backward compatibility, the user is explicitly - // managing destroyed + } + // Shift by 9 limbs + var prev = input.words[9]; + output.words[output.length++] = prev & mask; - this._readableState.destroyed = value; - this._writableState.destroyed = value; - } -}); -}).call(this)}).call(this,require('_process')) -},{"./_stream_readable":124,"./_stream_writable":126,"_process":391,"inherits":256}],123:[function(require,module,exports){ -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. -// a passthrough stream. -// basically just the most minimal sort of Transform stream. -// Every written chunk gets output as-is. -'use strict'; + for (i = 10; i < input.length; i++) { + var next = input.words[i] | 0; + input.words[i - 10] = ((next & mask) << 4) | (prev >>> 22); + prev = next; + } + prev >>>= 22; + input.words[i - 10] = prev; + if (prev === 0 && input.length > 10) { + input.length -= 10; + } else { + input.length -= 9; + } + }; -module.exports = PassThrough; + K256.prototype.imulK = function imulK (num) { + // K = 0x1000003d1 = [ 0x40, 0x3d1 ] + num.words[num.length] = 0; + num.words[num.length + 1] = 0; + num.length += 2; -var Transform = require('./_stream_transform'); + // bounded at: 0x40 * 0x3ffffff + 0x3d0 = 0x100000390 + var lo = 0; + for (var i = 0; i < num.length; i++) { + var w = num.words[i] | 0; + lo += w * 0x3d1; + num.words[i] = lo & 0x3ffffff; + lo = w * 0x40 + ((lo / 0x4000000) | 0); + } -require('inherits')(PassThrough, Transform); + // Fast length reduction + if (num.words[num.length - 1] === 0) { + num.length--; + if (num.words[num.length - 1] === 0) { + num.length--; + } + } + return num; + }; -function PassThrough(options) { - if (!(this instanceof PassThrough)) return new PassThrough(options); - Transform.call(this, options); -} + function P224 () { + MPrime.call( + this, + 'p224', + 'ffffffff ffffffff ffffffff ffffffff 00000000 00000000 00000001'); + } + inherits(P224, MPrime); -PassThrough.prototype._transform = function (chunk, encoding, cb) { - cb(null, chunk); -}; -},{"./_stream_transform":125,"inherits":256}],124:[function(require,module,exports){ -(function (process,global){(function (){ -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. -'use strict'; + function P192 () { + MPrime.call( + this, + 'p192', + 'ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff'); + } + inherits(P192, MPrime); -module.exports = Readable; -/**/ + function P25519 () { + // 2 ^ 255 - 19 + MPrime.call( + this, + '25519', + '7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed'); + } + inherits(P25519, MPrime); -var Duplex; -/**/ + P25519.prototype.imulK = function imulK (num) { + // K = 0x13 + var carry = 0; + for (var i = 0; i < num.length; i++) { + var hi = (num.words[i] | 0) * 0x13 + carry; + var lo = hi & 0x3ffffff; + hi >>>= 26; -Readable.ReadableState = ReadableState; -/**/ + num.words[i] = lo; + carry = hi; + } + if (carry !== 0) { + num.words[num.length++] = carry; + } + return num; + }; -var EE = require('events').EventEmitter; + // Exported mostly for testing purposes, use plain name instead + BN._prime = function prime (name) { + // Cached version of prime + if (primes[name]) return primes[name]; -var EElistenerCount = function EElistenerCount(emitter, type) { - return emitter.listeners(type).length; -}; -/**/ + var prime; + if (name === 'k256') { + prime = new K256(); + } else if (name === 'p224') { + prime = new P224(); + } else if (name === 'p192') { + prime = new P192(); + } else if (name === 'p25519') { + prime = new P25519(); + } else { + throw new Error('Unknown prime ' + name); + } + primes[name] = prime; -/**/ + return prime; + }; + // + // Base reduction engine + // + function Red (m) { + if (typeof m === 'string') { + var prime = BN._prime(m); + this.m = prime.p; + this.prime = prime; + } else { + assert(m.gtn(1), 'modulus must be greater than 1'); + this.m = m; + this.prime = null; + } + } -var Stream = require('./internal/streams/stream'); -/**/ + Red.prototype._verify1 = function _verify1 (a) { + assert(a.negative === 0, 'red works only with positives'); + assert(a.red, 'red works only with red numbers'); + }; + Red.prototype._verify2 = function _verify2 (a, b) { + assert((a.negative | b.negative) === 0, 'red works only with positives'); + assert(a.red && a.red === b.red, + 'red works only with red numbers'); + }; -var Buffer = require('buffer').Buffer; + Red.prototype.imod = function imod (a) { + if (this.prime) return this.prime.ireduce(a)._forceRed(this); -var OurUint8Array = global.Uint8Array || function () {}; + move(a, a.umod(this.m)._forceRed(this)); + return a; + }; -function _uint8ArrayToBuffer(chunk) { - return Buffer.from(chunk); -} + Red.prototype.neg = function neg (a) { + if (a.isZero()) { + return a.clone(); + } -function _isUint8Array(obj) { - return Buffer.isBuffer(obj) || obj instanceof OurUint8Array; -} -/**/ + return this.m.sub(a)._forceRed(this); + }; + Red.prototype.add = function add (a, b) { + this._verify2(a, b); -var debugUtil = require('util'); + var res = a.add(b); + if (res.cmp(this.m) >= 0) { + res.isub(this.m); + } + return res._forceRed(this); + }; -var debug; + Red.prototype.iadd = function iadd (a, b) { + this._verify2(a, b); -if (debugUtil && debugUtil.debuglog) { - debug = debugUtil.debuglog('stream'); -} else { - debug = function debug() {}; -} -/**/ + var res = a.iadd(b); + if (res.cmp(this.m) >= 0) { + res.isub(this.m); + } + return res; + }; + Red.prototype.sub = function sub (a, b) { + this._verify2(a, b); -var BufferList = require('./internal/streams/buffer_list'); + var res = a.sub(b); + if (res.cmpn(0) < 0) { + res.iadd(this.m); + } + return res._forceRed(this); + }; -var destroyImpl = require('./internal/streams/destroy'); + Red.prototype.isub = function isub (a, b) { + this._verify2(a, b); -var _require = require('./internal/streams/state'), - getHighWaterMark = _require.getHighWaterMark; + var res = a.isub(b); + if (res.cmpn(0) < 0) { + res.iadd(this.m); + } + return res; + }; -var _require$codes = require('../errors').codes, - ERR_INVALID_ARG_TYPE = _require$codes.ERR_INVALID_ARG_TYPE, - ERR_STREAM_PUSH_AFTER_EOF = _require$codes.ERR_STREAM_PUSH_AFTER_EOF, - ERR_METHOD_NOT_IMPLEMENTED = _require$codes.ERR_METHOD_NOT_IMPLEMENTED, - ERR_STREAM_UNSHIFT_AFTER_END_EVENT = _require$codes.ERR_STREAM_UNSHIFT_AFTER_END_EVENT; // Lazy loaded to improve the startup performance. + Red.prototype.shl = function shl (a, num) { + this._verify1(a); + return this.imod(a.ushln(num)); + }; + Red.prototype.imul = function imul (a, b) { + this._verify2(a, b); + return this.imod(a.imul(b)); + }; -var StringDecoder; -var createReadableStreamAsyncIterator; -var from; + Red.prototype.mul = function mul (a, b) { + this._verify2(a, b); + return this.imod(a.mul(b)); + }; -require('inherits')(Readable, Stream); + Red.prototype.isqr = function isqr (a) { + return this.imul(a, a.clone()); + }; -var errorOrDestroy = destroyImpl.errorOrDestroy; -var kProxyEvents = ['error', 'close', 'destroy', 'pause', 'resume']; + Red.prototype.sqr = function sqr (a) { + return this.mul(a, a); + }; -function prependListener(emitter, event, fn) { - // Sadly this is not cacheable as some libraries bundle their own - // event emitter implementation with them. - if (typeof emitter.prependListener === 'function') return emitter.prependListener(event, fn); // This is a hack to make sure that our error handler is attached before any - // userland ones. NEVER DO THIS. This is here only because this code needs - // to continue to work with older versions of Node.js that do not include - // the prependListener() method. The goal is to eventually remove this hack. + Red.prototype.sqrt = function sqrt (a) { + if (a.isZero()) return a.clone(); - if (!emitter._events || !emitter._events[event]) emitter.on(event, fn);else if (Array.isArray(emitter._events[event])) emitter._events[event].unshift(fn);else emitter._events[event] = [fn, emitter._events[event]]; -} + var mod3 = this.m.andln(3); + assert(mod3 % 2 === 1); -function ReadableState(options, stream, isDuplex) { - Duplex = Duplex || require('./_stream_duplex'); - options = options || {}; // Duplex streams are both readable and writable, but share - // the same options object. - // However, some cases require setting options to different - // values for the readable and the writable sides of the duplex stream. - // These options can be provided separately as readableXXX and writableXXX. + // Fast case + if (mod3 === 3) { + var pow = this.m.add(new BN(1)).iushrn(2); + return this.pow(a, pow); + } - if (typeof isDuplex !== 'boolean') isDuplex = stream instanceof Duplex; // object stream flag. Used to make read(n) ignore n and to - // make all the buffer merging and length checks go away + // Tonelli-Shanks algorithm (Totally unoptimized and slow) + // + // Find Q and S, that Q * 2 ^ S = (P - 1) + var q = this.m.subn(1); + var s = 0; + while (!q.isZero() && q.andln(1) === 0) { + s++; + q.iushrn(1); + } + assert(!q.isZero()); - this.objectMode = !!options.objectMode; - if (isDuplex) this.objectMode = this.objectMode || !!options.readableObjectMode; // the point at which it stops calling _read() to fill the buffer - // Note: 0 is a valid value, means "don't call _read preemptively ever" + var one = new BN(1).toRed(this); + var nOne = one.redNeg(); - this.highWaterMark = getHighWaterMark(this, options, 'readableHighWaterMark', isDuplex); // A linked list is used to store data chunks instead of an array because the - // linked list can remove elements from the beginning faster than - // array.shift() + // Find quadratic non-residue + // NOTE: Max is such because of generalized Riemann hypothesis. + var lpow = this.m.subn(1).iushrn(1); + var z = this.m.bitLength(); + z = new BN(2 * z * z).toRed(this); - this.buffer = new BufferList(); - this.length = 0; - this.pipes = null; - this.pipesCount = 0; - this.flowing = null; - this.ended = false; - this.endEmitted = false; - this.reading = false; // a flag to be able to tell if the event 'readable'/'data' is emitted - // immediately, or on a later tick. We set this to true at first, because - // any actions that shouldn't happen until "later" should generally also - // not happen before the first read call. + while (this.pow(z, lpow).cmp(nOne) !== 0) { + z.redIAdd(nOne); + } - this.sync = true; // whenever we return null, then we set a flag to say - // that we're awaiting a 'readable' event emission. + var c = this.pow(z, q); + var r = this.pow(a, q.addn(1).iushrn(1)); + var t = this.pow(a, q); + var m = s; + while (t.cmp(one) !== 0) { + var tmp = t; + for (var i = 0; tmp.cmp(one) !== 0; i++) { + tmp = tmp.redSqr(); + } + assert(i < m); + var b = this.pow(c, new BN(1).iushln(m - i - 1)); - this.needReadable = false; - this.emittedReadable = false; - this.readableListening = false; - this.resumeScheduled = false; - this.paused = true; // Should close be emitted on destroy. Defaults to true. + r = r.redMul(b); + c = b.redSqr(); + t = t.redMul(c); + m = i; + } - this.emitClose = options.emitClose !== false; // Should .destroy() be called after 'end' (and potentially 'finish') + return r; + }; - this.autoDestroy = !!options.autoDestroy; // has it been destroyed + Red.prototype.invm = function invm (a) { + var inv = a._invmp(this.m); + if (inv.negative !== 0) { + inv.negative = 0; + return this.imod(inv).redNeg(); + } else { + return this.imod(inv); + } + }; - this.destroyed = false; // Crypto is kind of old and crusty. Historically, its default string - // encoding is 'binary' so we have to make this configurable. - // Everything else in the universe uses 'utf8', though. + Red.prototype.pow = function pow (a, num) { + if (num.isZero()) return new BN(1).toRed(this); + if (num.cmpn(1) === 0) return a.clone(); - this.defaultEncoding = options.defaultEncoding || 'utf8'; // the number of writers that are awaiting a drain event in .pipe()s + var windowSize = 4; + var wnd = new Array(1 << windowSize); + wnd[0] = new BN(1).toRed(this); + wnd[1] = a; + for (var i = 2; i < wnd.length; i++) { + wnd[i] = this.mul(wnd[i - 1], a); + } - this.awaitDrain = 0; // if true, a maybeReadMore has been scheduled + var res = wnd[0]; + var current = 0; + var currentLen = 0; + var start = num.bitLength() % 26; + if (start === 0) { + start = 26; + } - this.readingMore = false; - this.decoder = null; - this.encoding = null; + for (i = num.length - 1; i >= 0; i--) { + var word = num.words[i]; + for (var j = start - 1; j >= 0; j--) { + var bit = (word >> j) & 1; + if (res !== wnd[0]) { + res = this.sqr(res); + } - if (options.encoding) { - if (!StringDecoder) StringDecoder = require('string_decoder/').StringDecoder; - this.decoder = new StringDecoder(options.encoding); - this.encoding = options.encoding; - } -} + if (bit === 0 && current === 0) { + currentLen = 0; + continue; + } -function Readable(options) { - Duplex = Duplex || require('./_stream_duplex'); - if (!(this instanceof Readable)) return new Readable(options); // Checking for a Stream.Duplex instance is faster here instead of inside - // the ReadableState constructor, at least with V8 6.5 + current <<= 1; + current |= bit; + currentLen++; + if (currentLen !== windowSize && (i !== 0 || j !== 0)) continue; - var isDuplex = this instanceof Duplex; - this._readableState = new ReadableState(options, this, isDuplex); // legacy + res = this.mul(res, wnd[current]); + currentLen = 0; + current = 0; + } + start = 26; + } - this.readable = true; + return res; + }; - if (options) { - if (typeof options.read === 'function') this._read = options.read; - if (typeof options.destroy === 'function') this._destroy = options.destroy; - } + Red.prototype.convertTo = function convertTo (num) { + var r = num.umod(this.m); - Stream.call(this); -} + return r === num ? r.clone() : r; + }; -Object.defineProperty(Readable.prototype, 'destroyed', { - // making it explicit this property is not enumerable - // because otherwise some prototype manipulation in - // userland will fail - enumerable: false, - get: function get() { - if (this._readableState === undefined) { - return false; - } + Red.prototype.convertFrom = function convertFrom (num) { + var res = num.clone(); + res.red = null; + return res; + }; - return this._readableState.destroyed; - }, - set: function set(value) { - // we ignore the value if the stream - // has not been initialized yet - if (!this._readableState) { - return; - } // backward compatibility, the user is explicitly - // managing destroyed + // + // Montgomery method engine + // + BN.mont = function mont (num) { + return new Mont(num); + }; - this._readableState.destroyed = value; - } -}); -Readable.prototype.destroy = destroyImpl.destroy; -Readable.prototype._undestroy = destroyImpl.undestroy; + function Mont (m) { + Red.call(this, m); -Readable.prototype._destroy = function (err, cb) { - cb(err); -}; // Manually shove something into the read() buffer. -// This returns true if the highWaterMark has not been hit yet, -// similar to how Writable.write() returns true if you should -// write() some more. + this.shift = this.m.bitLength(); + if (this.shift % 26 !== 0) { + this.shift += 26 - (this.shift % 26); + } + this.r = new BN(1).iushln(this.shift); + this.r2 = this.imod(this.r.sqr()); + this.rinv = this.r._invmp(this.m); -Readable.prototype.push = function (chunk, encoding) { - var state = this._readableState; - var skipChunkCheck; + this.minv = this.rinv.mul(this.r).isubn(1).div(this.m); + this.minv = this.minv.umod(this.r); + this.minv = this.r.sub(this.minv); + } + inherits(Mont, Red); - if (!state.objectMode) { - if (typeof chunk === 'string') { - encoding = encoding || state.defaultEncoding; + Mont.prototype.convertTo = function convertTo (num) { + return this.imod(num.ushln(this.shift)); + }; - if (encoding !== state.encoding) { - chunk = Buffer.from(chunk, encoding); - encoding = ''; - } + Mont.prototype.convertFrom = function convertFrom (num) { + var r = this.imod(num.mul(this.rinv)); + r.red = null; + return r; + }; - skipChunkCheck = true; + Mont.prototype.imul = function imul (a, b) { + if (a.isZero() || b.isZero()) { + a.words[0] = 0; + a.length = 1; + return a; } - } else { - skipChunkCheck = true; - } - - return readableAddChunk(this, chunk, encoding, false, skipChunkCheck); -}; // Unshift should *always* be something directly out of read() + var t = a.imul(b); + var c = t.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m); + var u = t.isub(c).iushrn(this.shift); + var res = u; -Readable.prototype.unshift = function (chunk) { - return readableAddChunk(this, chunk, null, true, false); -}; + if (u.cmp(this.m) >= 0) { + res = u.isub(this.m); + } else if (u.cmpn(0) < 0) { + res = u.iadd(this.m); + } -function readableAddChunk(stream, chunk, encoding, addToFront, skipChunkCheck) { - debug('readableAddChunk', chunk); - var state = stream._readableState; + return res._forceRed(this); + }; - if (chunk === null) { - state.reading = false; - onEofChunk(stream, state); - } else { - var er; - if (!skipChunkCheck) er = chunkInvalid(state, chunk); + Mont.prototype.mul = function mul (a, b) { + if (a.isZero() || b.isZero()) return new BN(0)._forceRed(this); - if (er) { - errorOrDestroy(stream, er); - } else if (state.objectMode || chunk && chunk.length > 0) { - if (typeof chunk !== 'string' && !state.objectMode && Object.getPrototypeOf(chunk) !== Buffer.prototype) { - chunk = _uint8ArrayToBuffer(chunk); - } + var t = a.mul(b); + var c = t.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m); + var u = t.isub(c).iushrn(this.shift); + var res = u; + if (u.cmp(this.m) >= 0) { + res = u.isub(this.m); + } else if (u.cmpn(0) < 0) { + res = u.iadd(this.m); + } - if (addToFront) { - if (state.endEmitted) errorOrDestroy(stream, new ERR_STREAM_UNSHIFT_AFTER_END_EVENT());else addChunk(stream, state, chunk, true); - } else if (state.ended) { - errorOrDestroy(stream, new ERR_STREAM_PUSH_AFTER_EOF()); - } else if (state.destroyed) { - return false; - } else { - state.reading = false; + return res._forceRed(this); + }; - if (state.decoder && !encoding) { - chunk = state.decoder.write(chunk); - if (state.objectMode || chunk.length !== 0) addChunk(stream, state, chunk, false);else maybeReadMore(stream, state); - } else { - addChunk(stream, state, chunk, false); - } - } - } else if (!addToFront) { - state.reading = false; - maybeReadMore(stream, state); - } - } // We can push more data if we are below the highWaterMark. - // Also, if we have no data yet, we can stand some more bytes. - // This is to work around cases where hwm=0, such as the repl. + Mont.prototype.invm = function invm (a) { + // (AR)^-1 * R^2 = (A^-1 * R^-1) * R^2 = A^-1 * R + var res = this.imod(a._invmp(this.m).mul(this.r2)); + return res._forceRed(this); + }; +})(typeof module === 'undefined' || module, this); +},{"buffer":88}],111:[function(require,module,exports){ +'use strict'; - return !state.ended && (state.length < state.highWaterMark || state.length === 0); -} +module.exports = require('./browser/algorithms.json'); -function addChunk(stream, state, chunk, addToFront) { - if (state.flowing && state.length === 0 && !state.sync) { - state.awaitDrain = 0; - stream.emit('data', chunk); - } else { - // update the buffer info. - state.length += state.objectMode ? 1 : chunk.length; - if (addToFront) state.buffer.unshift(chunk);else state.buffer.push(chunk); - if (state.needReadable) emitReadable(stream); +},{"./browser/algorithms.json":112}],112:[function(require,module,exports){ +module.exports={ + "sha224WithRSAEncryption": { + "sign": "rsa", + "hash": "sha224", + "id": "302d300d06096086480165030402040500041c" + }, + "RSA-SHA224": { + "sign": "ecdsa/rsa", + "hash": "sha224", + "id": "302d300d06096086480165030402040500041c" + }, + "sha256WithRSAEncryption": { + "sign": "rsa", + "hash": "sha256", + "id": "3031300d060960864801650304020105000420" + }, + "RSA-SHA256": { + "sign": "ecdsa/rsa", + "hash": "sha256", + "id": "3031300d060960864801650304020105000420" + }, + "sha384WithRSAEncryption": { + "sign": "rsa", + "hash": "sha384", + "id": "3041300d060960864801650304020205000430" + }, + "RSA-SHA384": { + "sign": "ecdsa/rsa", + "hash": "sha384", + "id": "3041300d060960864801650304020205000430" + }, + "sha512WithRSAEncryption": { + "sign": "rsa", + "hash": "sha512", + "id": "3051300d060960864801650304020305000440" + }, + "RSA-SHA512": { + "sign": "ecdsa/rsa", + "hash": "sha512", + "id": "3051300d060960864801650304020305000440" + }, + "RSA-SHA1": { + "sign": "rsa", + "hash": "sha1", + "id": "3021300906052b0e03021a05000414" + }, + "ecdsa-with-SHA1": { + "sign": "ecdsa", + "hash": "sha1", + "id": "" + }, + "sha256": { + "sign": "ecdsa", + "hash": "sha256", + "id": "" + }, + "sha224": { + "sign": "ecdsa", + "hash": "sha224", + "id": "" + }, + "sha384": { + "sign": "ecdsa", + "hash": "sha384", + "id": "" + }, + "sha512": { + "sign": "ecdsa", + "hash": "sha512", + "id": "" + }, + "DSA-SHA": { + "sign": "dsa", + "hash": "sha1", + "id": "" + }, + "DSA-SHA1": { + "sign": "dsa", + "hash": "sha1", + "id": "" + }, + "DSA": { + "sign": "dsa", + "hash": "sha1", + "id": "" + }, + "DSA-WITH-SHA224": { + "sign": "dsa", + "hash": "sha224", + "id": "" + }, + "DSA-SHA224": { + "sign": "dsa", + "hash": "sha224", + "id": "" + }, + "DSA-WITH-SHA256": { + "sign": "dsa", + "hash": "sha256", + "id": "" + }, + "DSA-SHA256": { + "sign": "dsa", + "hash": "sha256", + "id": "" + }, + "DSA-WITH-SHA384": { + "sign": "dsa", + "hash": "sha384", + "id": "" + }, + "DSA-SHA384": { + "sign": "dsa", + "hash": "sha384", + "id": "" + }, + "DSA-WITH-SHA512": { + "sign": "dsa", + "hash": "sha512", + "id": "" + }, + "DSA-SHA512": { + "sign": "dsa", + "hash": "sha512", + "id": "" + }, + "DSA-RIPEMD160": { + "sign": "dsa", + "hash": "rmd160", + "id": "" + }, + "ripemd160WithRSA": { + "sign": "rsa", + "hash": "rmd160", + "id": "3021300906052b2403020105000414" + }, + "RSA-RIPEMD160": { + "sign": "rsa", + "hash": "rmd160", + "id": "3021300906052b2403020105000414" + }, + "md5WithRSAEncryption": { + "sign": "rsa", + "hash": "md5", + "id": "3020300c06082a864886f70d020505000410" + }, + "RSA-MD5": { + "sign": "rsa", + "hash": "md5", + "id": "3020300c06082a864886f70d020505000410" } +} - maybeReadMore(stream, state); +},{}],113:[function(require,module,exports){ +module.exports={ + "1.3.132.0.10": "secp256k1", + "1.3.132.0.33": "p224", + "1.2.840.10045.3.1.1": "p192", + "1.2.840.10045.3.1.7": "p256", + "1.3.132.0.34": "p384", + "1.3.132.0.35": "p521" } -function chunkInvalid(state, chunk) { - var er; +},{}],114:[function(require,module,exports){ +'use strict'; - if (!_isUint8Array(chunk) && typeof chunk !== 'string' && chunk !== undefined && !state.objectMode) { - er = new ERR_INVALID_ARG_TYPE('chunk', ['string', 'Buffer', 'Uint8Array'], chunk); - } +var Buffer = require('safe-buffer').Buffer; +var createHash = require('create-hash'); +var stream = require('readable-stream'); +var inherits = require('inherits'); +var sign = require('./sign'); +var verify = require('./verify'); - return er; -} +var algorithms = require('./algorithms.json'); +Object.keys(algorithms).forEach(function (key) { + algorithms[key].id = Buffer.from(algorithms[key].id, 'hex'); + algorithms[key.toLowerCase()] = algorithms[key]; +}); -Readable.prototype.isPaused = function () { - return this._readableState.flowing === false; -}; // backwards compatibility. +function Sign(algorithm) { + stream.Writable.call(this); + var data = algorithms[algorithm]; + if (!data) { throw new Error('Unknown message digest'); } -Readable.prototype.setEncoding = function (enc) { - if (!StringDecoder) StringDecoder = require('string_decoder/').StringDecoder; - var decoder = new StringDecoder(enc); - this._readableState.decoder = decoder; // If setEncoding(null), decoder.encoding equals utf8 + this._hashType = data.hash; + this._hash = createHash(data.hash); + this._tag = data.id; + this._signType = data.sign; +} +inherits(Sign, stream.Writable); - this._readableState.encoding = this._readableState.decoder.encoding; // Iterate over current buffer to convert already stored Buffers: +Sign.prototype._write = function _write(data, _, done) { + this._hash.update(data); + done(); +}; - var p = this._readableState.buffer.head; - var content = ''; +Sign.prototype.update = function update(data, enc) { + this._hash.update(typeof data === 'string' ? Buffer.from(data, enc) : data); - while (p !== null) { - content += decoder.write(p.data); - p = p.next; - } + return this; +}; - this._readableState.buffer.clear(); +Sign.prototype.sign = function signMethod(key, enc) { + this.end(); + var hash = this._hash.digest(); + var sig = sign(hash, key, this._hashType, this._signType, this._tag); - if (content !== '') this._readableState.buffer.push(content); - this._readableState.length = content.length; - return this; -}; // Don't raise the hwm > 1GB + return enc ? sig.toString(enc) : sig; +}; +function Verify(algorithm) { + stream.Writable.call(this); -var MAX_HWM = 0x40000000; + var data = algorithms[algorithm]; + if (!data) { throw new Error('Unknown message digest'); } -function computeNewHighWaterMark(n) { - if (n >= MAX_HWM) { - // TODO(ronag): Throw ERR_VALUE_OUT_OF_RANGE. - n = MAX_HWM; - } else { - // Get the next highest power of 2 to prevent increasing hwm excessively in - // tiny amounts - n--; - n |= n >>> 1; - n |= n >>> 2; - n |= n >>> 4; - n |= n >>> 8; - n |= n >>> 16; - n++; - } + this._hash = createHash(data.hash); + this._tag = data.id; + this._signType = data.sign; +} +inherits(Verify, stream.Writable); - return n; -} // This function is designed to be inlinable, so please take care when making -// changes to the function body. +Verify.prototype._write = function _write(data, _, done) { + this._hash.update(data); + done(); +}; +Verify.prototype.update = function update(data, enc) { + this._hash.update(typeof data === 'string' ? Buffer.from(data, enc) : data); -function howMuchToRead(n, state) { - if (n <= 0 || state.length === 0 && state.ended) return 0; - if (state.objectMode) return 1; + return this; +}; - if (n !== n) { - // Only flow one buffer at a time - if (state.flowing && state.length) return state.buffer.head.data.length;else return state.length; - } // If we're asking for more than the current hwm, then raise the hwm. +Verify.prototype.verify = function verifyMethod(key, sig, enc) { + var sigBuffer = typeof sig === 'string' ? Buffer.from(sig, enc) : sig; + this.end(); + var hash = this._hash.digest(); + return verify(sigBuffer, hash, key, this._signType, this._tag); +}; - if (n > state.highWaterMark) state.highWaterMark = computeNewHighWaterMark(n); - if (n <= state.length) return n; // Don't have enough +function createSign(algorithm) { + return new Sign(algorithm); +} - if (!state.ended) { - state.needReadable = true; - return 0; - } +function createVerify(algorithm) { + return new Verify(algorithm); +} - return state.length; -} // you can override either this method, or the async _read(n) below. +module.exports = { + Sign: createSign, + Verify: createVerify, + createSign: createSign, + createVerify: createVerify +}; +},{"./algorithms.json":112,"./sign":115,"./verify":116,"create-hash":127,"inherits":200,"readable-stream":371,"safe-buffer":390}],115:[function(require,module,exports){ +'use strict'; -Readable.prototype.read = function (n) { - debug('read', n); - n = parseInt(n, 10); - var state = this._readableState; - var nOrig = n; - if (n !== 0) state.emittedReadable = false; // if we're doing read(0) to trigger a readable event, but we - // already have a bunch of data in the buffer, then just trigger - // the 'readable' event and move on. +// much of this based on https://github.com/indutny/self-signed/blob/gh-pages/lib/rsa.js +var Buffer = require('safe-buffer').Buffer; +var createHmac = require('create-hmac'); +var crt = require('browserify-rsa'); +var EC = require('elliptic').ec; +var BN = require('bn.js'); +var parseKeys = require('parse-asn1'); +var curves = require('./curves.json'); - if (n === 0 && state.needReadable && ((state.highWaterMark !== 0 ? state.length >= state.highWaterMark : state.length > 0) || state.ended)) { - debug('read: emitReadable', state.length, state.ended); - if (state.length === 0 && state.ended) endReadable(this);else emitReadable(this); - return null; - } +var RSA_PKCS1_PADDING = 1; - n = howMuchToRead(n, state); // if we've ended, and we're now clear, then finish it up. +function sign(hash, key, hashType, signType, tag) { + var priv = parseKeys(key); + if (priv.curve) { + // rsa keys can be interpreted as ecdsa ones in openssl + if (signType !== 'ecdsa' && signType !== 'ecdsa/rsa') { throw new Error('wrong private key type'); } + return ecSign(hash, priv); + } else if (priv.type === 'dsa') { + if (signType !== 'dsa') { throw new Error('wrong private key type'); } + return dsaSign(hash, priv, hashType); + } + if (signType !== 'rsa' && signType !== 'ecdsa/rsa') { throw new Error('wrong private key type'); } + if (key.padding !== undefined && key.padding !== RSA_PKCS1_PADDING) { throw new Error('illegal or unsupported padding mode'); } - if (n === 0 && state.ended) { - if (state.length === 0) endReadable(this); - return null; - } // All the actual chunk generation logic needs to be - // *below* the call to _read. The reason is that in certain - // synthetic stream cases, such as passthrough streams, _read - // may be a completely synchronous operation which may change - // the state of the read buffer, providing enough data when - // before there was *not* enough. - // - // So, the steps are: - // 1. Figure out what the state of things will be after we do - // a read from the buffer. - // - // 2. If that resulting state will trigger a _read, then call _read. - // Note that this may be asynchronous, or synchronous. Yes, it is - // deeply ugly to write APIs this way, but that still doesn't mean - // that the Readable class should behave improperly, as streams are - // designed to be sync/async agnostic. - // Take note if the _read call is sync or async (ie, if the read call - // has returned yet), so that we know whether or not it's safe to emit - // 'readable' etc. - // - // 3. Actually pull the requested chunks out of the buffer and return. - // if we need a readable event, then we need to do some reading. + hash = Buffer.concat([tag, hash]); + var len = priv.modulus.byteLength(); + var pad = [0, 1]; + while (hash.length + pad.length + 1 < len) { pad.push(0xff); } + pad.push(0x00); + var i = -1; + while (++i < hash.length) { pad.push(hash[i]); } + var out = crt(pad, priv); + return out; +} - var doRead = state.needReadable; - debug('need readable', doRead); // if we currently have less than the highWaterMark, then also read some +function ecSign(hash, priv) { + var curveId = curves[priv.curve.join('.')]; + if (!curveId) { throw new Error('unknown curve ' + priv.curve.join('.')); } - if (state.length === 0 || state.length - n < state.highWaterMark) { - doRead = true; - debug('length less than watermark', doRead); - } // however, if we've ended, then there's no point, and if we're already - // reading, then it's unnecessary. + var curve = new EC(curveId); + var key = curve.keyFromPrivate(priv.privateKey); + var out = key.sign(hash); + return Buffer.from(out.toDER()); +} - if (state.ended || state.reading) { - doRead = false; - debug('reading or ended', doRead); - } else if (doRead) { - debug('do read'); - state.reading = true; - state.sync = true; // if the length is currently zero, then we *need* a readable event. +function dsaSign(hash, priv, algo) { + var x = priv.params.priv_key; + var p = priv.params.p; + var q = priv.params.q; + var g = priv.params.g; + var r = new BN(0); + var k; + var H = bits2int(hash, q).mod(q); + var s = false; + var kv = getKey(x, q, hash, algo); + while (s === false) { + k = makeKey(q, kv, algo); + r = makeR(g, k, p, q); + s = k.invm(q).imul(H.add(x.mul(r))).mod(q); + if (s.cmpn(0) === 0) { + s = false; + r = new BN(0); + } + } + return toDER(r, s); +} - if (state.length === 0) state.needReadable = true; // call internal read method +function toDER(r, s) { + r = r.toArray(); + s = s.toArray(); - this._read(state.highWaterMark); + // Pad values + if (r[0] & 0x80) { r = [0].concat(r); } + if (s[0] & 0x80) { s = [0].concat(s); } - state.sync = false; // If _read pushed data synchronously, then `reading` will be false, - // and we need to re-evaluate how much data we can return to the user. + var total = r.length + s.length + 4; + var res = [ + 0x30, total, 0x02, r.length + ]; + res = res.concat(r, [0x02, s.length], s); + return Buffer.from(res); +} - if (!state.reading) n = howMuchToRead(nOrig, state); +function getKey(x, q, hash, algo) { + x = Buffer.from(x.toArray()); + if (x.length < q.byteLength()) { + var zeros = Buffer.alloc(q.byteLength() - x.length); + x = Buffer.concat([zeros, x]); + } + var hlen = hash.length; + var hbits = bits2octets(hash, q); + var v = Buffer.alloc(hlen); + v.fill(1); + var k = Buffer.alloc(hlen); + k = createHmac(algo, k).update(v).update(Buffer.from([0])).update(x).update(hbits).digest(); + v = createHmac(algo, k).update(v).digest(); + k = createHmac(algo, k).update(v).update(Buffer.from([1])).update(x).update(hbits).digest(); + v = createHmac(algo, k).update(v).digest(); + return { k: k, v: v }; +} + +function bits2int(obits, q) { + var bits = new BN(obits); + var shift = (obits.length << 3) - q.bitLength(); + if (shift > 0) { bits.ishrn(shift); } + return bits; +} + +function bits2octets(bits, q) { + bits = bits2int(bits, q); + bits = bits.mod(q); + var out = Buffer.from(bits.toArray()); + if (out.length < q.byteLength()) { + var zeros = Buffer.alloc(q.byteLength() - out.length); + out = Buffer.concat([zeros, out]); } + return out; +} - var ret; - if (n > 0) ret = fromList(n, state);else ret = null; +function makeKey(q, kv, algo) { + var t; + var k; - if (ret === null) { - state.needReadable = state.length <= state.highWaterMark; - n = 0; - } else { - state.length -= n; - state.awaitDrain = 0; - } + do { + t = Buffer.alloc(0); - if (state.length === 0) { - // If we have nothing in the buffer, then we want to know - // as soon as we *do* get something into the buffer. - if (!state.ended) state.needReadable = true; // If we tried to read() past the EOF, then emit end on the next tick. + while (t.length * 8 < q.bitLength()) { + kv.v = createHmac(algo, kv.k).update(kv.v).digest(); + t = Buffer.concat([t, kv.v]); + } - if (nOrig !== n && state.ended) endReadable(this); - } + k = bits2int(t, q); + kv.k = createHmac(algo, kv.k).update(kv.v).update(Buffer.from([0])).digest(); + kv.v = createHmac(algo, kv.k).update(kv.v).digest(); + } while (k.cmp(q) !== -1); - if (ret !== null) this.emit('data', ret); - return ret; -}; + return k; +} -function onEofChunk(stream, state) { - debug('onEofChunk'); - if (state.ended) return; +function makeR(g, k, p, q) { + return g.toRed(BN.mont(p)).redPow(k).fromRed().mod(q); +} - if (state.decoder) { - var chunk = state.decoder.end(); +module.exports = sign; +module.exports.getKey = getKey; +module.exports.makeKey = makeKey; - if (chunk && chunk.length) { - state.buffer.push(chunk); - state.length += state.objectMode ? 1 : chunk.length; - } - } +},{"./curves.json":113,"bn.js":117,"browserify-rsa":109,"create-hmac":129,"elliptic":147,"parse-asn1":341,"safe-buffer":390}],116:[function(require,module,exports){ +'use strict'; - state.ended = true; +// much of this based on https://github.com/indutny/self-signed/blob/gh-pages/lib/rsa.js +var Buffer = require('safe-buffer').Buffer; +var BN = require('bn.js'); +var EC = require('elliptic').ec; +var parseKeys = require('parse-asn1'); +var curves = require('./curves.json'); - if (state.sync) { - // if we are sync, wait until next tick to emit the data. - // Otherwise we risk emitting data in the flow() - // the readable code triggers during a read() call - emitReadable(stream); - } else { - // emit 'readable' now to make sure it gets picked up. - state.needReadable = false; - - if (!state.emittedReadable) { - state.emittedReadable = true; - emitReadable_(stream); - } +function verify(sig, hash, key, signType, tag) { + var pub = parseKeys(key); + if (pub.type === 'ec') { + // rsa keys can be interpreted as ecdsa ones in openssl + if (signType !== 'ecdsa' && signType !== 'ecdsa/rsa') { throw new Error('wrong public key type'); } + return ecVerify(sig, hash, pub); + } else if (pub.type === 'dsa') { + if (signType !== 'dsa') { throw new Error('wrong public key type'); } + return dsaVerify(sig, hash, pub); } -} // Don't emit readable right away in sync mode, because this can trigger -// another read() call => stack overflow. This way, it might trigger -// a nextTick recursion warning, but that's not so bad. - - -function emitReadable(stream) { - var state = stream._readableState; - debug('emitReadable', state.needReadable, state.emittedReadable); - state.needReadable = false; + if (signType !== 'rsa' && signType !== 'ecdsa/rsa') { throw new Error('wrong public key type'); } - if (!state.emittedReadable) { - debug('emitReadable', state.flowing); - state.emittedReadable = true; - process.nextTick(emitReadable_, stream); + hash = Buffer.concat([tag, hash]); + var len = pub.modulus.byteLength(); + var pad = [1]; + var padNum = 0; + while (hash.length + pad.length + 2 < len) { + pad.push(0xff); + padNum += 1; } -} - -function emitReadable_(stream) { - var state = stream._readableState; - debug('emitReadable_', state.destroyed, state.length, state.ended); + pad.push(0x00); + var i = -1; + while (++i < hash.length) { + pad.push(hash[i]); + } + pad = Buffer.from(pad); + var red = BN.mont(pub.modulus); + sig = new BN(sig).toRed(red); - if (!state.destroyed && (state.length || state.ended)) { - stream.emit('readable'); - state.emittedReadable = false; - } // The stream needs another readable event if - // 1. It is not flowing, as the flow mechanism will take - // care of it. - // 2. It is not ended. - // 3. It is below the highWaterMark, so we can schedule - // another readable later. + sig = sig.redPow(new BN(pub.publicExponent)); + sig = Buffer.from(sig.fromRed().toArray()); + var out = padNum < 8 ? 1 : 0; + len = Math.min(sig.length, pad.length); + if (sig.length !== pad.length) { out = 1; } + i = -1; + while (++i < len) { out |= sig[i] ^ pad[i]; } + return out === 0; +} - state.needReadable = !state.flowing && !state.ended && state.length <= state.highWaterMark; - flow(stream); -} // at this point, the user has presumably seen the 'readable' event, -// and called read() to consume some data. that may have triggered -// in turn another _read(n) call, in which case reading = true if -// it's in progress. -// However, if we're not ended, or reading, and the length < hwm, -// then go ahead and try to read some more preemptively. +function ecVerify(sig, hash, pub) { + var curveId = curves[pub.data.algorithm.curve.join('.')]; + if (!curveId) { throw new Error('unknown curve ' + pub.data.algorithm.curve.join('.')); } + var curve = new EC(curveId); + var pubkey = pub.data.subjectPrivateKey.data; -function maybeReadMore(stream, state) { - if (!state.readingMore) { - state.readingMore = true; - process.nextTick(maybeReadMore_, stream, state); - } + return curve.verify(hash, sig, pubkey); } -function maybeReadMore_(stream, state) { - // Attempt to read more data if we should. - // - // The conditions for reading more data are (one of): - // - Not enough data buffered (state.length < state.highWaterMark). The loop - // is responsible for filling the buffer with enough data if such data - // is available. If highWaterMark is 0 and we are not in the flowing mode - // we should _not_ attempt to buffer any extra data. We'll get more data - // when the stream consumer calls read() instead. - // - No data in the buffer, and the stream is in flowing mode. In this mode - // the loop below is responsible for ensuring read() is called. Failing to - // call read here would abort the flow and there's no other mechanism for - // continuing the flow if the stream consumer has just subscribed to the - // 'data' event. - // - // In addition to the above conditions to keep reading data, the following - // conditions prevent the data from being read: - // - The stream has ended (state.ended). - // - There is already a pending 'read' operation (state.reading). This is a - // case where the the stream has called the implementation defined _read() - // method, but they are processing the call asynchronously and have _not_ - // called push() with new data. In this case we skip performing more - // read()s. The execution ends in this method again after the _read() ends - // up calling push() with more data. - while (!state.reading && !state.ended && (state.length < state.highWaterMark || state.flowing && state.length === 0)) { - var len = state.length; - debug('maybeReadMore read 0'); - stream.read(0); - if (len === state.length) // didn't get any data, stop spinning. - break; - } +function dsaVerify(sig, hash, pub) { + var p = pub.data.p; + var q = pub.data.q; + var g = pub.data.g; + var y = pub.data.pub_key; + var unpacked = parseKeys.signature.decode(sig, 'der'); + var s = unpacked.s; + var r = unpacked.r; + checkValue(s, q); + checkValue(r, q); + var montp = BN.mont(p); + var w = s.invm(q); + var v = g.toRed(montp) + .redPow(new BN(hash).mul(w).mod(q)) + .fromRed() + .mul(y.toRed(montp).redPow(r.mul(w).mod(q)).fromRed()) + .mod(p) + .mod(q); + return v.cmp(r) === 0; +} - state.readingMore = false; -} // abstract method. to be overridden in specific implementation classes. -// call cb(er, data) where data is <= n in length. -// for virtual (non-string, non-buffer) streams, "length" is somewhat -// arbitrary, and perhaps not very meaningful. +function checkValue(b, q) { + if (b.cmpn(0) <= 0) { throw new Error('invalid sig'); } + if (b.cmp(q) >= 0) { throw new Error('invalid sig'); } +} +module.exports = verify; -Readable.prototype._read = function (n) { - errorOrDestroy(this, new ERR_METHOD_NOT_IMPLEMENTED('_read()')); -}; +},{"./curves.json":113,"bn.js":117,"elliptic":147,"parse-asn1":341,"safe-buffer":390}],117:[function(require,module,exports){ +arguments[4][110][0].apply(exports,arguments) +},{"buffer":88,"dup":110}],118:[function(require,module,exports){ +(function (Buffer){(function (){ +/*! + * The buffer module from node.js, for the browser. + * + * @author Feross Aboukhadijeh + * @license MIT + */ +/* eslint-disable no-proto */ -Readable.prototype.pipe = function (dest, pipeOpts) { - var src = this; - var state = this._readableState; +'use strict' - switch (state.pipesCount) { - case 0: - state.pipes = dest; - break; +var base64 = require('base64-js') +var ieee754 = require('ieee754') - case 1: - state.pipes = [state.pipes, dest]; - break; +exports.Buffer = Buffer +exports.SlowBuffer = SlowBuffer +exports.INSPECT_MAX_BYTES = 50 - default: - state.pipes.push(dest); - break; - } +var K_MAX_LENGTH = 0x7fffffff +exports.kMaxLength = K_MAX_LENGTH - state.pipesCount += 1; - debug('pipe count=%d opts=%j', state.pipesCount, pipeOpts); - var doEnd = (!pipeOpts || pipeOpts.end !== false) && dest !== process.stdout && dest !== process.stderr; - var endFn = doEnd ? onend : unpipe; - if (state.endEmitted) process.nextTick(endFn);else src.once('end', endFn); - dest.on('unpipe', onunpipe); +/** + * If `Buffer.TYPED_ARRAY_SUPPORT`: + * === true Use Uint8Array implementation (fastest) + * === false Print warning and recommend using `buffer` v4.x which has an Object + * implementation (most compatible, even IE6) + * + * Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+, + * Opera 11.6+, iOS 4.2+. + * + * We report that the browser does not support typed arrays if the are not subclassable + * using __proto__. Firefox 4-29 lacks support for adding new properties to `Uint8Array` + * (See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438). IE 10 lacks support + * for __proto__ and has a buggy typed array implementation. + */ +Buffer.TYPED_ARRAY_SUPPORT = typedArraySupport() - function onunpipe(readable, unpipeInfo) { - debug('onunpipe'); +if (!Buffer.TYPED_ARRAY_SUPPORT && typeof console !== 'undefined' && + typeof console.error === 'function') { + console.error( + 'This browser lacks typed array (Uint8Array) support which is required by ' + + '`buffer` v5.x. Use `buffer` v4.x if you require old browser support.' + ) +} - if (readable === src) { - if (unpipeInfo && unpipeInfo.hasUnpiped === false) { - unpipeInfo.hasUnpiped = true; - cleanup(); - } - } +function typedArraySupport () { + // Can typed array instances can be augmented? + try { + var arr = new Uint8Array(1) + arr.__proto__ = { __proto__: Uint8Array.prototype, foo: function () { return 42 } } + return arr.foo() === 42 + } catch (e) { + return false } +} - function onend() { - debug('onend'); - dest.end(); - } // when the dest drains, it reduces the awaitDrain counter - // on the source. This would be more elegant with a .once() - // handler in flow(), but adding and removing repeatedly is - // too slow. - +Object.defineProperty(Buffer.prototype, 'parent', { + enumerable: true, + get: function () { + if (!Buffer.isBuffer(this)) return undefined + return this.buffer + } +}) - var ondrain = pipeOnDrain(src); - dest.on('drain', ondrain); - var cleanedUp = false; +Object.defineProperty(Buffer.prototype, 'offset', { + enumerable: true, + get: function () { + if (!Buffer.isBuffer(this)) return undefined + return this.byteOffset + } +}) - function cleanup() { - debug('cleanup'); // cleanup event handlers once the pipe is broken +function createBuffer (length) { + if (length > K_MAX_LENGTH) { + throw new RangeError('The value "' + length + '" is invalid for option "size"') + } + // Return an augmented `Uint8Array` instance + var buf = new Uint8Array(length) + buf.__proto__ = Buffer.prototype + return buf +} - dest.removeListener('close', onclose); - dest.removeListener('finish', onfinish); - dest.removeListener('drain', ondrain); - dest.removeListener('error', onerror); - dest.removeListener('unpipe', onunpipe); - src.removeListener('end', onend); - src.removeListener('end', unpipe); - src.removeListener('data', ondata); - cleanedUp = true; // if the reader is waiting for a drain event from this - // specific writer, then it would cause it to never start - // flowing again. - // So, if this is awaiting a drain, then we just call it now. - // If we don't know, then assume that we are waiting for one. +/** + * The Buffer constructor returns instances of `Uint8Array` that have their + * prototype changed to `Buffer.prototype`. Furthermore, `Buffer` is a subclass of + * `Uint8Array`, so the returned instances will have all the node `Buffer` methods + * and the `Uint8Array` methods. Square bracket notation works as expected -- it + * returns a single octet. + * + * The `Uint8Array` prototype remains unmodified. + */ - if (state.awaitDrain && (!dest._writableState || dest._writableState.needDrain)) ondrain(); +function Buffer (arg, encodingOrOffset, length) { + // Common case. + if (typeof arg === 'number') { + if (typeof encodingOrOffset === 'string') { + throw new TypeError( + 'The "string" argument must be of type string. Received type number' + ) + } + return allocUnsafe(arg) } + return from(arg, encodingOrOffset, length) +} - src.on('data', ondata); - - function ondata(chunk) { - debug('ondata'); - var ret = dest.write(chunk); - debug('dest.write', ret); +// Fix subarray() in ES2016. See: https://github.com/feross/buffer/pull/97 +if (typeof Symbol !== 'undefined' && Symbol.species != null && + Buffer[Symbol.species] === Buffer) { + Object.defineProperty(Buffer, Symbol.species, { + value: null, + configurable: true, + enumerable: false, + writable: false + }) +} - if (ret === false) { - // If the user unpiped during `dest.write()`, it is possible - // to get stuck in a permanently paused state if that write - // also returned false. - // => Check whether `dest` is still a piping destination. - if ((state.pipesCount === 1 && state.pipes === dest || state.pipesCount > 1 && indexOf(state.pipes, dest) !== -1) && !cleanedUp) { - debug('false write response, pause', state.awaitDrain); - state.awaitDrain++; - } +Buffer.poolSize = 8192 // not used by this implementation - src.pause(); - } - } // if the dest has an error, then stop piping into it. - // however, don't suppress the throwing behavior for this. +function from (value, encodingOrOffset, length) { + if (typeof value === 'string') { + return fromString(value, encodingOrOffset) + } + if (ArrayBuffer.isView(value)) { + return fromArrayLike(value) + } - function onerror(er) { - debug('onerror', er); - unpipe(); - dest.removeListener('error', onerror); - if (EElistenerCount(dest, 'error') === 0) errorOrDestroy(dest, er); - } // Make sure our error handler is attached before userland ones. + if (value == null) { + throw TypeError( + 'The first argument must be one of type string, Buffer, ArrayBuffer, Array, ' + + 'or Array-like Object. Received type ' + (typeof value) + ) + } + if (isInstance(value, ArrayBuffer) || + (value && isInstance(value.buffer, ArrayBuffer))) { + return fromArrayBuffer(value, encodingOrOffset, length) + } - prependListener(dest, 'error', onerror); // Both close and finish should trigger unpipe, but only once. + if (typeof value === 'number') { + throw new TypeError( + 'The "value" argument must not be of type number. Received type number' + ) + } - function onclose() { - dest.removeListener('finish', onfinish); - unpipe(); + var valueOf = value.valueOf && value.valueOf() + if (valueOf != null && valueOf !== value) { + return Buffer.from(valueOf, encodingOrOffset, length) } - dest.once('close', onclose); + var b = fromObject(value) + if (b) return b - function onfinish() { - debug('onfinish'); - dest.removeListener('close', onclose); - unpipe(); + if (typeof Symbol !== 'undefined' && Symbol.toPrimitive != null && + typeof value[Symbol.toPrimitive] === 'function') { + return Buffer.from( + value[Symbol.toPrimitive]('string'), encodingOrOffset, length + ) } - dest.once('finish', onfinish); + throw new TypeError( + 'The first argument must be one of type string, Buffer, ArrayBuffer, Array, ' + + 'or Array-like Object. Received type ' + (typeof value) + ) +} - function unpipe() { - debug('unpipe'); - src.unpipe(dest); - } // tell the dest that it's being piped to +/** + * Functionally equivalent to Buffer(arg, encoding) but throws a TypeError + * if value is a number. + * Buffer.from(str[, encoding]) + * Buffer.from(array) + * Buffer.from(buffer) + * Buffer.from(arrayBuffer[, byteOffset[, length]]) + **/ +Buffer.from = function (value, encodingOrOffset, length) { + return from(value, encodingOrOffset, length) +} +// Note: Change prototype *after* Buffer.from is defined to workaround Chrome bug: +// https://github.com/feross/buffer/pull/148 +Buffer.prototype.__proto__ = Uint8Array.prototype +Buffer.__proto__ = Uint8Array - dest.emit('pipe', src); // start the flow if it hasn't been started already. +function assertSize (size) { + if (typeof size !== 'number') { + throw new TypeError('"size" argument must be of type number') + } else if (size < 0) { + throw new RangeError('The value "' + size + '" is invalid for option "size"') + } +} - if (!state.flowing) { - debug('pipe resume'); - src.resume(); +function alloc (size, fill, encoding) { + assertSize(size) + if (size <= 0) { + return createBuffer(size) + } + if (fill !== undefined) { + // Only pay attention to encoding if it's a string. This + // prevents accidentally sending in a number that would + // be interpretted as a start offset. + return typeof encoding === 'string' + ? createBuffer(size).fill(fill, encoding) + : createBuffer(size).fill(fill) } + return createBuffer(size) +} - return dest; -}; +/** + * Creates a new filled Buffer instance. + * alloc(size[, fill[, encoding]]) + **/ +Buffer.alloc = function (size, fill, encoding) { + return alloc(size, fill, encoding) +} -function pipeOnDrain(src) { - return function pipeOnDrainFunctionResult() { - var state = src._readableState; - debug('pipeOnDrain', state.awaitDrain); - if (state.awaitDrain) state.awaitDrain--; +function allocUnsafe (size) { + assertSize(size) + return createBuffer(size < 0 ? 0 : checked(size) | 0) +} - if (state.awaitDrain === 0 && EElistenerCount(src, 'data')) { - state.flowing = true; - flow(src); - } - }; +/** + * Equivalent to Buffer(num), by default creates a non-zero-filled Buffer instance. + * */ +Buffer.allocUnsafe = function (size) { + return allocUnsafe(size) +} +/** + * Equivalent to SlowBuffer(num), by default creates a non-zero-filled Buffer instance. + */ +Buffer.allocUnsafeSlow = function (size) { + return allocUnsafe(size) } -Readable.prototype.unpipe = function (dest) { - var state = this._readableState; - var unpipeInfo = { - hasUnpiped: false - }; // if we're not piping anywhere, then do nothing. +function fromString (string, encoding) { + if (typeof encoding !== 'string' || encoding === '') { + encoding = 'utf8' + } - if (state.pipesCount === 0) return this; // just one destination. most common case. + if (!Buffer.isEncoding(encoding)) { + throw new TypeError('Unknown encoding: ' + encoding) + } - if (state.pipesCount === 1) { - // passed in one, but it's not the right one. - if (dest && dest !== state.pipes) return this; - if (!dest) dest = state.pipes; // got a match. + var length = byteLength(string, encoding) | 0 + var buf = createBuffer(length) - state.pipes = null; - state.pipesCount = 0; - state.flowing = false; - if (dest) dest.emit('unpipe', this, unpipeInfo); - return this; - } // slow case. multiple pipe destinations. + var actual = buf.write(string, encoding) + if (actual !== length) { + // Writing a hex string, for example, that contains invalid characters will + // cause everything after the first invalid character to be ignored. (e.g. + // 'abxxcd' will be treated as 'ab') + buf = buf.slice(0, actual) + } - if (!dest) { - // remove all. - var dests = state.pipes; - var len = state.pipesCount; - state.pipes = null; - state.pipesCount = 0; - state.flowing = false; + return buf +} - for (var i = 0; i < len; i++) { - dests[i].emit('unpipe', this, { - hasUnpiped: false - }); - } +function fromArrayLike (array) { + var length = array.length < 0 ? 0 : checked(array.length) | 0 + var buf = createBuffer(length) + for (var i = 0; i < length; i += 1) { + buf[i] = array[i] & 255 + } + return buf +} - return this; - } // try to find the right one. +function fromArrayBuffer (array, byteOffset, length) { + if (byteOffset < 0 || array.byteLength < byteOffset) { + throw new RangeError('"offset" is outside of buffer bounds') + } + if (array.byteLength < byteOffset + (length || 0)) { + throw new RangeError('"length" is outside of buffer bounds') + } - var index = indexOf(state.pipes, dest); - if (index === -1) return this; - state.pipes.splice(index, 1); - state.pipesCount -= 1; - if (state.pipesCount === 1) state.pipes = state.pipes[0]; - dest.emit('unpipe', this, unpipeInfo); - return this; -}; // set up data events if they are asked for -// Ensure readable listeners eventually get something + var buf + if (byteOffset === undefined && length === undefined) { + buf = new Uint8Array(array) + } else if (length === undefined) { + buf = new Uint8Array(array, byteOffset) + } else { + buf = new Uint8Array(array, byteOffset, length) + } + // Return an augmented `Uint8Array` instance + buf.__proto__ = Buffer.prototype + return buf +} -Readable.prototype.on = function (ev, fn) { - var res = Stream.prototype.on.call(this, ev, fn); - var state = this._readableState; +function fromObject (obj) { + if (Buffer.isBuffer(obj)) { + var len = checked(obj.length) | 0 + var buf = createBuffer(len) - if (ev === 'data') { - // update readableListening so that resume() may be a no-op - // a few lines down. This is needed to support once('readable'). - state.readableListening = this.listenerCount('readable') > 0; // Try start flowing on next tick if stream isn't explicitly paused + if (buf.length === 0) { + return buf + } - if (state.flowing !== false) this.resume(); - } else if (ev === 'readable') { - if (!state.endEmitted && !state.readableListening) { - state.readableListening = state.needReadable = true; - state.flowing = false; - state.emittedReadable = false; - debug('on readable', state.length, state.reading); + obj.copy(buf, 0, 0, len) + return buf + } - if (state.length) { - emitReadable(this); - } else if (!state.reading) { - process.nextTick(nReadingNextTick, this); - } + if (obj.length !== undefined) { + if (typeof obj.length !== 'number' || numberIsNaN(obj.length)) { + return createBuffer(0) } + return fromArrayLike(obj) } - return res; -}; - -Readable.prototype.addListener = Readable.prototype.on; - -Readable.prototype.removeListener = function (ev, fn) { - var res = Stream.prototype.removeListener.call(this, ev, fn); + if (obj.type === 'Buffer' && Array.isArray(obj.data)) { + return fromArrayLike(obj.data) + } +} - if (ev === 'readable') { - // We need to check if there is someone still listening to - // readable and reset the state. However this needs to happen - // after readable has been emitted but before I/O (nextTick) to - // support once('readable', fn) cycles. This means that calling - // resume within the same tick will have no - // effect. - process.nextTick(updateReadableListening, this); +function checked (length) { + // Note: cannot use `length < K_MAX_LENGTH` here because that fails when + // length is NaN (which is otherwise coerced to zero.) + if (length >= K_MAX_LENGTH) { + throw new RangeError('Attempt to allocate Buffer larger than maximum ' + + 'size: 0x' + K_MAX_LENGTH.toString(16) + ' bytes') } + return length | 0 +} - return res; -}; +function SlowBuffer (length) { + if (+length != length) { // eslint-disable-line eqeqeq + length = 0 + } + return Buffer.alloc(+length) +} -Readable.prototype.removeAllListeners = function (ev) { - var res = Stream.prototype.removeAllListeners.apply(this, arguments); +Buffer.isBuffer = function isBuffer (b) { + return b != null && b._isBuffer === true && + b !== Buffer.prototype // so Buffer.isBuffer(Buffer.prototype) will be false +} - if (ev === 'readable' || ev === undefined) { - // We need to check if there is someone still listening to - // readable and reset the state. However this needs to happen - // after readable has been emitted but before I/O (nextTick) to - // support once('readable', fn) cycles. This means that calling - // resume within the same tick will have no - // effect. - process.nextTick(updateReadableListening, this); +Buffer.compare = function compare (a, b) { + if (isInstance(a, Uint8Array)) a = Buffer.from(a, a.offset, a.byteLength) + if (isInstance(b, Uint8Array)) b = Buffer.from(b, b.offset, b.byteLength) + if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) { + throw new TypeError( + 'The "buf1", "buf2" arguments must be one of type Buffer or Uint8Array' + ) } - return res; -}; + if (a === b) return 0 -function updateReadableListening(self) { - var state = self._readableState; - state.readableListening = self.listenerCount('readable') > 0; + var x = a.length + var y = b.length - if (state.resumeScheduled && !state.paused) { - // flowing needs to be set to true now, otherwise - // the upcoming resume will not flow. - state.flowing = true; // crude way to check if we should resume - } else if (self.listenerCount('data') > 0) { - self.resume(); + for (var i = 0, len = Math.min(x, y); i < len; ++i) { + if (a[i] !== b[i]) { + x = a[i] + y = b[i] + break + } } -} - -function nReadingNextTick(self) { - debug('readable nexttick read 0'); - self.read(0); -} // pause() and resume() are remnants of the legacy readable stream API -// If the user uses them, then switch into old mode. + if (x < y) return -1 + if (y < x) return 1 + return 0 +} -Readable.prototype.resume = function () { - var state = this._readableState; +Buffer.isEncoding = function isEncoding (encoding) { + switch (String(encoding).toLowerCase()) { + case 'hex': + case 'utf8': + case 'utf-8': + case 'ascii': + case 'latin1': + case 'binary': + case 'base64': + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return true + default: + return false + } +} - if (!state.flowing) { - debug('resume'); // we flow only if there is no one listening - // for readable, but we still have to call - // resume() +Buffer.concat = function concat (list, length) { + if (!Array.isArray(list)) { + throw new TypeError('"list" argument must be an Array of Buffers') + } - state.flowing = !state.readableListening; - resume(this, state); + if (list.length === 0) { + return Buffer.alloc(0) } - state.paused = false; - return this; -}; + var i + if (length === undefined) { + length = 0 + for (i = 0; i < list.length; ++i) { + length += list[i].length + } + } -function resume(stream, state) { - if (!state.resumeScheduled) { - state.resumeScheduled = true; - process.nextTick(resume_, stream, state); + var buffer = Buffer.allocUnsafe(length) + var pos = 0 + for (i = 0; i < list.length; ++i) { + var buf = list[i] + if (isInstance(buf, Uint8Array)) { + buf = Buffer.from(buf) + } + if (!Buffer.isBuffer(buf)) { + throw new TypeError('"list" argument must be an Array of Buffers') + } + buf.copy(buffer, pos) + pos += buf.length } + return buffer } -function resume_(stream, state) { - debug('resume', state.reading); - - if (!state.reading) { - stream.read(0); +function byteLength (string, encoding) { + if (Buffer.isBuffer(string)) { + return string.length + } + if (ArrayBuffer.isView(string) || isInstance(string, ArrayBuffer)) { + return string.byteLength + } + if (typeof string !== 'string') { + throw new TypeError( + 'The "string" argument must be one of type string, Buffer, or ArrayBuffer. ' + + 'Received type ' + typeof string + ) } - state.resumeScheduled = false; - stream.emit('resume'); - flow(stream); - if (state.flowing && !state.reading) stream.read(0); + var len = string.length + var mustMatch = (arguments.length > 2 && arguments[2] === true) + if (!mustMatch && len === 0) return 0 + + // Use a for loop to avoid recursion + var loweredCase = false + for (;;) { + switch (encoding) { + case 'ascii': + case 'latin1': + case 'binary': + return len + case 'utf8': + case 'utf-8': + return utf8ToBytes(string).length + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return len * 2 + case 'hex': + return len >>> 1 + case 'base64': + return base64ToBytes(string).length + default: + if (loweredCase) { + return mustMatch ? -1 : utf8ToBytes(string).length // assume utf8 + } + encoding = ('' + encoding).toLowerCase() + loweredCase = true + } + } } +Buffer.byteLength = byteLength -Readable.prototype.pause = function () { - debug('call pause flowing=%j', this._readableState.flowing); +function slowToString (encoding, start, end) { + var loweredCase = false - if (this._readableState.flowing !== false) { - debug('pause'); - this._readableState.flowing = false; - this.emit('pause'); + // No need to verify that "this.length <= MAX_UINT32" since it's a read-only + // property of a typed array. + + // This behaves neither like String nor Uint8Array in that we set start/end + // to their upper/lower bounds if the value passed is out of range. + // undefined is handled specially as per ECMA-262 6th Edition, + // Section 13.3.3.7 Runtime Semantics: KeyedBindingInitialization. + if (start === undefined || start < 0) { + start = 0 + } + // Return early if start > this.length. Done here to prevent potential uint32 + // coercion fail below. + if (start > this.length) { + return '' } - this._readableState.paused = true; - return this; -}; + if (end === undefined || end > this.length) { + end = this.length + } -function flow(stream) { - var state = stream._readableState; - debug('flow', state.flowing); + if (end <= 0) { + return '' + } + + // Force coersion to uint32. This will also coerce falsey/NaN values to 0. + end >>>= 0 + start >>>= 0 - while (state.flowing && stream.read() !== null) { - ; + if (end <= start) { + return '' } -} // wrap an old-style stream as the async data source. -// This is *not* part of the readable stream interface. -// It is an ugly unfortunate mess of history. + if (!encoding) encoding = 'utf8' -Readable.prototype.wrap = function (stream) { - var _this = this; + while (true) { + switch (encoding) { + case 'hex': + return hexSlice(this, start, end) - var state = this._readableState; - var paused = false; - stream.on('end', function () { - debug('wrapped end'); + case 'utf8': + case 'utf-8': + return utf8Slice(this, start, end) - if (state.decoder && !state.ended) { - var chunk = state.decoder.end(); - if (chunk && chunk.length) _this.push(chunk); - } + case 'ascii': + return asciiSlice(this, start, end) - _this.push(null); - }); - stream.on('data', function (chunk) { - debug('wrapped data'); - if (state.decoder) chunk = state.decoder.write(chunk); // don't skip over falsy values in objectMode + case 'latin1': + case 'binary': + return latin1Slice(this, start, end) - if (state.objectMode && (chunk === null || chunk === undefined)) return;else if (!state.objectMode && (!chunk || !chunk.length)) return; + case 'base64': + return base64Slice(this, start, end) - var ret = _this.push(chunk); + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return utf16leSlice(this, start, end) - if (!ret) { - paused = true; - stream.pause(); + default: + if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding) + encoding = (encoding + '').toLowerCase() + loweredCase = true } - }); // proxy all the other methods. - // important when wrapping filters and duplexes. + } +} - for (var i in stream) { - if (this[i] === undefined && typeof stream[i] === 'function') { - this[i] = function methodWrap(method) { - return function methodWrapReturnFunction() { - return stream[method].apply(stream, arguments); - }; - }(i); - } - } // proxy certain important events. +// This property is used by `Buffer.isBuffer` (and the `is-buffer` npm package) +// to detect a Buffer instance. It's not possible to use `instanceof Buffer` +// reliably in a browserify context because there could be multiple different +// copies of the 'buffer' package in use. This method works even for Buffer +// instances that were created from another copy of the `buffer` package. +// See: https://github.com/feross/buffer/issues/154 +Buffer.prototype._isBuffer = true +function swap (b, n, m) { + var i = b[n] + b[n] = b[m] + b[m] = i +} - for (var n = 0; n < kProxyEvents.length; n++) { - stream.on(kProxyEvents[n], this.emit.bind(this, kProxyEvents[n])); - } // when we try to consume some more bytes, simply unpause the - // underlying stream. +Buffer.prototype.swap16 = function swap16 () { + var len = this.length + if (len % 2 !== 0) { + throw new RangeError('Buffer size must be a multiple of 16-bits') + } + for (var i = 0; i < len; i += 2) { + swap(this, i, i + 1) + } + return this +} +Buffer.prototype.swap32 = function swap32 () { + var len = this.length + if (len % 4 !== 0) { + throw new RangeError('Buffer size must be a multiple of 32-bits') + } + for (var i = 0; i < len; i += 4) { + swap(this, i, i + 3) + swap(this, i + 1, i + 2) + } + return this +} - this._read = function (n) { - debug('wrapped _read', n); +Buffer.prototype.swap64 = function swap64 () { + var len = this.length + if (len % 8 !== 0) { + throw new RangeError('Buffer size must be a multiple of 64-bits') + } + for (var i = 0; i < len; i += 8) { + swap(this, i, i + 7) + swap(this, i + 1, i + 6) + swap(this, i + 2, i + 5) + swap(this, i + 3, i + 4) + } + return this +} - if (paused) { - paused = false; - stream.resume(); - } - }; +Buffer.prototype.toString = function toString () { + var length = this.length + if (length === 0) return '' + if (arguments.length === 0) return utf8Slice(this, 0, length) + return slowToString.apply(this, arguments) +} - return this; -}; +Buffer.prototype.toLocaleString = Buffer.prototype.toString -if (typeof Symbol === 'function') { - Readable.prototype[Symbol.asyncIterator] = function () { - if (createReadableStreamAsyncIterator === undefined) { - createReadableStreamAsyncIterator = require('./internal/streams/async_iterator'); - } +Buffer.prototype.equals = function equals (b) { + if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer') + if (this === b) return true + return Buffer.compare(this, b) === 0 +} - return createReadableStreamAsyncIterator(this); - }; +Buffer.prototype.inspect = function inspect () { + var str = '' + var max = exports.INSPECT_MAX_BYTES + str = this.toString('hex', 0, max).replace(/(.{2})/g, '$1 ').trim() + if (this.length > max) str += ' ... ' + return '' } -Object.defineProperty(Readable.prototype, 'readableHighWaterMark', { - // making it explicit this property is not enumerable - // because otherwise some prototype manipulation in - // userland will fail - enumerable: false, - get: function get() { - return this._readableState.highWaterMark; - } -}); -Object.defineProperty(Readable.prototype, 'readableBuffer', { - // making it explicit this property is not enumerable - // because otherwise some prototype manipulation in - // userland will fail - enumerable: false, - get: function get() { - return this._readableState && this._readableState.buffer; +Buffer.prototype.compare = function compare (target, start, end, thisStart, thisEnd) { + if (isInstance(target, Uint8Array)) { + target = Buffer.from(target, target.offset, target.byteLength) } -}); -Object.defineProperty(Readable.prototype, 'readableFlowing', { - // making it explicit this property is not enumerable - // because otherwise some prototype manipulation in - // userland will fail - enumerable: false, - get: function get() { - return this._readableState.flowing; - }, - set: function set(state) { - if (this._readableState) { - this._readableState.flowing = state; - } + if (!Buffer.isBuffer(target)) { + throw new TypeError( + 'The "target" argument must be one of type Buffer or Uint8Array. ' + + 'Received type ' + (typeof target) + ) } -}); // exposed for testing purposes only. -Readable._fromList = fromList; -Object.defineProperty(Readable.prototype, 'readableLength', { - // making it explicit this property is not enumerable - // because otherwise some prototype manipulation in - // userland will fail - enumerable: false, - get: function get() { - return this._readableState.length; + if (start === undefined) { + start = 0 } -}); // Pluck off n bytes from an array of buffers. -// Length is the combined lengths of all the buffers in the list. -// This function is designed to be inlinable, so please take care when making -// changes to the function body. - -function fromList(n, state) { - // nothing buffered - if (state.length === 0) return null; - var ret; - if (state.objectMode) ret = state.buffer.shift();else if (!n || n >= state.length) { - // read it all, truncate the list - if (state.decoder) ret = state.buffer.join('');else if (state.buffer.length === 1) ret = state.buffer.first();else ret = state.buffer.concat(state.length); - state.buffer.clear(); - } else { - // read part of list - ret = state.buffer.consume(n, state.decoder); + if (end === undefined) { + end = target ? target.length : 0 + } + if (thisStart === undefined) { + thisStart = 0 + } + if (thisEnd === undefined) { + thisEnd = this.length } - return ret; -} -function endReadable(stream) { - var state = stream._readableState; - debug('endReadable', state.endEmitted); + if (start < 0 || end > target.length || thisStart < 0 || thisEnd > this.length) { + throw new RangeError('out of range index') + } - if (!state.endEmitted) { - state.ended = true; - process.nextTick(endReadableNT, state, stream); + if (thisStart >= thisEnd && start >= end) { + return 0 + } + if (thisStart >= thisEnd) { + return -1 + } + if (start >= end) { + return 1 } -} -function endReadableNT(state, stream) { - debug('endReadableNT', state.endEmitted, state.length); // Check that we didn't get one last unshift. + start >>>= 0 + end >>>= 0 + thisStart >>>= 0 + thisEnd >>>= 0 - if (!state.endEmitted && state.length === 0) { - state.endEmitted = true; - stream.readable = false; - stream.emit('end'); + if (this === target) return 0 - if (state.autoDestroy) { - // In case of duplex streams we need a way to detect - // if the writable side is ready for autoDestroy as well - var wState = stream._writableState; + var x = thisEnd - thisStart + var y = end - start + var len = Math.min(x, y) - if (!wState || wState.autoDestroy && wState.finished) { - stream.destroy(); - } - } - } -} + var thisCopy = this.slice(thisStart, thisEnd) + var targetCopy = target.slice(start, end) -if (typeof Symbol === 'function') { - Readable.from = function (iterable, opts) { - if (from === undefined) { - from = require('./internal/streams/from'); + for (var i = 0; i < len; ++i) { + if (thisCopy[i] !== targetCopy[i]) { + x = thisCopy[i] + y = targetCopy[i] + break } - - return from(Readable, iterable, opts); - }; -} - -function indexOf(xs, x) { - for (var i = 0, l = xs.length; i < l; i++) { - if (xs[i] === x) return i; } - return -1; + if (x < y) return -1 + if (y < x) return 1 + return 0 } -}).call(this)}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"../errors":121,"./_stream_duplex":122,"./internal/streams/async_iterator":127,"./internal/streams/buffer_list":128,"./internal/streams/destroy":129,"./internal/streams/from":131,"./internal/streams/state":133,"./internal/streams/stream":134,"_process":391,"buffer":137,"events":211,"inherits":256,"string_decoder/":415,"util":93}],125:[function(require,module,exports){ -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. -// a transform stream is a readable/writable stream where you do -// something with the data. Sometimes it's called a "filter", -// but that's not a great name for it, since that implies a thing where -// some bits pass through, and others are simply ignored. (That would -// be a valid example of a transform, of course.) -// -// While the output is causally related to the input, it's not a -// necessarily symmetric or synchronous transformation. For example, -// a zlib stream might take multiple plain-text writes(), and then -// emit a single compressed chunk some time in the future. -// -// Here's how this works: -// -// The Transform stream has all the aspects of the readable and writable -// stream classes. When you write(chunk), that calls _write(chunk,cb) -// internally, and returns false if there's a lot of pending writes -// buffered up. When you call read(), that calls _read(n) until -// there's enough pending readable data buffered up. -// -// In a transform stream, the written data is placed in a buffer. When -// _read(n) is called, it transforms the queued up data, calling the -// buffered _write cb's as it consumes chunks. If consuming a single -// written chunk would result in multiple output chunks, then the first -// outputted bit calls the readcb, and subsequent chunks just go into -// the read buffer, and will cause it to emit 'readable' if necessary. -// -// This way, back-pressure is actually determined by the reading side, -// since _read has to be called to start processing a new chunk. However, -// a pathological inflate type of transform can cause excessive buffering -// here. For example, imagine a stream where every byte of input is -// interpreted as an integer from 0-255, and then results in that many -// bytes of output. Writing the 4 bytes {ff,ff,ff,ff} would result in -// 1kb of data being output. In this case, you could write a very small -// amount of input, and end up with a very large amount of output. In -// such a pathological inflating mechanism, there'd be no way to tell -// the system to stop doing the transform. A single 4MB write could -// cause the system to run out of memory. -// -// However, even in such a pathological case, only a single written chunk -// would be consumed, and then the rest would wait (un-transformed) until -// the results of the previous transformed chunk were consumed. -'use strict'; - -module.exports = Transform; - -var _require$codes = require('../errors').codes, - ERR_METHOD_NOT_IMPLEMENTED = _require$codes.ERR_METHOD_NOT_IMPLEMENTED, - ERR_MULTIPLE_CALLBACK = _require$codes.ERR_MULTIPLE_CALLBACK, - ERR_TRANSFORM_ALREADY_TRANSFORMING = _require$codes.ERR_TRANSFORM_ALREADY_TRANSFORMING, - ERR_TRANSFORM_WITH_LENGTH_0 = _require$codes.ERR_TRANSFORM_WITH_LENGTH_0; - -var Duplex = require('./_stream_duplex'); - -require('inherits')(Transform, Duplex); -function afterTransform(er, data) { - var ts = this._transformState; - ts.transforming = false; - var cb = ts.writecb; +// Finds either the first index of `val` in `buffer` at offset >= `byteOffset`, +// OR the last index of `val` in `buffer` at offset <= `byteOffset`. +// +// Arguments: +// - buffer - a Buffer to search +// - val - a string, Buffer, or number +// - byteOffset - an index into `buffer`; will be clamped to an int32 +// - encoding - an optional encoding, relevant is val is a string +// - dir - true for indexOf, false for lastIndexOf +function bidirectionalIndexOf (buffer, val, byteOffset, encoding, dir) { + // Empty buffer means no match + if (buffer.length === 0) return -1 - if (cb === null) { - return this.emit('error', new ERR_MULTIPLE_CALLBACK()); + // Normalize byteOffset + if (typeof byteOffset === 'string') { + encoding = byteOffset + byteOffset = 0 + } else if (byteOffset > 0x7fffffff) { + byteOffset = 0x7fffffff + } else if (byteOffset < -0x80000000) { + byteOffset = -0x80000000 } - - ts.writechunk = null; - ts.writecb = null; - if (data != null) // single equals check for both `null` and `undefined` - this.push(data); - cb(er); - var rs = this._readableState; - rs.reading = false; - - if (rs.needReadable || rs.length < rs.highWaterMark) { - this._read(rs.highWaterMark); + byteOffset = +byteOffset // Coerce to Number. + if (numberIsNaN(byteOffset)) { + // byteOffset: it it's undefined, null, NaN, "foo", etc, search whole buffer + byteOffset = dir ? 0 : (buffer.length - 1) } -} - -function Transform(options) { - if (!(this instanceof Transform)) return new Transform(options); - Duplex.call(this, options); - this._transformState = { - afterTransform: afterTransform.bind(this), - needTransform: false, - transforming: false, - writecb: null, - writechunk: null, - writeencoding: null - }; // start out asking for a readable event once data is transformed. - this._readableState.needReadable = true; // we have implemented the _read method, and done the other things - // that Readable wants before the first _read call, so unset the - // sync guard flag. - - this._readableState.sync = false; + // Normalize byteOffset: negative offsets start from the end of the buffer + if (byteOffset < 0) byteOffset = buffer.length + byteOffset + if (byteOffset >= buffer.length) { + if (dir) return -1 + else byteOffset = buffer.length - 1 + } else if (byteOffset < 0) { + if (dir) byteOffset = 0 + else return -1 + } - if (options) { - if (typeof options.transform === 'function') this._transform = options.transform; - if (typeof options.flush === 'function') this._flush = options.flush; - } // When the writable side finishes, then flush out anything remaining. + // Normalize val + if (typeof val === 'string') { + val = Buffer.from(val, encoding) + } + // Finally, search either indexOf (if dir is true) or lastIndexOf + if (Buffer.isBuffer(val)) { + // Special case: looking for empty string/buffer always fails + if (val.length === 0) { + return -1 + } + return arrayIndexOf(buffer, val, byteOffset, encoding, dir) + } else if (typeof val === 'number') { + val = val & 0xFF // Search for a byte value [0-255] + if (typeof Uint8Array.prototype.indexOf === 'function') { + if (dir) { + return Uint8Array.prototype.indexOf.call(buffer, val, byteOffset) + } else { + return Uint8Array.prototype.lastIndexOf.call(buffer, val, byteOffset) + } + } + return arrayIndexOf(buffer, [ val ], byteOffset, encoding, dir) + } - this.on('prefinish', prefinish); + throw new TypeError('val must be string, number or Buffer') } -function prefinish() { - var _this = this; +function arrayIndexOf (arr, val, byteOffset, encoding, dir) { + var indexSize = 1 + var arrLength = arr.length + var valLength = val.length - if (typeof this._flush === 'function' && !this._readableState.destroyed) { - this._flush(function (er, data) { - done(_this, er, data); - }); - } else { - done(this, null, null); + if (encoding !== undefined) { + encoding = String(encoding).toLowerCase() + if (encoding === 'ucs2' || encoding === 'ucs-2' || + encoding === 'utf16le' || encoding === 'utf-16le') { + if (arr.length < 2 || val.length < 2) { + return -1 + } + indexSize = 2 + arrLength /= 2 + valLength /= 2 + byteOffset /= 2 + } } -} - -Transform.prototype.push = function (chunk, encoding) { - this._transformState.needTransform = false; - return Duplex.prototype.push.call(this, chunk, encoding); -}; // This is the part where you do stuff! -// override this function in implementation classes. -// 'chunk' is an input chunk. -// -// Call `push(newChunk)` to pass along transformed output -// to the readable side. You may call 'push' zero or more times. -// -// Call `cb(err)` when you are done with this chunk. If you pass -// an error, then that'll put the hurt on the whole operation. If you -// never call cb(), then you'll never get another chunk. - - -Transform.prototype._transform = function (chunk, encoding, cb) { - cb(new ERR_METHOD_NOT_IMPLEMENTED('_transform()')); -}; -Transform.prototype._write = function (chunk, encoding, cb) { - var ts = this._transformState; - ts.writecb = cb; - ts.writechunk = chunk; - ts.writeencoding = encoding; + function read (buf, i) { + if (indexSize === 1) { + return buf[i] + } else { + return buf.readUInt16BE(i * indexSize) + } + } - if (!ts.transforming) { - var rs = this._readableState; - if (ts.needTransform || rs.needReadable || rs.length < rs.highWaterMark) this._read(rs.highWaterMark); + var i + if (dir) { + var foundIndex = -1 + for (i = byteOffset; i < arrLength; i++) { + if (read(arr, i) === read(val, foundIndex === -1 ? 0 : i - foundIndex)) { + if (foundIndex === -1) foundIndex = i + if (i - foundIndex + 1 === valLength) return foundIndex * indexSize + } else { + if (foundIndex !== -1) i -= i - foundIndex + foundIndex = -1 + } + } + } else { + if (byteOffset + valLength > arrLength) byteOffset = arrLength - valLength + for (i = byteOffset; i >= 0; i--) { + var found = true + for (var j = 0; j < valLength; j++) { + if (read(arr, i + j) !== read(val, j)) { + found = false + break + } + } + if (found) return i + } } -}; // Doesn't matter what the args are here. -// _transform does all the work. -// That we got here means that the readable side wants more data. + return -1 +} -Transform.prototype._read = function (n) { - var ts = this._transformState; +Buffer.prototype.includes = function includes (val, byteOffset, encoding) { + return this.indexOf(val, byteOffset, encoding) !== -1 +} - if (ts.writechunk !== null && !ts.transforming) { - ts.transforming = true; +Buffer.prototype.indexOf = function indexOf (val, byteOffset, encoding) { + return bidirectionalIndexOf(this, val, byteOffset, encoding, true) +} - this._transform(ts.writechunk, ts.writeencoding, ts.afterTransform); +Buffer.prototype.lastIndexOf = function lastIndexOf (val, byteOffset, encoding) { + return bidirectionalIndexOf(this, val, byteOffset, encoding, false) +} + +function hexWrite (buf, string, offset, length) { + offset = Number(offset) || 0 + var remaining = buf.length - offset + if (!length) { + length = remaining } else { - // mark that we need a transform, so that any data that comes in - // will get processed, now that we've asked for it. - ts.needTransform = true; + length = Number(length) + if (length > remaining) { + length = remaining + } } -}; - -Transform.prototype._destroy = function (err, cb) { - Duplex.prototype._destroy.call(this, err, function (err2) { - cb(err2); - }); -}; -function done(stream, er, data) { - if (er) return stream.emit('error', er); - if (data != null) // single equals check for both `null` and `undefined` - stream.push(data); // TODO(BridgeAR): Write a test for these two error cases - // if there's nothing in the write buffer, then that means - // that nothing more will ever be provided + var strLen = string.length - if (stream._writableState.length) throw new ERR_TRANSFORM_WITH_LENGTH_0(); - if (stream._transformState.transforming) throw new ERR_TRANSFORM_ALREADY_TRANSFORMING(); - return stream.push(null); + if (length > strLen / 2) { + length = strLen / 2 + } + for (var i = 0; i < length; ++i) { + var parsed = parseInt(string.substr(i * 2, 2), 16) + if (numberIsNaN(parsed)) return i + buf[offset + i] = parsed + } + return i } -},{"../errors":121,"./_stream_duplex":122,"inherits":256}],126:[function(require,module,exports){ -(function (process,global){(function (){ -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. -// A bit simpler than readable streams. -// Implement an async ._write(chunk, encoding, cb), and it'll handle all -// the drain event emission and buffering. -'use strict'; - -module.exports = Writable; -/* */ -function WriteReq(chunk, encoding, cb) { - this.chunk = chunk; - this.encoding = encoding; - this.callback = cb; - this.next = null; -} // It seems a linked list but it is not -// there will be only 2 of these for each stream +function utf8Write (buf, string, offset, length) { + return blitBuffer(utf8ToBytes(string, buf.length - offset), buf, offset, length) +} +function asciiWrite (buf, string, offset, length) { + return blitBuffer(asciiToBytes(string), buf, offset, length) +} -function CorkedRequest(state) { - var _this = this; +function latin1Write (buf, string, offset, length) { + return asciiWrite(buf, string, offset, length) +} - this.next = null; - this.entry = null; +function base64Write (buf, string, offset, length) { + return blitBuffer(base64ToBytes(string), buf, offset, length) +} - this.finish = function () { - onCorkedFinish(_this, state); - }; +function ucs2Write (buf, string, offset, length) { + return blitBuffer(utf16leToBytes(string, buf.length - offset), buf, offset, length) } -/* */ -/**/ +Buffer.prototype.write = function write (string, offset, length, encoding) { + // Buffer#write(string) + if (offset === undefined) { + encoding = 'utf8' + length = this.length + offset = 0 + // Buffer#write(string, encoding) + } else if (length === undefined && typeof offset === 'string') { + encoding = offset + length = this.length + offset = 0 + // Buffer#write(string, offset[, length][, encoding]) + } else if (isFinite(offset)) { + offset = offset >>> 0 + if (isFinite(length)) { + length = length >>> 0 + if (encoding === undefined) encoding = 'utf8' + } else { + encoding = length + length = undefined + } + } else { + throw new Error( + 'Buffer.write(string, encoding, offset[, length]) is no longer supported' + ) + } + var remaining = this.length - offset + if (length === undefined || length > remaining) length = remaining -var Duplex; -/**/ + if ((string.length > 0 && (length < 0 || offset < 0)) || offset > this.length) { + throw new RangeError('Attempt to write outside buffer bounds') + } -Writable.WritableState = WritableState; -/**/ + if (!encoding) encoding = 'utf8' -var internalUtil = { - deprecate: require('util-deprecate') -}; -/**/ + var loweredCase = false + for (;;) { + switch (encoding) { + case 'hex': + return hexWrite(this, string, offset, length) -/**/ + case 'utf8': + case 'utf-8': + return utf8Write(this, string, offset, length) -var Stream = require('./internal/streams/stream'); -/**/ + case 'ascii': + return asciiWrite(this, string, offset, length) + case 'latin1': + case 'binary': + return latin1Write(this, string, offset, length) -var Buffer = require('buffer').Buffer; + case 'base64': + // Warning: maxLength not taken into account in base64Write + return base64Write(this, string, offset, length) -var OurUint8Array = global.Uint8Array || function () {}; + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return ucs2Write(this, string, offset, length) -function _uint8ArrayToBuffer(chunk) { - return Buffer.from(chunk); + default: + if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding) + encoding = ('' + encoding).toLowerCase() + loweredCase = true + } + } } -function _isUint8Array(obj) { - return Buffer.isBuffer(obj) || obj instanceof OurUint8Array; +Buffer.prototype.toJSON = function toJSON () { + return { + type: 'Buffer', + data: Array.prototype.slice.call(this._arr || this, 0) + } } -var destroyImpl = require('./internal/streams/destroy'); +function base64Slice (buf, start, end) { + if (start === 0 && end === buf.length) { + return base64.fromByteArray(buf) + } else { + return base64.fromByteArray(buf.slice(start, end)) + } +} -var _require = require('./internal/streams/state'), - getHighWaterMark = _require.getHighWaterMark; +function utf8Slice (buf, start, end) { + end = Math.min(buf.length, end) + var res = [] -var _require$codes = require('../errors').codes, - ERR_INVALID_ARG_TYPE = _require$codes.ERR_INVALID_ARG_TYPE, - ERR_METHOD_NOT_IMPLEMENTED = _require$codes.ERR_METHOD_NOT_IMPLEMENTED, - ERR_MULTIPLE_CALLBACK = _require$codes.ERR_MULTIPLE_CALLBACK, - ERR_STREAM_CANNOT_PIPE = _require$codes.ERR_STREAM_CANNOT_PIPE, - ERR_STREAM_DESTROYED = _require$codes.ERR_STREAM_DESTROYED, - ERR_STREAM_NULL_VALUES = _require$codes.ERR_STREAM_NULL_VALUES, - ERR_STREAM_WRITE_AFTER_END = _require$codes.ERR_STREAM_WRITE_AFTER_END, - ERR_UNKNOWN_ENCODING = _require$codes.ERR_UNKNOWN_ENCODING; + var i = start + while (i < end) { + var firstByte = buf[i] + var codePoint = null + var bytesPerSequence = (firstByte > 0xEF) ? 4 + : (firstByte > 0xDF) ? 3 + : (firstByte > 0xBF) ? 2 + : 1 -var errorOrDestroy = destroyImpl.errorOrDestroy; + if (i + bytesPerSequence <= end) { + var secondByte, thirdByte, fourthByte, tempCodePoint -require('inherits')(Writable, Stream); + switch (bytesPerSequence) { + case 1: + if (firstByte < 0x80) { + codePoint = firstByte + } + break + case 2: + secondByte = buf[i + 1] + if ((secondByte & 0xC0) === 0x80) { + tempCodePoint = (firstByte & 0x1F) << 0x6 | (secondByte & 0x3F) + if (tempCodePoint > 0x7F) { + codePoint = tempCodePoint + } + } + break + case 3: + secondByte = buf[i + 1] + thirdByte = buf[i + 2] + if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80) { + tempCodePoint = (firstByte & 0xF) << 0xC | (secondByte & 0x3F) << 0x6 | (thirdByte & 0x3F) + if (tempCodePoint > 0x7FF && (tempCodePoint < 0xD800 || tempCodePoint > 0xDFFF)) { + codePoint = tempCodePoint + } + } + break + case 4: + secondByte = buf[i + 1] + thirdByte = buf[i + 2] + fourthByte = buf[i + 3] + if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80 && (fourthByte & 0xC0) === 0x80) { + tempCodePoint = (firstByte & 0xF) << 0x12 | (secondByte & 0x3F) << 0xC | (thirdByte & 0x3F) << 0x6 | (fourthByte & 0x3F) + if (tempCodePoint > 0xFFFF && tempCodePoint < 0x110000) { + codePoint = tempCodePoint + } + } + } + } -function nop() {} + if (codePoint === null) { + // we did not generate a valid codePoint so insert a + // replacement char (U+FFFD) and advance only 1 byte + codePoint = 0xFFFD + bytesPerSequence = 1 + } else if (codePoint > 0xFFFF) { + // encode to utf16 (surrogate pair dance) + codePoint -= 0x10000 + res.push(codePoint >>> 10 & 0x3FF | 0xD800) + codePoint = 0xDC00 | codePoint & 0x3FF + } -function WritableState(options, stream, isDuplex) { - Duplex = Duplex || require('./_stream_duplex'); - options = options || {}; // Duplex streams are both readable and writable, but share - // the same options object. - // However, some cases require setting options to different - // values for the readable and the writable sides of the duplex stream, - // e.g. options.readableObjectMode vs. options.writableObjectMode, etc. + res.push(codePoint) + i += bytesPerSequence + } - if (typeof isDuplex !== 'boolean') isDuplex = stream instanceof Duplex; // object stream flag to indicate whether or not this stream - // contains buffers or objects. + return decodeCodePointsArray(res) +} - this.objectMode = !!options.objectMode; - if (isDuplex) this.objectMode = this.objectMode || !!options.writableObjectMode; // the point at which write() starts returning false - // Note: 0 is a valid value, means that we always return false if - // the entire buffer is not flushed immediately on write() +// Based on http://stackoverflow.com/a/22747272/680742, the browser with +// the lowest limit is Chrome, with 0x10000 args. +// We go 1 magnitude less, for safety +var MAX_ARGUMENTS_LENGTH = 0x1000 - this.highWaterMark = getHighWaterMark(this, options, 'writableHighWaterMark', isDuplex); // if _final has been called +function decodeCodePointsArray (codePoints) { + var len = codePoints.length + if (len <= MAX_ARGUMENTS_LENGTH) { + return String.fromCharCode.apply(String, codePoints) // avoid extra slice() + } - this.finalCalled = false; // drain event flag. + // Decode in chunks to avoid "call stack size exceeded". + var res = '' + var i = 0 + while (i < len) { + res += String.fromCharCode.apply( + String, + codePoints.slice(i, i += MAX_ARGUMENTS_LENGTH) + ) + } + return res +} - this.needDrain = false; // at the start of calling end() +function asciiSlice (buf, start, end) { + var ret = '' + end = Math.min(buf.length, end) - this.ending = false; // when end() has been called, and returned + for (var i = start; i < end; ++i) { + ret += String.fromCharCode(buf[i] & 0x7F) + } + return ret +} - this.ended = false; // when 'finish' is emitted +function latin1Slice (buf, start, end) { + var ret = '' + end = Math.min(buf.length, end) - this.finished = false; // has it been destroyed + for (var i = start; i < end; ++i) { + ret += String.fromCharCode(buf[i]) + } + return ret +} - this.destroyed = false; // should we decode strings into buffers before passing to _write? - // this is here so that some node-core streams can optimize string - // handling at a lower level. +function hexSlice (buf, start, end) { + var len = buf.length - var noDecode = options.decodeStrings === false; - this.decodeStrings = !noDecode; // Crypto is kind of old and crusty. Historically, its default string - // encoding is 'binary' so we have to make this configurable. - // Everything else in the universe uses 'utf8', though. + if (!start || start < 0) start = 0 + if (!end || end < 0 || end > len) end = len - this.defaultEncoding = options.defaultEncoding || 'utf8'; // not an actual buffer we keep track of, but a measurement - // of how much we're waiting to get pushed to some underlying - // socket or file. + var out = '' + for (var i = start; i < end; ++i) { + out += toHex(buf[i]) + } + return out +} - this.length = 0; // a flag to see when we're in the middle of a write. +function utf16leSlice (buf, start, end) { + var bytes = buf.slice(start, end) + var res = '' + for (var i = 0; i < bytes.length; i += 2) { + res += String.fromCharCode(bytes[i] + (bytes[i + 1] * 256)) + } + return res +} - this.writing = false; // when true all writes will be buffered until .uncork() call +Buffer.prototype.slice = function slice (start, end) { + var len = this.length + start = ~~start + end = end === undefined ? len : ~~end - this.corked = 0; // a flag to be able to tell if the onwrite cb is called immediately, - // or on a later tick. We set this to true at first, because any - // actions that shouldn't happen until "later" should generally also - // not happen before the first write call. + if (start < 0) { + start += len + if (start < 0) start = 0 + } else if (start > len) { + start = len + } - this.sync = true; // a flag to know if we're processing previously buffered items, which - // may call the _write() callback in the same tick, so that we don't - // end up in an overlapped onwrite situation. + if (end < 0) { + end += len + if (end < 0) end = 0 + } else if (end > len) { + end = len + } - this.bufferProcessing = false; // the callback that's passed to _write(chunk,cb) + if (end < start) end = start - this.onwrite = function (er) { - onwrite(stream, er); - }; // the callback that the user supplies to write(chunk,encoding,cb) + var newBuf = this.subarray(start, end) + // Return an augmented `Uint8Array` instance + newBuf.__proto__ = Buffer.prototype + return newBuf +} +/* + * Need to make sure that buffer isn't trying to write out of bounds. + */ +function checkOffset (offset, ext, length) { + if ((offset % 1) !== 0 || offset < 0) throw new RangeError('offset is not uint') + if (offset + ext > length) throw new RangeError('Trying to access beyond buffer length') +} - this.writecb = null; // the amount that is being written when _write is called. +Buffer.prototype.readUIntLE = function readUIntLE (offset, byteLength, noAssert) { + offset = offset >>> 0 + byteLength = byteLength >>> 0 + if (!noAssert) checkOffset(offset, byteLength, this.length) - this.writelen = 0; - this.bufferedRequest = null; - this.lastBufferedRequest = null; // number of pending user-supplied write callbacks - // this must be 0 before 'finish' can be emitted + var val = this[offset] + var mul = 1 + var i = 0 + while (++i < byteLength && (mul *= 0x100)) { + val += this[offset + i] * mul + } - this.pendingcb = 0; // emit prefinish if the only thing we're waiting for is _write cbs - // This is relevant for synchronous Transform streams + return val +} - this.prefinished = false; // True if the error was already emitted and should not be thrown again +Buffer.prototype.readUIntBE = function readUIntBE (offset, byteLength, noAssert) { + offset = offset >>> 0 + byteLength = byteLength >>> 0 + if (!noAssert) { + checkOffset(offset, byteLength, this.length) + } - this.errorEmitted = false; // Should close be emitted on destroy. Defaults to true. + var val = this[offset + --byteLength] + var mul = 1 + while (byteLength > 0 && (mul *= 0x100)) { + val += this[offset + --byteLength] * mul + } - this.emitClose = options.emitClose !== false; // Should .destroy() be called after 'finish' (and potentially 'end') + return val +} - this.autoDestroy = !!options.autoDestroy; // count buffered requests +Buffer.prototype.readUInt8 = function readUInt8 (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 1, this.length) + return this[offset] +} - this.bufferedRequestCount = 0; // allocate the first CorkedRequest, there is always - // one allocated and free to use, and we maintain at most two +Buffer.prototype.readUInt16LE = function readUInt16LE (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 2, this.length) + return this[offset] | (this[offset + 1] << 8) +} - this.corkedRequestsFree = new CorkedRequest(this); +Buffer.prototype.readUInt16BE = function readUInt16BE (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 2, this.length) + return (this[offset] << 8) | this[offset + 1] } -WritableState.prototype.getBuffer = function getBuffer() { - var current = this.bufferedRequest; - var out = []; +Buffer.prototype.readUInt32LE = function readUInt32LE (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 4, this.length) - while (current) { - out.push(current); - current = current.next; - } + return ((this[offset]) | + (this[offset + 1] << 8) | + (this[offset + 2] << 16)) + + (this[offset + 3] * 0x1000000) +} - return out; -}; +Buffer.prototype.readUInt32BE = function readUInt32BE (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 4, this.length) -(function () { - try { - Object.defineProperty(WritableState.prototype, 'buffer', { - get: internalUtil.deprecate(function writableStateBufferGetter() { - return this.getBuffer(); - }, '_writableState.buffer is deprecated. Use _writableState.getBuffer ' + 'instead.', 'DEP0003') - }); - } catch (_) {} -})(); // Test _writableState for inheritance to account for Duplex streams, -// whose prototype chain only points to Readable. + return (this[offset] * 0x1000000) + + ((this[offset + 1] << 16) | + (this[offset + 2] << 8) | + this[offset + 3]) +} + +Buffer.prototype.readIntLE = function readIntLE (offset, byteLength, noAssert) { + offset = offset >>> 0 + byteLength = byteLength >>> 0 + if (!noAssert) checkOffset(offset, byteLength, this.length) + var val = this[offset] + var mul = 1 + var i = 0 + while (++i < byteLength && (mul *= 0x100)) { + val += this[offset + i] * mul + } + mul *= 0x80 -var realHasInstance; + if (val >= mul) val -= Math.pow(2, 8 * byteLength) -if (typeof Symbol === 'function' && Symbol.hasInstance && typeof Function.prototype[Symbol.hasInstance] === 'function') { - realHasInstance = Function.prototype[Symbol.hasInstance]; - Object.defineProperty(Writable, Symbol.hasInstance, { - value: function value(object) { - if (realHasInstance.call(this, object)) return true; - if (this !== Writable) return false; - return object && object._writableState instanceof WritableState; - } - }); -} else { - realHasInstance = function realHasInstance(object) { - return object instanceof this; - }; + return val } -function Writable(options) { - Duplex = Duplex || require('./_stream_duplex'); // Writable ctor is applied to Duplexes, too. - // `realHasInstance` is necessary because using plain `instanceof` - // would return false, as no `_writableState` property is attached. - // Trying to use the custom `instanceof` for Writable here will also break the - // Node.js LazyTransform implementation, which has a non-trivial getter for - // `_writableState` that would lead to infinite recursion. - // Checking for a Stream.Duplex instance is faster here instead of inside - // the WritableState constructor, at least with V8 6.5 +Buffer.prototype.readIntBE = function readIntBE (offset, byteLength, noAssert) { + offset = offset >>> 0 + byteLength = byteLength >>> 0 + if (!noAssert) checkOffset(offset, byteLength, this.length) - var isDuplex = this instanceof Duplex; - if (!isDuplex && !realHasInstance.call(Writable, this)) return new Writable(options); - this._writableState = new WritableState(options, this, isDuplex); // legacy. + var i = byteLength + var mul = 1 + var val = this[offset + --i] + while (i > 0 && (mul *= 0x100)) { + val += this[offset + --i] * mul + } + mul *= 0x80 - this.writable = true; + if (val >= mul) val -= Math.pow(2, 8 * byteLength) - if (options) { - if (typeof options.write === 'function') this._write = options.write; - if (typeof options.writev === 'function') this._writev = options.writev; - if (typeof options.destroy === 'function') this._destroy = options.destroy; - if (typeof options.final === 'function') this._final = options.final; - } + return val +} - Stream.call(this); -} // Otherwise people can pipe Writable streams, which is just wrong. +Buffer.prototype.readInt8 = function readInt8 (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 1, this.length) + if (!(this[offset] & 0x80)) return (this[offset]) + return ((0xff - this[offset] + 1) * -1) +} +Buffer.prototype.readInt16LE = function readInt16LE (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 2, this.length) + var val = this[offset] | (this[offset + 1] << 8) + return (val & 0x8000) ? val | 0xFFFF0000 : val +} -Writable.prototype.pipe = function () { - errorOrDestroy(this, new ERR_STREAM_CANNOT_PIPE()); -}; +Buffer.prototype.readInt16BE = function readInt16BE (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 2, this.length) + var val = this[offset + 1] | (this[offset] << 8) + return (val & 0x8000) ? val | 0xFFFF0000 : val +} -function writeAfterEnd(stream, cb) { - var er = new ERR_STREAM_WRITE_AFTER_END(); // TODO: defer error events consistently everywhere, not just the cb +Buffer.prototype.readInt32LE = function readInt32LE (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 4, this.length) - errorOrDestroy(stream, er); - process.nextTick(cb, er); -} // Checks that a user-supplied chunk is valid, especially for the particular -// mode the stream is in. Currently this means that `null` is never accepted -// and undefined/non-string values are only allowed in object mode. + return (this[offset]) | + (this[offset + 1] << 8) | + (this[offset + 2] << 16) | + (this[offset + 3] << 24) +} +Buffer.prototype.readInt32BE = function readInt32BE (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 4, this.length) -function validChunk(stream, state, chunk, cb) { - var er; + return (this[offset] << 24) | + (this[offset + 1] << 16) | + (this[offset + 2] << 8) | + (this[offset + 3]) +} - if (chunk === null) { - er = new ERR_STREAM_NULL_VALUES(); - } else if (typeof chunk !== 'string' && !state.objectMode) { - er = new ERR_INVALID_ARG_TYPE('chunk', ['string', 'Buffer'], chunk); - } +Buffer.prototype.readFloatLE = function readFloatLE (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 4, this.length) + return ieee754.read(this, offset, true, 23, 4) +} - if (er) { - errorOrDestroy(stream, er); - process.nextTick(cb, er); - return false; - } +Buffer.prototype.readFloatBE = function readFloatBE (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 4, this.length) + return ieee754.read(this, offset, false, 23, 4) +} - return true; +Buffer.prototype.readDoubleLE = function readDoubleLE (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 8, this.length) + return ieee754.read(this, offset, true, 52, 8) } -Writable.prototype.write = function (chunk, encoding, cb) { - var state = this._writableState; - var ret = false; +Buffer.prototype.readDoubleBE = function readDoubleBE (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 8, this.length) + return ieee754.read(this, offset, false, 52, 8) +} - var isBuf = !state.objectMode && _isUint8Array(chunk); +function checkInt (buf, value, offset, ext, max, min) { + if (!Buffer.isBuffer(buf)) throw new TypeError('"buffer" argument must be a Buffer instance') + if (value > max || value < min) throw new RangeError('"value" argument is out of bounds') + if (offset + ext > buf.length) throw new RangeError('Index out of range') +} - if (isBuf && !Buffer.isBuffer(chunk)) { - chunk = _uint8ArrayToBuffer(chunk); +Buffer.prototype.writeUIntLE = function writeUIntLE (value, offset, byteLength, noAssert) { + value = +value + offset = offset >>> 0 + byteLength = byteLength >>> 0 + if (!noAssert) { + var maxBytes = Math.pow(2, 8 * byteLength) - 1 + checkInt(this, value, offset, byteLength, maxBytes, 0) } - if (typeof encoding === 'function') { - cb = encoding; - encoding = null; + var mul = 1 + var i = 0 + this[offset] = value & 0xFF + while (++i < byteLength && (mul *= 0x100)) { + this[offset + i] = (value / mul) & 0xFF } - if (isBuf) encoding = 'buffer';else if (!encoding) encoding = state.defaultEncoding; - if (typeof cb !== 'function') cb = nop; - if (state.ending) writeAfterEnd(this, cb);else if (isBuf || validChunk(this, state, chunk, cb)) { - state.pendingcb++; - ret = writeOrBuffer(this, state, isBuf, chunk, encoding, cb); + return offset + byteLength +} + +Buffer.prototype.writeUIntBE = function writeUIntBE (value, offset, byteLength, noAssert) { + value = +value + offset = offset >>> 0 + byteLength = byteLength >>> 0 + if (!noAssert) { + var maxBytes = Math.pow(2, 8 * byteLength) - 1 + checkInt(this, value, offset, byteLength, maxBytes, 0) } - return ret; -}; -Writable.prototype.cork = function () { - this._writableState.corked++; -}; + var i = byteLength - 1 + var mul = 1 + this[offset + i] = value & 0xFF + while (--i >= 0 && (mul *= 0x100)) { + this[offset + i] = (value / mul) & 0xFF + } -Writable.prototype.uncork = function () { - var state = this._writableState; + return offset + byteLength +} - if (state.corked) { - state.corked--; - if (!state.writing && !state.corked && !state.bufferProcessing && state.bufferedRequest) clearBuffer(this, state); - } -}; +Buffer.prototype.writeUInt8 = function writeUInt8 (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) checkInt(this, value, offset, 1, 0xff, 0) + this[offset] = (value & 0xff) + return offset + 1 +} -Writable.prototype.setDefaultEncoding = function setDefaultEncoding(encoding) { - // node::ParseEncoding() requires lower case. - if (typeof encoding === 'string') encoding = encoding.toLowerCase(); - if (!(['hex', 'utf8', 'utf-8', 'ascii', 'binary', 'base64', 'ucs2', 'ucs-2', 'utf16le', 'utf-16le', 'raw'].indexOf((encoding + '').toLowerCase()) > -1)) throw new ERR_UNKNOWN_ENCODING(encoding); - this._writableState.defaultEncoding = encoding; - return this; -}; +Buffer.prototype.writeUInt16LE = function writeUInt16LE (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0) + this[offset] = (value & 0xff) + this[offset + 1] = (value >>> 8) + return offset + 2 +} -Object.defineProperty(Writable.prototype, 'writableBuffer', { - // making it explicit this property is not enumerable - // because otherwise some prototype manipulation in - // userland will fail - enumerable: false, - get: function get() { - return this._writableState && this._writableState.getBuffer(); - } -}); +Buffer.prototype.writeUInt16BE = function writeUInt16BE (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0) + this[offset] = (value >>> 8) + this[offset + 1] = (value & 0xff) + return offset + 2 +} -function decodeChunk(state, chunk, encoding) { - if (!state.objectMode && state.decodeStrings !== false && typeof chunk === 'string') { - chunk = Buffer.from(chunk, encoding); - } +Buffer.prototype.writeUInt32LE = function writeUInt32LE (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0) + this[offset + 3] = (value >>> 24) + this[offset + 2] = (value >>> 16) + this[offset + 1] = (value >>> 8) + this[offset] = (value & 0xff) + return offset + 4 +} - return chunk; +Buffer.prototype.writeUInt32BE = function writeUInt32BE (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0) + this[offset] = (value >>> 24) + this[offset + 1] = (value >>> 16) + this[offset + 2] = (value >>> 8) + this[offset + 3] = (value & 0xff) + return offset + 4 } -Object.defineProperty(Writable.prototype, 'writableHighWaterMark', { - // making it explicit this property is not enumerable - // because otherwise some prototype manipulation in - // userland will fail - enumerable: false, - get: function get() { - return this._writableState.highWaterMark; - } -}); // if we're already writing something, then just put this -// in the queue, and wait our turn. Otherwise, call _write -// If we return false, then we need a drain event, so set that flag. +Buffer.prototype.writeIntLE = function writeIntLE (value, offset, byteLength, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) { + var limit = Math.pow(2, (8 * byteLength) - 1) -function writeOrBuffer(stream, state, isBuf, chunk, encoding, cb) { - if (!isBuf) { - var newChunk = decodeChunk(state, chunk, encoding); + checkInt(this, value, offset, byteLength, limit - 1, -limit) + } - if (chunk !== newChunk) { - isBuf = true; - encoding = 'buffer'; - chunk = newChunk; + var i = 0 + var mul = 1 + var sub = 0 + this[offset] = value & 0xFF + while (++i < byteLength && (mul *= 0x100)) { + if (value < 0 && sub === 0 && this[offset + i - 1] !== 0) { + sub = 1 } + this[offset + i] = ((value / mul) >> 0) - sub & 0xFF } - var len = state.objectMode ? 1 : chunk.length; - state.length += len; - var ret = state.length < state.highWaterMark; // we must ensure that previous needDrain will not be reset to false. + return offset + byteLength +} - if (!ret) state.needDrain = true; +Buffer.prototype.writeIntBE = function writeIntBE (value, offset, byteLength, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) { + var limit = Math.pow(2, (8 * byteLength) - 1) - if (state.writing || state.corked) { - var last = state.lastBufferedRequest; - state.lastBufferedRequest = { - chunk: chunk, - encoding: encoding, - isBuf: isBuf, - callback: cb, - next: null - }; + checkInt(this, value, offset, byteLength, limit - 1, -limit) + } - if (last) { - last.next = state.lastBufferedRequest; - } else { - state.bufferedRequest = state.lastBufferedRequest; + var i = byteLength - 1 + var mul = 1 + var sub = 0 + this[offset + i] = value & 0xFF + while (--i >= 0 && (mul *= 0x100)) { + if (value < 0 && sub === 0 && this[offset + i + 1] !== 0) { + sub = 1 } + this[offset + i] = ((value / mul) >> 0) - sub & 0xFF + } - state.bufferedRequestCount += 1; - } else { - doWrite(stream, state, false, len, chunk, encoding, cb); - } + return offset + byteLength +} - return ret; +Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80) + if (value < 0) value = 0xff + value + 1 + this[offset] = (value & 0xff) + return offset + 1 } -function doWrite(stream, state, writev, len, chunk, encoding, cb) { - state.writelen = len; - state.writecb = cb; - state.writing = true; - state.sync = true; - if (state.destroyed) state.onwrite(new ERR_STREAM_DESTROYED('write'));else if (writev) stream._writev(chunk, state.onwrite);else stream._write(chunk, encoding, state.onwrite); - state.sync = false; +Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000) + this[offset] = (value & 0xff) + this[offset + 1] = (value >>> 8) + return offset + 2 } -function onwriteError(stream, state, sync, er, cb) { - --state.pendingcb; +Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000) + this[offset] = (value >>> 8) + this[offset + 1] = (value & 0xff) + return offset + 2 +} - if (sync) { - // defer the callback if we are being called synchronously - // to avoid piling up things on the stack - process.nextTick(cb, er); // this can emit finish, and it will always happen - // after error +Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000) + this[offset] = (value & 0xff) + this[offset + 1] = (value >>> 8) + this[offset + 2] = (value >>> 16) + this[offset + 3] = (value >>> 24) + return offset + 4 +} - process.nextTick(finishMaybe, stream, state); - stream._writableState.errorEmitted = true; - errorOrDestroy(stream, er); - } else { - // the caller expect this to happen before if - // it is async - cb(er); - stream._writableState.errorEmitted = true; - errorOrDestroy(stream, er); // this can emit finish, but finish must - // always follow error +Buffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000) + if (value < 0) value = 0xffffffff + value + 1 + this[offset] = (value >>> 24) + this[offset + 1] = (value >>> 16) + this[offset + 2] = (value >>> 8) + this[offset + 3] = (value & 0xff) + return offset + 4 +} - finishMaybe(stream, state); - } +function checkIEEE754 (buf, value, offset, ext, max, min) { + if (offset + ext > buf.length) throw new RangeError('Index out of range') + if (offset < 0) throw new RangeError('Index out of range') } -function onwriteStateUpdate(state) { - state.writing = false; - state.writecb = null; - state.length -= state.writelen; - state.writelen = 0; +function writeFloat (buf, value, offset, littleEndian, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) { + checkIEEE754(buf, value, offset, 4, 3.4028234663852886e+38, -3.4028234663852886e+38) + } + ieee754.write(buf, value, offset, littleEndian, 23, 4) + return offset + 4 } -function onwrite(stream, er) { - var state = stream._writableState; - var sync = state.sync; - var cb = state.writecb; - if (typeof cb !== 'function') throw new ERR_MULTIPLE_CALLBACK(); - onwriteStateUpdate(state); - if (er) onwriteError(stream, state, sync, er, cb);else { - // Check if we're actually ready to finish, but don't emit yet - var finished = needFinish(state) || stream.destroyed; +Buffer.prototype.writeFloatLE = function writeFloatLE (value, offset, noAssert) { + return writeFloat(this, value, offset, true, noAssert) +} - if (!finished && !state.corked && !state.bufferProcessing && state.bufferedRequest) { - clearBuffer(stream, state); - } +Buffer.prototype.writeFloatBE = function writeFloatBE (value, offset, noAssert) { + return writeFloat(this, value, offset, false, noAssert) +} - if (sync) { - process.nextTick(afterWrite, stream, state, finished, cb); - } else { - afterWrite(stream, state, finished, cb); - } +function writeDouble (buf, value, offset, littleEndian, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) { + checkIEEE754(buf, value, offset, 8, 1.7976931348623157E+308, -1.7976931348623157E+308) } + ieee754.write(buf, value, offset, littleEndian, 52, 8) + return offset + 8 } -function afterWrite(stream, state, finished, cb) { - if (!finished) onwriteDrain(stream, state); - state.pendingcb--; - cb(); - finishMaybe(stream, state); -} // Must force callback to be called on nextTick, so that we don't -// emit 'drain' before the write() consumer gets the 'false' return -// value, and has a chance to attach a 'drain' listener. +Buffer.prototype.writeDoubleLE = function writeDoubleLE (value, offset, noAssert) { + return writeDouble(this, value, offset, true, noAssert) +} +Buffer.prototype.writeDoubleBE = function writeDoubleBE (value, offset, noAssert) { + return writeDouble(this, value, offset, false, noAssert) +} -function onwriteDrain(stream, state) { - if (state.length === 0 && state.needDrain) { - state.needDrain = false; - stream.emit('drain'); +// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length) +Buffer.prototype.copy = function copy (target, targetStart, start, end) { + if (!Buffer.isBuffer(target)) throw new TypeError('argument should be a Buffer') + if (!start) start = 0 + if (!end && end !== 0) end = this.length + if (targetStart >= target.length) targetStart = target.length + if (!targetStart) targetStart = 0 + if (end > 0 && end < start) end = start + + // Copy 0 bytes; we're done + if (end === start) return 0 + if (target.length === 0 || this.length === 0) return 0 + + // Fatal error conditions + if (targetStart < 0) { + throw new RangeError('targetStart out of bounds') } -} // if there's something in the buffer waiting, then process it + if (start < 0 || start >= this.length) throw new RangeError('Index out of range') + if (end < 0) throw new RangeError('sourceEnd out of bounds') + // Are we oob? + if (end > this.length) end = this.length + if (target.length - targetStart < end - start) { + end = target.length - targetStart + start + } -function clearBuffer(stream, state) { - state.bufferProcessing = true; - var entry = state.bufferedRequest; + var len = end - start - if (stream._writev && entry && entry.next) { - // Fast case, write everything using _writev() - var l = state.bufferedRequestCount; - var buffer = new Array(l); - var holder = state.corkedRequestsFree; - holder.entry = entry; - var count = 0; - var allBuffers = true; + if (this === target && typeof Uint8Array.prototype.copyWithin === 'function') { + // Use built-in when available, missing from IE11 + this.copyWithin(targetStart, start, end) + } else if (this === target && start < targetStart && targetStart < end) { + // descending copy from end + for (var i = len - 1; i >= 0; --i) { + target[i + targetStart] = this[i + start] + } + } else { + Uint8Array.prototype.set.call( + target, + this.subarray(start, end), + targetStart + ) + } - while (entry) { - buffer[count] = entry; - if (!entry.isBuf) allBuffers = false; - entry = entry.next; - count += 1; + return len +} + +// Usage: +// buffer.fill(number[, offset[, end]]) +// buffer.fill(buffer[, offset[, end]]) +// buffer.fill(string[, offset[, end]][, encoding]) +Buffer.prototype.fill = function fill (val, start, end, encoding) { + // Handle string cases: + if (typeof val === 'string') { + if (typeof start === 'string') { + encoding = start + start = 0 + end = this.length + } else if (typeof end === 'string') { + encoding = end + end = this.length + } + if (encoding !== undefined && typeof encoding !== 'string') { + throw new TypeError('encoding must be a string') + } + if (typeof encoding === 'string' && !Buffer.isEncoding(encoding)) { + throw new TypeError('Unknown encoding: ' + encoding) + } + if (val.length === 1) { + var code = val.charCodeAt(0) + if ((encoding === 'utf8' && code < 128) || + encoding === 'latin1') { + // Fast path: If `val` fits into a single byte, use that numeric value. + val = code + } } + } else if (typeof val === 'number') { + val = val & 255 + } - buffer.allBuffers = allBuffers; - doWrite(stream, state, true, state.length, buffer, '', holder.finish); // doWrite is almost always async, defer these to save a bit of time - // as the hot path ends with doWrite + // Invalid ranges are not set to a default, so can range check early. + if (start < 0 || this.length < start || this.length < end) { + throw new RangeError('Out of range index') + } - state.pendingcb++; - state.lastBufferedRequest = null; + if (end <= start) { + return this + } - if (holder.next) { - state.corkedRequestsFree = holder.next; - holder.next = null; - } else { - state.corkedRequestsFree = new CorkedRequest(state); - } + start = start >>> 0 + end = end === undefined ? this.length : end >>> 0 - state.bufferedRequestCount = 0; - } else { - // Slow case, write chunks one-by-one - while (entry) { - var chunk = entry.chunk; - var encoding = entry.encoding; - var cb = entry.callback; - var len = state.objectMode ? 1 : chunk.length; - doWrite(stream, state, false, len, chunk, encoding, cb); - entry = entry.next; - state.bufferedRequestCount--; // if we didn't call the onwrite immediately, then - // it means that we need to wait until it does. - // also, that means that the chunk and cb are currently - // being processed, so move the buffer counter past them. + if (!val) val = 0 - if (state.writing) { - break; - } + var i + if (typeof val === 'number') { + for (i = start; i < end; ++i) { + this[i] = val + } + } else { + var bytes = Buffer.isBuffer(val) + ? val + : Buffer.from(val, encoding) + var len = bytes.length + if (len === 0) { + throw new TypeError('The value "' + val + + '" is invalid for argument "value"') + } + for (i = 0; i < end - start; ++i) { + this[i + start] = bytes[i % len] } - - if (entry === null) state.lastBufferedRequest = null; } - state.bufferedRequest = entry; - state.bufferProcessing = false; + return this } -Writable.prototype._write = function (chunk, encoding, cb) { - cb(new ERR_METHOD_NOT_IMPLEMENTED('_write()')); -}; - -Writable.prototype._writev = null; +// HELPER FUNCTIONS +// ================ -Writable.prototype.end = function (chunk, encoding, cb) { - var state = this._writableState; +var INVALID_BASE64_RE = /[^+/0-9A-Za-z-_]/g - if (typeof chunk === 'function') { - cb = chunk; - chunk = null; - encoding = null; - } else if (typeof encoding === 'function') { - cb = encoding; - encoding = null; +function base64clean (str) { + // Node takes equal signs as end of the Base64 encoding + str = str.split('=')[0] + // Node strips out invalid characters like \n and \t from the string, base64-js does not + str = str.trim().replace(INVALID_BASE64_RE, '') + // Node converts strings with length < 2 to '' + if (str.length < 2) return '' + // Node allows for non-padded base64 strings (missing trailing ===), base64-js does not + while (str.length % 4 !== 0) { + str = str + '=' } + return str +} - if (chunk !== null && chunk !== undefined) this.write(chunk, encoding); // .end() fully uncorks +function toHex (n) { + if (n < 16) return '0' + n.toString(16) + return n.toString(16) +} - if (state.corked) { - state.corked = 1; - this.uncork(); - } // ignore unnecessary end() calls. +function utf8ToBytes (string, units) { + units = units || Infinity + var codePoint + var length = string.length + var leadSurrogate = null + var bytes = [] + for (var i = 0; i < length; ++i) { + codePoint = string.charCodeAt(i) - if (!state.ending) endWritable(this, state, cb); - return this; -}; + // is surrogate component + if (codePoint > 0xD7FF && codePoint < 0xE000) { + // last char was a lead + if (!leadSurrogate) { + // no lead yet + if (codePoint > 0xDBFF) { + // unexpected trail + if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) + continue + } else if (i + 1 === length) { + // unpaired lead + if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) + continue + } -Object.defineProperty(Writable.prototype, 'writableLength', { - // making it explicit this property is not enumerable - // because otherwise some prototype manipulation in - // userland will fail - enumerable: false, - get: function get() { - return this._writableState.length; - } -}); + // valid lead + leadSurrogate = codePoint -function needFinish(state) { - return state.ending && state.length === 0 && state.bufferedRequest === null && !state.finished && !state.writing; -} + continue + } -function callFinal(stream, state) { - stream._final(function (err) { - state.pendingcb--; + // 2 leads in a row + if (codePoint < 0xDC00) { + if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) + leadSurrogate = codePoint + continue + } - if (err) { - errorOrDestroy(stream, err); + // valid surrogate pair + codePoint = (leadSurrogate - 0xD800 << 10 | codePoint - 0xDC00) + 0x10000 + } else if (leadSurrogate) { + // valid bmp char, but last char was a lead + if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) } - state.prefinished = true; - stream.emit('prefinish'); - finishMaybe(stream, state); - }); -} + leadSurrogate = null -function prefinish(stream, state) { - if (!state.prefinished && !state.finalCalled) { - if (typeof stream._final === 'function' && !state.destroyed) { - state.pendingcb++; - state.finalCalled = true; - process.nextTick(callFinal, stream, state); + // encode utf8 + if (codePoint < 0x80) { + if ((units -= 1) < 0) break + bytes.push(codePoint) + } else if (codePoint < 0x800) { + if ((units -= 2) < 0) break + bytes.push( + codePoint >> 0x6 | 0xC0, + codePoint & 0x3F | 0x80 + ) + } else if (codePoint < 0x10000) { + if ((units -= 3) < 0) break + bytes.push( + codePoint >> 0xC | 0xE0, + codePoint >> 0x6 & 0x3F | 0x80, + codePoint & 0x3F | 0x80 + ) + } else if (codePoint < 0x110000) { + if ((units -= 4) < 0) break + bytes.push( + codePoint >> 0x12 | 0xF0, + codePoint >> 0xC & 0x3F | 0x80, + codePoint >> 0x6 & 0x3F | 0x80, + codePoint & 0x3F | 0x80 + ) } else { - state.prefinished = true; - stream.emit('prefinish'); + throw new Error('Invalid code point') } } + + return bytes } -function finishMaybe(stream, state) { - var need = needFinish(state); +function asciiToBytes (str) { + var byteArray = [] + for (var i = 0; i < str.length; ++i) { + // Node's code seems to be doing this and not & 0x7F.. + byteArray.push(str.charCodeAt(i) & 0xFF) + } + return byteArray +} - if (need) { - prefinish(stream, state); +function utf16leToBytes (str, units) { + var c, hi, lo + var byteArray = [] + for (var i = 0; i < str.length; ++i) { + if ((units -= 2) < 0) break - if (state.pendingcb === 0) { - state.finished = true; - stream.emit('finish'); + c = str.charCodeAt(i) + hi = c >> 8 + lo = c % 256 + byteArray.push(lo) + byteArray.push(hi) + } - if (state.autoDestroy) { - // In case of duplex streams we need a way to detect - // if the readable side is ready for autoDestroy as well - var rState = stream._readableState; + return byteArray +} - if (!rState || rState.autoDestroy && rState.endEmitted) { - stream.destroy(); - } - } - } +function base64ToBytes (str) { + return base64.toByteArray(base64clean(str)) +} + +function blitBuffer (src, dst, offset, length) { + for (var i = 0; i < length; ++i) { + if ((i + offset >= dst.length) || (i >= src.length)) break + dst[i + offset] = src[i] } + return i +} - return need; +// ArrayBuffer or Uint8Array objects from other contexts (i.e. iframes) do not pass +// the `instanceof` check but they should be treated as of that type. +// See: https://github.com/feross/buffer/issues/166 +function isInstance (obj, type) { + return obj instanceof type || + (obj != null && obj.constructor != null && obj.constructor.name != null && + obj.constructor.name === type.name) +} +function numberIsNaN (obj) { + // For IE11 support + return obj !== obj // eslint-disable-line no-self-compare } -function endWritable(stream, state, cb) { - state.ending = true; - finishMaybe(stream, state); +}).call(this)}).call(this,require("buffer").Buffer) +},{"base64-js":85,"buffer":118,"ieee754":199}],119:[function(require,module,exports){ +(function (Buffer){(function (){ +module.exports = function xor (a, b) { + var length = Math.min(a.length, b.length) + var buffer = new Buffer(length) - if (cb) { - if (state.finished) process.nextTick(cb);else stream.once('finish', cb); + for (var i = 0; i < length; ++i) { + buffer[i] = a[i] ^ b[i] } - state.ended = true; - stream.writable = false; + return buffer } -function onCorkedFinish(corkReq, state, err) { - var entry = corkReq.entry; - corkReq.entry = null; +}).call(this)}).call(this,require("buffer").Buffer) +},{"buffer":118}],120:[function(require,module,exports){ +'use strict'; - while (entry) { - var cb = entry.callback; - state.pendingcb--; - cb(err); - entry = entry.next; - } // reuse the free corkReq. +var GetIntrinsic = require('get-intrinsic'); +var callBind = require('./'); - state.corkedRequestsFree.next = corkReq; -} +var $indexOf = callBind(GetIntrinsic('String.prototype.indexOf')); -Object.defineProperty(Writable.prototype, 'destroyed', { - // making it explicit this property is not enumerable - // because otherwise some prototype manipulation in - // userland will fail - enumerable: false, - get: function get() { - if (this._writableState === undefined) { - return false; - } +module.exports = function callBoundIntrinsic(name, allowMissing) { + var intrinsic = GetIntrinsic(name, !!allowMissing); + if (typeof intrinsic === 'function' && $indexOf(name, '.prototype.') > -1) { + return callBind(intrinsic); + } + return intrinsic; +}; - return this._writableState.destroyed; - }, - set: function set(value) { - // we ignore the value if the stream - // has not been initialized yet - if (!this._writableState) { - return; - } // backward compatibility, the user is explicitly - // managing destroyed +},{"./":121,"get-intrinsic":178}],121:[function(require,module,exports){ +'use strict'; +var bind = require('function-bind'); +var GetIntrinsic = require('get-intrinsic'); +var setFunctionLength = require('set-function-length'); - this._writableState.destroyed = value; - } -}); -Writable.prototype.destroy = destroyImpl.destroy; -Writable.prototype._undestroy = destroyImpl.undestroy; +var $TypeError = require('es-errors/type'); +var $apply = GetIntrinsic('%Function.prototype.apply%'); +var $call = GetIntrinsic('%Function.prototype.call%'); +var $reflectApply = GetIntrinsic('%Reflect.apply%', true) || bind.call($call, $apply); -Writable.prototype._destroy = function (err, cb) { - cb(err); +var $defineProperty = require('es-define-property'); +var $max = GetIntrinsic('%Math.max%'); + +module.exports = function callBind(originalFunction) { + if (typeof originalFunction !== 'function') { + throw new $TypeError('a function is required'); + } + var func = $reflectApply(bind, $call, arguments); + return setFunctionLength( + func, + 1 + $max(0, originalFunction.length - (arguments.length - 1)), + true + ); }; -}).call(this)}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"../errors":121,"./_stream_duplex":122,"./internal/streams/destroy":129,"./internal/streams/state":133,"./internal/streams/stream":134,"_process":391,"buffer":137,"inherits":256,"util-deprecate":416}],127:[function(require,module,exports){ -(function (process){(function (){ -'use strict'; -var _Object$setPrototypeO; +var applyBind = function applyBind() { + return $reflectApply(bind, $apply, arguments); +}; -function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } +if ($defineProperty) { + $defineProperty(module.exports, 'apply', { value: applyBind }); +} else { + module.exports.apply = applyBind; +} -var finished = require('./end-of-stream'); +},{"es-define-property":164,"es-errors/type":170,"function-bind":177,"get-intrinsic":178,"set-function-length":391}],122:[function(require,module,exports){ +'use strict' -var kLastResolve = Symbol('lastResolve'); -var kLastReject = Symbol('lastReject'); -var kError = Symbol('error'); -var kEnded = Symbol('ended'); -var kLastPromise = Symbol('lastPromise'); -var kHandlePromise = Symbol('handlePromise'); -var kStream = Symbol('stream'); +var nextTick = require('./next-tick') -function createIterResult(value, done) { - return { - value: value, - done: done - }; +exports.fromCallback = function (callback, symbol) { + if (callback === undefined) { + var promise = new Promise(function (resolve, reject) { + callback = function (err, res) { + if (err) reject(err) + else resolve(res) + } + }) + + callback[symbol !== undefined ? symbol : 'promise'] = promise + } else if (typeof callback !== 'function') { + throw new TypeError('Callback must be a function') + } + + return callback } -function readAndResolve(iter) { - var resolve = iter[kLastResolve]; +exports.fromPromise = function (promise, callback) { + if (callback === undefined) return promise - if (resolve !== null) { - var data = iter[kStream].read(); // we defer if data is null - // we can be expecting either 'end' or - // 'error' + promise + .then(function (res) { nextTick(() => callback(null, res)) }) + .catch(function (err) { nextTick(() => callback(err)) }) +} - if (data !== null) { - iter[kLastPromise] = null; - iter[kLastResolve] = null; - iter[kLastReject] = null; - resolve(createIterResult(data, false)); - } +},{"./next-tick":123}],123:[function(require,module,exports){ +module.exports = typeof queueMicrotask === 'function' ? queueMicrotask : (fn) => Promise.resolve().then(fn) + +},{}],124:[function(require,module,exports){ +var Buffer = require('safe-buffer').Buffer +var Transform = require('stream').Transform +var StringDecoder = require('string_decoder').StringDecoder +var inherits = require('inherits') + +function CipherBase (hashMode) { + Transform.call(this) + this.hashMode = typeof hashMode === 'string' + if (this.hashMode) { + this[hashMode] = this._finalOrDigest + } else { + this.final = this._finalOrDigest } + if (this._final) { + this.__final = this._final + this._final = null + } + this._decoder = null + this._encoding = null } +inherits(CipherBase, Transform) -function onReadable(iter) { - // we wait for the next tick, because it might - // emit an error with process.nextTick - process.nextTick(readAndResolve, iter); -} +CipherBase.prototype.update = function (data, inputEnc, outputEnc) { + if (typeof data === 'string') { + data = Buffer.from(data, inputEnc) + } -function wrapForNext(lastPromise, iter) { - return function (resolve, reject) { - lastPromise.then(function () { - if (iter[kEnded]) { - resolve(createIterResult(undefined, true)); - return; - } + var outData = this._update(data) + if (this.hashMode) return this - iter[kHandlePromise](resolve, reject); - }, reject); - }; + if (outputEnc) { + outData = this._toString(outData, outputEnc) + } + + return outData } -var AsyncIteratorPrototype = Object.getPrototypeOf(function () {}); -var ReadableStreamAsyncIteratorPrototype = Object.setPrototypeOf((_Object$setPrototypeO = { - get stream() { - return this[kStream]; - }, +CipherBase.prototype.setAutoPadding = function () {} +CipherBase.prototype.getAuthTag = function () { + throw new Error('trying to get auth tag in unsupported state') +} - next: function next() { - var _this = this; +CipherBase.prototype.setAuthTag = function () { + throw new Error('trying to set auth tag in unsupported state') +} - // if we have detected an error in the meanwhile - // reject straight away - var error = this[kError]; +CipherBase.prototype.setAAD = function () { + throw new Error('trying to set aad in unsupported state') +} - if (error !== null) { - return Promise.reject(error); +CipherBase.prototype._transform = function (data, _, next) { + var err + try { + if (this.hashMode) { + this._update(data) + } else { + this.push(this._update(data)) } + } catch (e) { + err = e + } finally { + next(err) + } +} +CipherBase.prototype._flush = function (done) { + var err + try { + this.push(this.__final()) + } catch (e) { + err = e + } - if (this[kEnded]) { - return Promise.resolve(createIterResult(undefined, true)); - } + done(err) +} +CipherBase.prototype._finalOrDigest = function (outputEnc) { + var outData = this.__final() || Buffer.alloc(0) + if (outputEnc) { + outData = this._toString(outData, outputEnc, true) + } + return outData +} - if (this[kStream].destroyed) { - // We need to defer via nextTick because if .destroy(err) is - // called, the error will be emitted via nextTick, and - // we cannot guarantee that there is no error lingering around - // waiting to be emitted. - return new Promise(function (resolve, reject) { - process.nextTick(function () { - if (_this[kError]) { - reject(_this[kError]); - } else { - resolve(createIterResult(undefined, true)); - } - }); - }); - } // if we have multiple next() calls - // we will wait for the previous Promise to finish - // this logic is optimized to support for await loops, - // where next() is only called once at a time +CipherBase.prototype._toString = function (value, enc, fin) { + if (!this._decoder) { + this._decoder = new StringDecoder(enc) + this._encoding = enc + } + if (this._encoding !== enc) throw new Error('can\'t switch encodings') - var lastPromise = this[kLastPromise]; - var promise; + var out = this._decoder.write(value) + if (fin) { + out += this._decoder.end() + } - if (lastPromise) { - promise = new Promise(wrapForNext(lastPromise, this)); - } else { - // fast path needed to support multiple this.push() - // without triggering the next() queue - var data = this[kStream].read(); + return out +} - if (data !== null) { - return Promise.resolve(createIterResult(data, false)); - } +module.exports = CipherBase - promise = new Promise(this[kHandlePromise]); - } +},{"inherits":200,"safe-buffer":390,"stream":400,"string_decoder":415}],125:[function(require,module,exports){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. - this[kLastPromise] = promise; - return promise; - } -}, _defineProperty(_Object$setPrototypeO, Symbol.asyncIterator, function () { - return this; -}), _defineProperty(_Object$setPrototypeO, "return", function _return() { - var _this2 = this; +// NOTE: These type checking functions intentionally don't use `instanceof` +// because it is fragile and can be easily faked with `Object.create()`. - // destroy(err, cb) is a private API - // we can guarantee we have that here, because we control the - // Readable class this is attached to - return new Promise(function (resolve, reject) { - _this2[kStream].destroy(null, function (err) { - if (err) { - reject(err); - return; - } +function isArray(arg) { + if (Array.isArray) { + return Array.isArray(arg); + } + return objectToString(arg) === '[object Array]'; +} +exports.isArray = isArray; - resolve(createIterResult(undefined, true)); - }); - }); -}), _Object$setPrototypeO), AsyncIteratorPrototype); +function isBoolean(arg) { + return typeof arg === 'boolean'; +} +exports.isBoolean = isBoolean; -var createReadableStreamAsyncIterator = function createReadableStreamAsyncIterator(stream) { - var _Object$create; +function isNull(arg) { + return arg === null; +} +exports.isNull = isNull; - var iterator = Object.create(ReadableStreamAsyncIteratorPrototype, (_Object$create = {}, _defineProperty(_Object$create, kStream, { - value: stream, - writable: true - }), _defineProperty(_Object$create, kLastResolve, { - value: null, - writable: true - }), _defineProperty(_Object$create, kLastReject, { - value: null, - writable: true - }), _defineProperty(_Object$create, kError, { - value: null, - writable: true - }), _defineProperty(_Object$create, kEnded, { - value: stream._readableState.endEmitted, - writable: true - }), _defineProperty(_Object$create, kHandlePromise, { - value: function value(resolve, reject) { - var data = iterator[kStream].read(); +function isNullOrUndefined(arg) { + return arg == null; +} +exports.isNullOrUndefined = isNullOrUndefined; - if (data) { - iterator[kLastPromise] = null; - iterator[kLastResolve] = null; - iterator[kLastReject] = null; - resolve(createIterResult(data, false)); - } else { - iterator[kLastResolve] = resolve; - iterator[kLastReject] = reject; - } - }, - writable: true - }), _Object$create)); - iterator[kLastPromise] = null; - finished(stream, function (err) { - if (err && err.code !== 'ERR_STREAM_PREMATURE_CLOSE') { - var reject = iterator[kLastReject]; // reject if we are waiting for data in the Promise - // returned by next() and store the error +function isNumber(arg) { + return typeof arg === 'number'; +} +exports.isNumber = isNumber; - if (reject !== null) { - iterator[kLastPromise] = null; - iterator[kLastResolve] = null; - iterator[kLastReject] = null; - reject(err); - } +function isString(arg) { + return typeof arg === 'string'; +} +exports.isString = isString; - iterator[kError] = err; - return; - } +function isSymbol(arg) { + return typeof arg === 'symbol'; +} +exports.isSymbol = isSymbol; - var resolve = iterator[kLastResolve]; +function isUndefined(arg) { + return arg === void 0; +} +exports.isUndefined = isUndefined; - if (resolve !== null) { - iterator[kLastPromise] = null; - iterator[kLastResolve] = null; - iterator[kLastReject] = null; - resolve(createIterResult(undefined, true)); - } +function isRegExp(re) { + return objectToString(re) === '[object RegExp]'; +} +exports.isRegExp = isRegExp; - iterator[kEnded] = true; - }); - stream.on('readable', onReadable.bind(null, iterator)); - return iterator; -}; +function isObject(arg) { + return typeof arg === 'object' && arg !== null; +} +exports.isObject = isObject; -module.exports = createReadableStreamAsyncIterator; -}).call(this)}).call(this,require('_process')) -},{"./end-of-stream":130,"_process":391}],128:[function(require,module,exports){ -'use strict'; +function isDate(d) { + return objectToString(d) === '[object Date]'; +} +exports.isDate = isDate; -function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } +function isError(e) { + return (objectToString(e) === '[object Error]' || e instanceof Error); +} +exports.isError = isError; -function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } +function isFunction(arg) { + return typeof arg === 'function'; +} +exports.isFunction = isFunction; -function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } +function isPrimitive(arg) { + return arg === null || + typeof arg === 'boolean' || + typeof arg === 'number' || + typeof arg === 'string' || + typeof arg === 'symbol' || // ES6 symbol + typeof arg === 'undefined'; +} +exports.isPrimitive = isPrimitive; -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } +exports.isBuffer = require('buffer').Buffer.isBuffer; -function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } +function objectToString(o) { + return Object.prototype.toString.call(o); +} -function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } +},{"buffer":118}],126:[function(require,module,exports){ +(function (Buffer){(function (){ +var elliptic = require('elliptic') +var BN = require('bn.js') -var _require = require('buffer'), - Buffer = _require.Buffer; +module.exports = function createECDH (curve) { + return new ECDH(curve) +} -var _require2 = require('util'), - inspect = _require2.inspect; +var aliases = { + secp256k1: { + name: 'secp256k1', + byteLength: 32 + }, + secp224r1: { + name: 'p224', + byteLength: 28 + }, + prime256v1: { + name: 'p256', + byteLength: 32 + }, + prime192v1: { + name: 'p192', + byteLength: 24 + }, + ed25519: { + name: 'ed25519', + byteLength: 32 + }, + secp384r1: { + name: 'p384', + byteLength: 48 + }, + secp521r1: { + name: 'p521', + byteLength: 66 + } +} -var custom = inspect && inspect.custom || 'inspect'; +aliases.p224 = aliases.secp224r1 +aliases.p256 = aliases.secp256r1 = aliases.prime256v1 +aliases.p192 = aliases.secp192r1 = aliases.prime192v1 +aliases.p384 = aliases.secp384r1 +aliases.p521 = aliases.secp521r1 -function copyBuffer(src, target, offset) { - Buffer.prototype.copy.call(src, target, offset); +function ECDH (curve) { + this.curveType = aliases[curve] + if (!this.curveType) { + this.curveType = { + name: curve + } + } + this.curve = new elliptic.ec(this.curveType.name) // eslint-disable-line new-cap + this.keys = void 0 } -module.exports = -/*#__PURE__*/ -function () { - function BufferList() { - _classCallCheck(this, BufferList); +ECDH.prototype.generateKeys = function (enc, format) { + this.keys = this.curve.genKeyPair() + return this.getPublicKey(enc, format) +} - this.head = null; - this.tail = null; - this.length = 0; +ECDH.prototype.computeSecret = function (other, inenc, enc) { + inenc = inenc || 'utf8' + if (!Buffer.isBuffer(other)) { + other = new Buffer(other, inenc) } + var otherPub = this.curve.keyFromPublic(other).getPublic() + var out = otherPub.mul(this.keys.getPrivate()).getX() + return formatReturnValue(out, enc, this.curveType.byteLength) +} - _createClass(BufferList, [{ - key: "push", - value: function push(v) { - var entry = { - data: v, - next: null - }; - if (this.length > 0) this.tail.next = entry;else this.head = entry; - this.tail = entry; - ++this.length; +ECDH.prototype.getPublicKey = function (enc, format) { + var key = this.keys.getPublic(format === 'compressed', true) + if (format === 'hybrid') { + if (key[key.length - 1] % 2) { + key[0] = 7 + } else { + key[0] = 6 } - }, { - key: "unshift", - value: function unshift(v) { - var entry = { - data: v, - next: this.head - }; - if (this.length === 0) this.tail = entry; - this.head = entry; - ++this.length; - } - }, { - key: "shift", - value: function shift() { - if (this.length === 0) return; - var ret = this.head.data; - if (this.length === 1) this.head = this.tail = null;else this.head = this.head.next; - --this.length; - return ret; - } - }, { - key: "clear", - value: function clear() { - this.head = this.tail = null; - this.length = 0; - } - }, { - key: "join", - value: function join(s) { - if (this.length === 0) return ''; - var p = this.head; - var ret = '' + p.data; - - while (p = p.next) { - ret += s + p.data; - } - - return ret; - } - }, { - key: "concat", - value: function concat(n) { - if (this.length === 0) return Buffer.alloc(0); - var ret = Buffer.allocUnsafe(n >>> 0); - var p = this.head; - var i = 0; - - while (p) { - copyBuffer(p.data, ret, i); - i += p.data.length; - p = p.next; - } - - return ret; - } // Consumes a specified amount of bytes or characters from the buffered data. - - }, { - key: "consume", - value: function consume(n, hasStrings) { - var ret; - - if (n < this.head.data.length) { - // `slice` is the same for buffers and strings. - ret = this.head.data.slice(0, n); - this.head.data = this.head.data.slice(n); - } else if (n === this.head.data.length) { - // First chunk is a perfect match. - ret = this.shift(); - } else { - // Result spans more than one buffer. - ret = hasStrings ? this._getString(n) : this._getBuffer(n); - } - - return ret; - } - }, { - key: "first", - value: function first() { - return this.head.data; - } // Consumes a specified amount of characters from the buffered data. - - }, { - key: "_getString", - value: function _getString(n) { - var p = this.head; - var c = 1; - var ret = p.data; - n -= ret.length; + } + return formatReturnValue(key, enc) +} - while (p = p.next) { - var str = p.data; - var nb = n > str.length ? str.length : n; - if (nb === str.length) ret += str;else ret += str.slice(0, n); - n -= nb; +ECDH.prototype.getPrivateKey = function (enc) { + return formatReturnValue(this.keys.getPrivate(), enc) +} - if (n === 0) { - if (nb === str.length) { - ++c; - if (p.next) this.head = p.next;else this.head = this.tail = null; - } else { - this.head = p; - p.data = str.slice(nb); - } +ECDH.prototype.setPublicKey = function (pub, enc) { + enc = enc || 'utf8' + if (!Buffer.isBuffer(pub)) { + pub = new Buffer(pub, enc) + } + this.keys._importPublic(pub) + return this +} - break; - } +ECDH.prototype.setPrivateKey = function (priv, enc) { + enc = enc || 'utf8' + if (!Buffer.isBuffer(priv)) { + priv = new Buffer(priv, enc) + } - ++c; - } + var _priv = new BN(priv) + _priv = _priv.toString(16) + this.keys = this.curve.genKeyPair() + this.keys._importPrivate(_priv) + return this +} - this.length -= c; - return ret; - } // Consumes a specified amount of bytes from the buffered data. +function formatReturnValue (bn, enc, len) { + if (!Array.isArray(bn)) { + bn = bn.toArray() + } + var buf = new Buffer(bn) + if (len && buf.length < len) { + var zeros = new Buffer(len - buf.length) + zeros.fill(0) + buf = Buffer.concat([zeros, buf]) + } + if (!enc) { + return buf + } else { + return buf.toString(enc) + } +} - }, { - key: "_getBuffer", - value: function _getBuffer(n) { - var ret = Buffer.allocUnsafe(n); - var p = this.head; - var c = 1; - p.data.copy(ret); - n -= p.data.length; +}).call(this)}).call(this,require("buffer").Buffer) +},{"bn.js":86,"buffer":118,"elliptic":147}],127:[function(require,module,exports){ +'use strict' +var inherits = require('inherits') +var MD5 = require('md5.js') +var RIPEMD160 = require('ripemd160') +var sha = require('sha.js') +var Base = require('cipher-base') - while (p = p.next) { - var buf = p.data; - var nb = n > buf.length ? buf.length : n; - buf.copy(ret, ret.length - n, 0, nb); - n -= nb; +function Hash (hash) { + Base.call(this, 'digest') - if (n === 0) { - if (nb === buf.length) { - ++c; - if (p.next) this.head = p.next;else this.head = this.tail = null; - } else { - this.head = p; - p.data = buf.slice(nb); - } + this._hash = hash +} - break; - } +inherits(Hash, Base) - ++c; - } +Hash.prototype._update = function (data) { + this._hash.update(data) +} - this.length -= c; - return ret; - } // Make sure the linked list only shows the minimal necessary information. +Hash.prototype._final = function () { + return this._hash.digest() +} - }, { - key: custom, - value: function value(_, options) { - return inspect(this, _objectSpread({}, options, { - // Only inspect one level. - depth: 0, - // It should not recurse. - customInspect: false - })); - } - }]); +module.exports = function createHash (alg) { + alg = alg.toLowerCase() + if (alg === 'md5') return new MD5() + if (alg === 'rmd160' || alg === 'ripemd160') return new RIPEMD160() - return BufferList; -}(); -},{"buffer":137,"util":93}],129:[function(require,module,exports){ -(function (process){(function (){ -'use strict'; // undocumented cb() API, needed for core, not for public API + return new Hash(sha(alg)) +} -function destroy(err, cb) { - var _this = this; +},{"cipher-base":124,"inherits":200,"md5.js":241,"ripemd160":372,"sha.js":393}],128:[function(require,module,exports){ +var MD5 = require('md5.js') - var readableDestroyed = this._readableState && this._readableState.destroyed; - var writableDestroyed = this._writableState && this._writableState.destroyed; +module.exports = function (buffer) { + return new MD5().update(buffer).digest() +} - if (readableDestroyed || writableDestroyed) { - if (cb) { - cb(err); - } else if (err) { - if (!this._writableState) { - process.nextTick(emitErrorNT, this, err); - } else if (!this._writableState.errorEmitted) { - this._writableState.errorEmitted = true; - process.nextTick(emitErrorNT, this, err); - } - } +},{"md5.js":241}],129:[function(require,module,exports){ +'use strict' +var inherits = require('inherits') +var Legacy = require('./legacy') +var Base = require('cipher-base') +var Buffer = require('safe-buffer').Buffer +var md5 = require('create-hash/md5') +var RIPEMD160 = require('ripemd160') - return this; - } // we set destroyed to true before firing error callbacks in order - // to make it re-entrance safe in case destroy() is called within callbacks +var sha = require('sha.js') +var ZEROS = Buffer.alloc(128) - if (this._readableState) { - this._readableState.destroyed = true; - } // if this is a duplex stream mark the writable part as destroyed as well +function Hmac (alg, key) { + Base.call(this, 'digest') + if (typeof key === 'string') { + key = Buffer.from(key) + } + var blocksize = (alg === 'sha512' || alg === 'sha384') ? 128 : 64 - if (this._writableState) { - this._writableState.destroyed = true; + this._alg = alg + this._key = key + if (key.length > blocksize) { + var hash = alg === 'rmd160' ? new RIPEMD160() : sha(alg) + key = hash.update(key).digest() + } else if (key.length < blocksize) { + key = Buffer.concat([key, ZEROS], blocksize) } - this._destroy(err || null, function (err) { - if (!cb && err) { - if (!_this._writableState) { - process.nextTick(emitErrorAndCloseNT, _this, err); - } else if (!_this._writableState.errorEmitted) { - _this._writableState.errorEmitted = true; - process.nextTick(emitErrorAndCloseNT, _this, err); - } else { - process.nextTick(emitCloseNT, _this); - } - } else if (cb) { - process.nextTick(emitCloseNT, _this); - cb(err); - } else { - process.nextTick(emitCloseNT, _this); - } - }); + var ipad = this._ipad = Buffer.allocUnsafe(blocksize) + var opad = this._opad = Buffer.allocUnsafe(blocksize) - return this; + for (var i = 0; i < blocksize; i++) { + ipad[i] = key[i] ^ 0x36 + opad[i] = key[i] ^ 0x5C + } + this._hash = alg === 'rmd160' ? new RIPEMD160() : sha(alg) + this._hash.update(ipad) } -function emitErrorAndCloseNT(self, err) { - emitErrorNT(self, err); - emitCloseNT(self); +inherits(Hmac, Base) + +Hmac.prototype._update = function (data) { + this._hash.update(data) } -function emitCloseNT(self) { - if (self._writableState && !self._writableState.emitClose) return; - if (self._readableState && !self._readableState.emitClose) return; - self.emit('close'); +Hmac.prototype._final = function () { + var h = this._hash.digest() + var hash = this._alg === 'rmd160' ? new RIPEMD160() : sha(this._alg) + return hash.update(this._opad).update(h).digest() } -function undestroy() { - if (this._readableState) { - this._readableState.destroyed = false; - this._readableState.reading = false; - this._readableState.ended = false; - this._readableState.endEmitted = false; +module.exports = function createHmac (alg, key) { + alg = alg.toLowerCase() + if (alg === 'rmd160' || alg === 'ripemd160') { + return new Hmac('rmd160', key) } - - if (this._writableState) { - this._writableState.destroyed = false; - this._writableState.ended = false; - this._writableState.ending = false; - this._writableState.finalCalled = false; - this._writableState.prefinished = false; - this._writableState.finished = false; - this._writableState.errorEmitted = false; + if (alg === 'md5') { + return new Legacy(md5, key) } + return new Hmac(alg, key) } -function emitErrorNT(self, err) { - self.emit('error', err); -} +},{"./legacy":130,"cipher-base":124,"create-hash/md5":128,"inherits":200,"ripemd160":372,"safe-buffer":390,"sha.js":393}],130:[function(require,module,exports){ +'use strict' +var inherits = require('inherits') +var Buffer = require('safe-buffer').Buffer -function errorOrDestroy(stream, err) { - // We have tests that rely on errors being emitted - // in the same tick, so changing this is semver major. - // For now when you opt-in to autoDestroy we allow - // the error to be emitted nextTick. In a future - // semver major update we should change the default to this. - var rState = stream._readableState; - var wState = stream._writableState; - if (rState && rState.autoDestroy || wState && wState.autoDestroy) stream.destroy(err);else stream.emit('error', err); -} +var Base = require('cipher-base') -module.exports = { - destroy: destroy, - undestroy: undestroy, - errorOrDestroy: errorOrDestroy -}; -}).call(this)}).call(this,require('_process')) -},{"_process":391}],130:[function(require,module,exports){ -// Ported from https://github.com/mafintosh/end-of-stream with -// permission from the author, Mathias Buus (@mafintosh). -'use strict'; +var ZEROS = Buffer.alloc(128) +var blocksize = 64 -var ERR_STREAM_PREMATURE_CLOSE = require('../../../errors').codes.ERR_STREAM_PREMATURE_CLOSE; +function Hmac (alg, key) { + Base.call(this, 'digest') + if (typeof key === 'string') { + key = Buffer.from(key) + } -function once(callback) { - var called = false; - return function () { - if (called) return; - called = true; + this._alg = alg + this._key = key - for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { - args[_key] = arguments[_key]; - } + if (key.length > blocksize) { + key = alg(key) + } else if (key.length < blocksize) { + key = Buffer.concat([key, ZEROS], blocksize) + } - callback.apply(this, args); - }; + var ipad = this._ipad = Buffer.allocUnsafe(blocksize) + var opad = this._opad = Buffer.allocUnsafe(blocksize) + + for (var i = 0; i < blocksize; i++) { + ipad[i] = key[i] ^ 0x36 + opad[i] = key[i] ^ 0x5C + } + + this._hash = [ipad] } -function noop() {} +inherits(Hmac, Base) -function isRequest(stream) { - return stream.setHeader && typeof stream.abort === 'function'; +Hmac.prototype._update = function (data) { + this._hash.push(data) } -function eos(stream, opts, callback) { - if (typeof opts === 'function') return eos(stream, null, opts); - if (!opts) opts = {}; - callback = once(callback || noop); - var readable = opts.readable || opts.readable !== false && stream.readable; - var writable = opts.writable || opts.writable !== false && stream.writable; +Hmac.prototype._final = function () { + var h = this._alg(Buffer.concat(this._hash)) + return this._alg(Buffer.concat([this._opad, h])) +} +module.exports = Hmac - var onlegacyfinish = function onlegacyfinish() { - if (!stream.writable) onfinish(); - }; +},{"cipher-base":124,"inherits":200,"safe-buffer":390}],131:[function(require,module,exports){ +'use strict' - var writableEnded = stream._writableState && stream._writableState.finished; +exports.randomBytes = exports.rng = exports.pseudoRandomBytes = exports.prng = require('randombytes') +exports.createHash = exports.Hash = require('create-hash') +exports.createHmac = exports.Hmac = require('create-hmac') - var onfinish = function onfinish() { - writable = false; - writableEnded = true; - if (!readable) callback.call(stream); - }; +var algos = require('browserify-sign/algos') +var algoKeys = Object.keys(algos) +var hashes = ['sha1', 'sha224', 'sha256', 'sha384', 'sha512', 'md5', 'rmd160'].concat(algoKeys) +exports.getHashes = function () { + return hashes +} - var readableEnded = stream._readableState && stream._readableState.endEmitted; +var p = require('pbkdf2') +exports.pbkdf2 = p.pbkdf2 +exports.pbkdf2Sync = p.pbkdf2Sync - var onend = function onend() { - readable = false; - readableEnded = true; - if (!writable) callback.call(stream); - }; +var aes = require('browserify-cipher') - var onerror = function onerror(err) { - callback.call(stream, err); - }; +exports.Cipher = aes.Cipher +exports.createCipher = aes.createCipher +exports.Cipheriv = aes.Cipheriv +exports.createCipheriv = aes.createCipheriv +exports.Decipher = aes.Decipher +exports.createDecipher = aes.createDecipher +exports.Decipheriv = aes.Decipheriv +exports.createDecipheriv = aes.createDecipheriv +exports.getCiphers = aes.getCiphers +exports.listCiphers = aes.listCiphers - var onclose = function onclose() { - var err; +var dh = require('diffie-hellman') - if (readable && !readableEnded) { - if (!stream._readableState || !stream._readableState.ended) err = new ERR_STREAM_PREMATURE_CLOSE(); - return callback.call(stream, err); - } +exports.DiffieHellmanGroup = dh.DiffieHellmanGroup +exports.createDiffieHellmanGroup = dh.createDiffieHellmanGroup +exports.getDiffieHellman = dh.getDiffieHellman +exports.createDiffieHellman = dh.createDiffieHellman +exports.DiffieHellman = dh.DiffieHellman - if (writable && !writableEnded) { - if (!stream._writableState || !stream._writableState.ended) err = new ERR_STREAM_PREMATURE_CLOSE(); - return callback.call(stream, err); - } - }; +var sign = require('browserify-sign') - var onrequest = function onrequest() { - stream.req.on('finish', onfinish); - }; +exports.createSign = sign.createSign +exports.Sign = sign.Sign +exports.createVerify = sign.createVerify +exports.Verify = sign.Verify - if (isRequest(stream)) { - stream.on('complete', onfinish); - stream.on('abort', onclose); - if (stream.req) onrequest();else stream.on('request', onrequest); - } else if (writable && !stream._writableState) { - // legacy streams - stream.on('end', onlegacyfinish); - stream.on('close', onlegacyfinish); - } +exports.createECDH = require('create-ecdh') - stream.on('end', onend); - stream.on('finish', onfinish); - if (opts.error !== false) stream.on('error', onerror); - stream.on('close', onclose); - return function () { - stream.removeListener('complete', onfinish); - stream.removeListener('abort', onclose); - stream.removeListener('request', onrequest); - if (stream.req) stream.req.removeListener('finish', onfinish); - stream.removeListener('end', onlegacyfinish); - stream.removeListener('close', onlegacyfinish); - stream.removeListener('finish', onfinish); - stream.removeListener('end', onend); - stream.removeListener('error', onerror); - stream.removeListener('close', onclose); - }; -} +var publicEncrypt = require('public-encrypt') -module.exports = eos; -},{"../../../errors":121}],131:[function(require,module,exports){ -module.exports = function () { - throw new Error('Readable.from is not available in the browser') -}; +exports.publicEncrypt = publicEncrypt.publicEncrypt +exports.privateEncrypt = publicEncrypt.privateEncrypt +exports.publicDecrypt = publicEncrypt.publicDecrypt +exports.privateDecrypt = publicEncrypt.privateDecrypt -},{}],132:[function(require,module,exports){ -// Ported from https://github.com/mafintosh/pump with -// permission from the author, Mathias Buus (@mafintosh). -'use strict'; +// the least I can do is make error messages for the rest of the node.js/crypto api. +// ;[ +// 'createCredentials' +// ].forEach(function (name) { +// exports[name] = function () { +// throw new Error([ +// 'sorry, ' + name + ' is not implemented yet', +// 'we accept pull requests', +// 'https://github.com/crypto-browserify/crypto-browserify' +// ].join('\n')) +// } +// }) -var eos; +var rf = require('randomfill') -function once(callback) { - var called = false; - return function () { - if (called) return; - called = true; - callback.apply(void 0, arguments); - }; -} - -var _require$codes = require('../../../errors').codes, - ERR_MISSING_ARGS = _require$codes.ERR_MISSING_ARGS, - ERR_STREAM_DESTROYED = _require$codes.ERR_STREAM_DESTROYED; - -function noop(err) { - // Rethrow the error if it exists to avoid swallowing it - if (err) throw err; -} +exports.randomFill = rf.randomFill +exports.randomFillSync = rf.randomFillSync -function isRequest(stream) { - return stream.setHeader && typeof stream.abort === 'function'; +exports.createCredentials = function () { + throw new Error([ + 'sorry, createCredentials is not implemented yet', + 'we accept pull requests', + 'https://github.com/crypto-browserify/crypto-browserify' + ].join('\n')) } -function destroyer(stream, reading, writing, callback) { - callback = once(callback); - var closed = false; - stream.on('close', function () { - closed = true; - }); - if (eos === undefined) eos = require('./end-of-stream'); - eos(stream, { - readable: reading, - writable: writing - }, function (err) { - if (err) return callback(err); - closed = true; - callback(); - }); - var destroyed = false; - return function (err) { - if (closed) return; - if (destroyed) return; - destroyed = true; // request.destroy just do .end - .abort is what we want - - if (isRequest(stream)) return stream.abort(); - if (typeof stream.destroy === 'function') return stream.destroy(); - callback(err || new ERR_STREAM_DESTROYED('pipe')); - }; +exports.constants = { + 'DH_CHECK_P_NOT_SAFE_PRIME': 2, + 'DH_CHECK_P_NOT_PRIME': 1, + 'DH_UNABLE_TO_CHECK_GENERATOR': 4, + 'DH_NOT_SUITABLE_GENERATOR': 8, + 'NPN_ENABLED': 1, + 'ALPN_ENABLED': 1, + 'RSA_PKCS1_PADDING': 1, + 'RSA_SSLV23_PADDING': 2, + 'RSA_NO_PADDING': 3, + 'RSA_PKCS1_OAEP_PADDING': 4, + 'RSA_X931_PADDING': 5, + 'RSA_PKCS1_PSS_PADDING': 6, + 'POINT_CONVERSION_COMPRESSED': 2, + 'POINT_CONVERSION_UNCOMPRESSED': 4, + 'POINT_CONVERSION_HYBRID': 6 } -function call(fn) { - fn(); -} +},{"browserify-cipher":106,"browserify-sign":114,"browserify-sign/algos":111,"create-ecdh":126,"create-hash":127,"create-hmac":129,"diffie-hellman":143,"pbkdf2":342,"public-encrypt":351,"randombytes":358,"randomfill":359}],132:[function(require,module,exports){ +'use strict' -function pipe(from, to) { - return from.pipe(to); -} +const { AbstractChainedBatch } = require('abstract-leveldown') +const kOperations = Symbol('operations') -function popCallback(streams) { - if (!streams.length) return noop; - if (typeof streams[streams.length - 1] !== 'function') return noop; - return streams.pop(); -} +module.exports = class DeferredChainedBatch extends AbstractChainedBatch { + constructor (db) { + super(db) + this[kOperations] = [] + } -function pipeline() { - for (var _len = arguments.length, streams = new Array(_len), _key = 0; _key < _len; _key++) { - streams[_key] = arguments[_key]; + _put (key, value, options) { + this[kOperations].push({ ...options, type: 'put', key, value }) } - var callback = popCallback(streams); - if (Array.isArray(streams[0])) streams = streams[0]; + _del (key, options) { + this[kOperations].push({ ...options, type: 'del', key }) + } - if (streams.length < 2) { - throw new ERR_MISSING_ARGS('streams'); + _clear () { + this[kOperations] = [] } - var error; - var destroys = streams.map(function (stream, i) { - var reading = i < streams.length - 1; - var writing = i > 0; - return destroyer(stream, reading, writing, function (err) { - if (!error) error = err; - if (err) destroys.forEach(call); - if (reading) return; - destroys.forEach(call); - callback(error); - }); - }); - return streams.reduce(pipe); + _write (options, callback) { + // AbstractChainedBatch would call _batch(), we call batch() + this.db.batch(this[kOperations], options, callback) + } } -module.exports = pipeline; -},{"../../../errors":121,"./end-of-stream":130}],133:[function(require,module,exports){ -'use strict'; +},{"abstract-leveldown":30}],133:[function(require,module,exports){ +'use strict' -var ERR_INVALID_OPT_VALUE = require('../../../errors').codes.ERR_INVALID_OPT_VALUE; +const { AbstractIterator } = require('abstract-leveldown') +const inherits = require('inherits') +const getCallback = require('./util').getCallback -function highWaterMarkFrom(options, isDuplex, duplexKey) { - return options.highWaterMark != null ? options.highWaterMark : isDuplex ? options[duplexKey] : null; -} +const kOptions = Symbol('options') +const kIterator = Symbol('iterator') +const kOperations = Symbol('operations') +const kPromise = Symbol('promise') -function getHighWaterMark(state, options, duplexKey, isDuplex) { - var hwm = highWaterMarkFrom(options, isDuplex, duplexKey); +function DeferredIterator (db, options) { + AbstractIterator.call(this, db) - if (hwm != null) { - if (!(isFinite(hwm) && Math.floor(hwm) === hwm) || hwm < 0) { - var name = isDuplex ? duplexKey : 'highWaterMark'; - throw new ERR_INVALID_OPT_VALUE(name, hwm); - } + this[kOptions] = options + this[kIterator] = null + this[kOperations] = [] +} - return Math.floor(hwm); - } // Default value +inherits(DeferredIterator, AbstractIterator) +DeferredIterator.prototype.setDb = function (db) { + this[kIterator] = db.iterator(this[kOptions]) - return state.objectMode ? 16 : 16 * 1024; + for (const op of this[kOperations].splice(0, this[kOperations].length)) { + this[kIterator][op.method](...op.args) + } } -module.exports = { - getHighWaterMark: getHighWaterMark -}; -},{"../../../errors":121}],134:[function(require,module,exports){ -module.exports = require('events').EventEmitter; - -},{"events":211}],135:[function(require,module,exports){ -exports = module.exports = require('./lib/_stream_readable.js'); -exports.Stream = exports; -exports.Readable = exports; -exports.Writable = require('./lib/_stream_writable.js'); -exports.Duplex = require('./lib/_stream_duplex.js'); -exports.Transform = require('./lib/_stream_transform.js'); -exports.PassThrough = require('./lib/_stream_passthrough.js'); -exports.finished = require('./lib/internal/streams/end-of-stream.js'); -exports.pipeline = require('./lib/internal/streams/pipeline.js'); +DeferredIterator.prototype.next = function (...args) { + if (this.db.status === 'open') { + return this[kIterator].next(...args) + } -},{"./lib/_stream_duplex.js":122,"./lib/_stream_passthrough.js":123,"./lib/_stream_readable.js":124,"./lib/_stream_transform.js":125,"./lib/_stream_writable.js":126,"./lib/internal/streams/end-of-stream.js":130,"./lib/internal/streams/pipeline.js":132}],136:[function(require,module,exports){ -/*! safe-buffer. MIT License. Feross Aboukhadijeh */ -/* eslint-disable node/no-deprecated-api */ -var buffer = require('buffer') -var Buffer = buffer.Buffer + const callback = getCallback(args, kPromise, function map (key, value) { + if (key === undefined && value === undefined) { + return undefined + } else { + return [key, value] + } + }) -// alternative to using Object.keys for old browsers -function copyProps (src, dst) { - for (var key in src) { - dst[key] = src[key] + if (this.db.status === 'opening') { + this[kOperations].push({ method: 'next', args }) + } else { + this._nextTick(callback, new Error('Database is not open')) } -} -if (Buffer.from && Buffer.alloc && Buffer.allocUnsafe && Buffer.allocUnsafeSlow) { - module.exports = buffer -} else { - // Copy properties from require('buffer') - copyProps(buffer, exports) - exports.Buffer = SafeBuffer -} -function SafeBuffer (arg, encodingOrOffset, length) { - return Buffer(arg, encodingOrOffset, length) + return callback[kPromise] || this } -SafeBuffer.prototype = Object.create(Buffer.prototype) - -// Copy static methods from Buffer -copyProps(Buffer, SafeBuffer) - -SafeBuffer.from = function (arg, encodingOrOffset, length) { - if (typeof arg === 'number') { - throw new TypeError('Argument must not be a number') +DeferredIterator.prototype.seek = function (...args) { + if (this.db.status === 'open') { + this[kIterator].seek(...args) + } else if (this.db.status === 'opening') { + this[kOperations].push({ method: 'seek', args }) + } else { + throw new Error('Database is not open') } - return Buffer(arg, encodingOrOffset, length) } -SafeBuffer.alloc = function (size, fill, encoding) { - if (typeof size !== 'number') { - throw new TypeError('Argument must be a number') +DeferredIterator.prototype.end = function (...args) { + if (this.db.status === 'open') { + return this[kIterator].end(...args) } - var buf = Buffer(size) - if (fill !== undefined) { - if (typeof encoding === 'string') { - buf.fill(fill, encoding) - } else { - buf.fill(fill) - } + + const callback = getCallback(args, kPromise) + + if (this.db.status === 'opening') { + this[kOperations].push({ method: 'end', args }) } else { - buf.fill(0) + this._nextTick(callback, new Error('Database is not open')) } - return buf -} -SafeBuffer.allocUnsafe = function (size) { - if (typeof size !== 'number') { - throw new TypeError('Argument must be a number') - } - return Buffer(size) + return callback[kPromise] || this } -SafeBuffer.allocUnsafeSlow = function (size) { - if (typeof size !== 'number') { - throw new TypeError('Argument must be a number') +for (const method of ['next', 'seek', 'end']) { + DeferredIterator.prototype['_' + method] = function () { + /* istanbul ignore next: assertion */ + throw new Error('Did not expect private method to be called: ' + method) } - return buffer.SlowBuffer(size) } -},{"buffer":137}],137:[function(require,module,exports){ -(function (Buffer){(function (){ -/*! - * The buffer module from node.js, for the browser. - * - * @author Feross Aboukhadijeh - * @license MIT - */ -/* eslint-disable no-proto */ +module.exports = DeferredIterator +},{"./util":135,"abstract-leveldown":30,"inherits":200}],134:[function(require,module,exports){ 'use strict' -var base64 = require('base64-js') -var ieee754 = require('ieee754') - -exports.Buffer = Buffer -exports.SlowBuffer = SlowBuffer -exports.INSPECT_MAX_BYTES = 50 +const { AbstractLevelDOWN } = require('abstract-leveldown') +const inherits = require('inherits') +const DeferredIterator = require('./deferred-iterator') +const DeferredChainedBatch = require('./deferred-chained-batch') +const getCallback = require('./util').getCallback -var K_MAX_LENGTH = 0x7fffffff -exports.kMaxLength = K_MAX_LENGTH +const deferrables = ['put', 'get', 'getMany', 'del', 'batch', 'clear'] +const optionalDeferrables = ['approximateSize', 'compactRange'] -/** - * If `Buffer.TYPED_ARRAY_SUPPORT`: - * === true Use Uint8Array implementation (fastest) - * === false Print warning and recommend using `buffer` v4.x which has an Object - * implementation (most compatible, even IE6) - * - * Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+, - * Opera 11.6+, iOS 4.2+. - * - * We report that the browser does not support typed arrays if the are not subclassable - * using __proto__. Firefox 4-29 lacks support for adding new properties to `Uint8Array` - * (See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438). IE 10 lacks support - * for __proto__ and has a buggy typed array implementation. - */ -Buffer.TYPED_ARRAY_SUPPORT = typedArraySupport() +const kInnerDb = Symbol('innerDb') +const kOperations = Symbol('operations') +const kPromise = Symbol('promise') -if (!Buffer.TYPED_ARRAY_SUPPORT && typeof console !== 'undefined' && - typeof console.error === 'function') { - console.error( - 'This browser lacks typed array (Uint8Array) support which is required by ' + - '`buffer` v5.x. Use `buffer` v4.x if you require old browser support.' - ) -} +function DeferredLevelDOWN (db) { + AbstractLevelDOWN.call(this, db.supports || {}) -function typedArraySupport () { - // Can typed array instances can be augmented? - try { - var arr = new Uint8Array(1) - arr.__proto__ = { __proto__: Uint8Array.prototype, foo: function () { return 42 } } - return arr.foo() === 42 - } catch (e) { - return false + // TODO (future major): remove this fallback; db must have manifest that + // declares approximateSize and compactRange in additionalMethods. + for (const m of optionalDeferrables) { + if (typeof db[m] === 'function' && !this.supports.additionalMethods[m]) { + this.supports.additionalMethods[m] = true + } } + + this[kInnerDb] = db + this[kOperations] = [] + + implement(this) } -Object.defineProperty(Buffer.prototype, 'parent', { - enumerable: true, - get: function () { - if (!Buffer.isBuffer(this)) return undefined - return this.buffer - } -}) +inherits(DeferredLevelDOWN, AbstractLevelDOWN) -Object.defineProperty(Buffer.prototype, 'offset', { +DeferredLevelDOWN.prototype.type = 'deferred-leveldown' + +// Backwards compatibility for reachdown and subleveldown +Object.defineProperty(DeferredLevelDOWN.prototype, '_db', { enumerable: true, - get: function () { - if (!Buffer.isBuffer(this)) return undefined - return this.byteOffset + get () { + return this[kInnerDb] } }) -function createBuffer (length) { - if (length > K_MAX_LENGTH) { - throw new RangeError('The value "' + length + '" is invalid for option "size"') - } - // Return an augmented `Uint8Array` instance - var buf = new Uint8Array(length) - buf.__proto__ = Buffer.prototype - return buf -} +DeferredLevelDOWN.prototype._open = function (options, callback) { + const onopen = (err) => { + if (err || this[kInnerDb].status !== 'open') { + // TODO: reject scheduled operations + return callback(err || new Error('Database is not open')) + } -/** - * The Buffer constructor returns instances of `Uint8Array` that have their - * prototype changed to `Buffer.prototype`. Furthermore, `Buffer` is a subclass of - * `Uint8Array`, so the returned instances will have all the node `Buffer` methods - * and the `Uint8Array` methods. Square bracket notation works as expected -- it - * returns a single octet. - * - * The `Uint8Array` prototype remains unmodified. - */ + const operations = this[kOperations] + this[kOperations] = [] -function Buffer (arg, encodingOrOffset, length) { - // Common case. - if (typeof arg === 'number') { - if (typeof encodingOrOffset === 'string') { - throw new TypeError( - 'The "string" argument must be of type string. Received type number' - ) + for (const op of operations) { + if (op.iterator) { + op.iterator.setDb(this[kInnerDb]) + } else { + this[kInnerDb][op.method](...op.args) + } } - return allocUnsafe(arg) + + /* istanbul ignore if: assertion */ + if (this[kOperations].length > 0) { + throw new Error('Did not expect further operations') + } + + callback() + } + + if (this[kInnerDb].status === 'new' || this[kInnerDb].status === 'closed') { + this[kInnerDb].open(options, onopen) + } else { + this._nextTick(onopen) } - return from(arg, encodingOrOffset, length) } -// Fix subarray() in ES2016. See: https://github.com/feross/buffer/pull/97 -if (typeof Symbol !== 'undefined' && Symbol.species != null && - Buffer[Symbol.species] === Buffer) { - Object.defineProperty(Buffer, Symbol.species, { - value: null, - configurable: true, - enumerable: false, - writable: false - }) +DeferredLevelDOWN.prototype._close = function (callback) { + this[kInnerDb].close(callback) } -Buffer.poolSize = 8192 // not used by this implementation +DeferredLevelDOWN.prototype._isOperational = function () { + return this.status === 'opening' +} -function from (value, encodingOrOffset, length) { - if (typeof value === 'string') { - return fromString(value, encodingOrOffset) - } +function implement (self) { + const additionalMethods = Object.keys(self.supports.additionalMethods) - if (ArrayBuffer.isView(value)) { - return fromArrayLike(value) - } + for (const method of deferrables.concat(additionalMethods)) { + // Override the public rather than private methods to cover cases where abstract-leveldown + // has a fast-path like on db.batch([]) which bypasses _batch() because the array is empty. + self[method] = function (...args) { + if (method === 'batch' && args.length === 0) { + return new DeferredChainedBatch(this) + } else if (this.status === 'open') { + return this[kInnerDb][method](...args) + } - if (value == null) { - throw TypeError( - 'The first argument must be one of type string, Buffer, ArrayBuffer, Array, ' + - 'or Array-like Object. Received type ' + (typeof value) - ) - } + const callback = getCallback(args, kPromise) - if (isInstance(value, ArrayBuffer) || - (value && isInstance(value.buffer, ArrayBuffer))) { - return fromArrayBuffer(value, encodingOrOffset, length) - } + if (this.status === 'opening') { + this[kOperations].push({ method, args }) + } else { + this._nextTick(callback, new Error('Database is not open')) + } - if (typeof value === 'number') { - throw new TypeError( - 'The "value" argument must not be of type number. Received type number' - ) + return callback[kPromise] + } } - var valueOf = value.valueOf && value.valueOf() - if (valueOf != null && valueOf !== value) { - return Buffer.from(valueOf, encodingOrOffset, length) + self.iterator = function (options) { + if (this.status === 'open') { + return this[kInnerDb].iterator(options) + } else if (this.status === 'opening') { + const iterator = new DeferredIterator(this, options) + this[kOperations].push({ iterator }) + return iterator + } else { + throw new Error('Database is not open') + } } - var b = fromObject(value) - if (b) return b - - if (typeof Symbol !== 'undefined' && Symbol.toPrimitive != null && - typeof value[Symbol.toPrimitive] === 'function') { - return Buffer.from( - value[Symbol.toPrimitive]('string'), encodingOrOffset, length - ) + for (const method of deferrables.concat(['iterator'])) { + self['_' + method] = function () { + /* istanbul ignore next: assertion */ + throw new Error('Did not expect private method to be called: ' + method) + } } - - throw new TypeError( - 'The first argument must be one of type string, Buffer, ArrayBuffer, Array, ' + - 'or Array-like Object. Received type ' + (typeof value) - ) } -/** - * Functionally equivalent to Buffer(arg, encoding) but throws a TypeError - * if value is a number. - * Buffer.from(str[, encoding]) - * Buffer.from(array) - * Buffer.from(buffer) - * Buffer.from(arrayBuffer[, byteOffset[, length]]) - **/ -Buffer.from = function (value, encodingOrOffset, length) { - return from(value, encodingOrOffset, length) -} +module.exports = DeferredLevelDOWN +module.exports.DeferredIterator = DeferredIterator -// Note: Change prototype *after* Buffer.from is defined to workaround Chrome bug: -// https://github.com/feross/buffer/pull/148 -Buffer.prototype.__proto__ = Uint8Array.prototype -Buffer.__proto__ = Uint8Array +},{"./deferred-chained-batch":132,"./deferred-iterator":133,"./util":135,"abstract-leveldown":30,"inherits":200}],135:[function(require,module,exports){ +'use strict' -function assertSize (size) { - if (typeof size !== 'number') { - throw new TypeError('"size" argument must be of type number') - } else if (size < 0) { - throw new RangeError('The value "' + size + '" is invalid for option "size"') +exports.getCallback = function (args, symbol, map) { + let callback = args[args.length - 1] + + if (typeof callback !== 'function') { + const promise = new Promise((resolve, reject) => { + args.push(callback = function (err, ...results) { + if (err) reject(err) + else resolve(map ? map(...results) : results[0]) + }) + }) + + callback[symbol] = promise } + + return callback } -function alloc (size, fill, encoding) { - assertSize(size) - if (size <= 0) { - return createBuffer(size) - } - if (fill !== undefined) { - // Only pay attention to encoding if it's a string. This - // prevents accidentally sending in a number that would - // be interpretted as a start offset. - return typeof encoding === 'string' - ? createBuffer(size).fill(fill, encoding) - : createBuffer(size).fill(fill) - } - return createBuffer(size) -} +},{}],136:[function(require,module,exports){ +'use strict'; -/** - * Creates a new filled Buffer instance. - * alloc(size[, fill[, encoding]]) - **/ -Buffer.alloc = function (size, fill, encoding) { - return alloc(size, fill, encoding) -} +var $defineProperty = require('es-define-property'); -function allocUnsafe (size) { - assertSize(size) - return createBuffer(size < 0 ? 0 : checked(size) | 0) -} +var $SyntaxError = require('es-errors/syntax'); +var $TypeError = require('es-errors/type'); -/** - * Equivalent to Buffer(num), by default creates a non-zero-filled Buffer instance. - * */ -Buffer.allocUnsafe = function (size) { - return allocUnsafe(size) -} -/** - * Equivalent to SlowBuffer(num), by default creates a non-zero-filled Buffer instance. - */ -Buffer.allocUnsafeSlow = function (size) { - return allocUnsafe(size) -} +var gopd = require('gopd'); -function fromString (string, encoding) { - if (typeof encoding !== 'string' || encoding === '') { - encoding = 'utf8' - } +/** @type {import('.')} */ +module.exports = function defineDataProperty( + obj, + property, + value +) { + if (!obj || (typeof obj !== 'object' && typeof obj !== 'function')) { + throw new $TypeError('`obj` must be an object or a function`'); + } + if (typeof property !== 'string' && typeof property !== 'symbol') { + throw new $TypeError('`property` must be a string or a symbol`'); + } + if (arguments.length > 3 && typeof arguments[3] !== 'boolean' && arguments[3] !== null) { + throw new $TypeError('`nonEnumerable`, if provided, must be a boolean or null'); + } + if (arguments.length > 4 && typeof arguments[4] !== 'boolean' && arguments[4] !== null) { + throw new $TypeError('`nonWritable`, if provided, must be a boolean or null'); + } + if (arguments.length > 5 && typeof arguments[5] !== 'boolean' && arguments[5] !== null) { + throw new $TypeError('`nonConfigurable`, if provided, must be a boolean or null'); + } + if (arguments.length > 6 && typeof arguments[6] !== 'boolean') { + throw new $TypeError('`loose`, if provided, must be a boolean'); + } - if (!Buffer.isEncoding(encoding)) { - throw new TypeError('Unknown encoding: ' + encoding) - } + var nonEnumerable = arguments.length > 3 ? arguments[3] : null; + var nonWritable = arguments.length > 4 ? arguments[4] : null; + var nonConfigurable = arguments.length > 5 ? arguments[5] : null; + var loose = arguments.length > 6 ? arguments[6] : false; - var length = byteLength(string, encoding) | 0 - var buf = createBuffer(length) + /* @type {false | TypedPropertyDescriptor} */ + var desc = !!gopd && gopd(obj, property); - var actual = buf.write(string, encoding) + if ($defineProperty) { + $defineProperty(obj, property, { + configurable: nonConfigurable === null && desc ? desc.configurable : !nonConfigurable, + enumerable: nonEnumerable === null && desc ? desc.enumerable : !nonEnumerable, + value: value, + writable: nonWritable === null && desc ? desc.writable : !nonWritable + }); + } else if (loose || (!nonEnumerable && !nonWritable && !nonConfigurable)) { + // must fall back to [[Set]], and was not explicitly asked to make non-enumerable, non-writable, or non-configurable + obj[property] = value; // eslint-disable-line no-param-reassign + } else { + throw new $SyntaxError('This environment does not support defining a property as non-configurable, non-writable, or non-enumerable.'); + } +}; - if (actual !== length) { - // Writing a hex string, for example, that contains invalid characters will - // cause everything after the first invalid character to be ignored. (e.g. - // 'abxxcd' will be treated as 'ab') - buf = buf.slice(0, actual) - } +},{"es-define-property":164,"es-errors/syntax":169,"es-errors/type":170,"gopd":179}],137:[function(require,module,exports){ +'use strict'; - return buf -} +exports.utils = require('./des/utils'); +exports.Cipher = require('./des/cipher'); +exports.DES = require('./des/des'); +exports.CBC = require('./des/cbc'); +exports.EDE = require('./des/ede'); -function fromArrayLike (array) { - var length = array.length < 0 ? 0 : checked(array.length) | 0 - var buf = createBuffer(length) - for (var i = 0; i < length; i += 1) { - buf[i] = array[i] & 255 - } - return buf +},{"./des/cbc":138,"./des/cipher":139,"./des/des":140,"./des/ede":141,"./des/utils":142}],138:[function(require,module,exports){ +'use strict'; + +var assert = require('minimalistic-assert'); +var inherits = require('inherits'); + +var proto = {}; + +function CBCState(iv) { + assert.equal(iv.length, 8, 'Invalid IV length'); + + this.iv = new Array(8); + for (var i = 0; i < this.iv.length; i++) + this.iv[i] = iv[i]; } -function fromArrayBuffer (array, byteOffset, length) { - if (byteOffset < 0 || array.byteLength < byteOffset) { - throw new RangeError('"offset" is outside of buffer bounds') +function instantiate(Base) { + function CBC(options) { + Base.call(this, options); + this._cbcInit(); } + inherits(CBC, Base); - if (array.byteLength < byteOffset + (length || 0)) { - throw new RangeError('"length" is outside of buffer bounds') + var keys = Object.keys(proto); + for (var i = 0; i < keys.length; i++) { + var key = keys[i]; + CBC.prototype[key] = proto[key]; } - var buf - if (byteOffset === undefined && length === undefined) { - buf = new Uint8Array(array) - } else if (length === undefined) { - buf = new Uint8Array(array, byteOffset) - } else { - buf = new Uint8Array(array, byteOffset, length) - } + CBC.create = function create(options) { + return new CBC(options); + }; - // Return an augmented `Uint8Array` instance - buf.__proto__ = Buffer.prototype - return buf + return CBC; } -function fromObject (obj) { - if (Buffer.isBuffer(obj)) { - var len = checked(obj.length) | 0 - var buf = createBuffer(len) - - if (buf.length === 0) { - return buf - } +exports.instantiate = instantiate; - obj.copy(buf, 0, 0, len) - return buf - } +proto._cbcInit = function _cbcInit() { + var state = new CBCState(this.options.iv); + this._cbcState = state; +}; - if (obj.length !== undefined) { - if (typeof obj.length !== 'number' || numberIsNaN(obj.length)) { - return createBuffer(0) - } - return fromArrayLike(obj) - } +proto._update = function _update(inp, inOff, out, outOff) { + var state = this._cbcState; + var superProto = this.constructor.super_.prototype; - if (obj.type === 'Buffer' && Array.isArray(obj.data)) { - return fromArrayLike(obj.data) - } -} + var iv = state.iv; + if (this.type === 'encrypt') { + for (var i = 0; i < this.blockSize; i++) + iv[i] ^= inp[inOff + i]; -function checked (length) { - // Note: cannot use `length < K_MAX_LENGTH` here because that fails when - // length is NaN (which is otherwise coerced to zero.) - if (length >= K_MAX_LENGTH) { - throw new RangeError('Attempt to allocate Buffer larger than maximum ' + - 'size: 0x' + K_MAX_LENGTH.toString(16) + ' bytes') - } - return length | 0 -} + superProto._update.call(this, iv, 0, out, outOff); -function SlowBuffer (length) { - if (+length != length) { // eslint-disable-line eqeqeq - length = 0 - } - return Buffer.alloc(+length) -} + for (var i = 0; i < this.blockSize; i++) + iv[i] = out[outOff + i]; + } else { + superProto._update.call(this, inp, inOff, out, outOff); -Buffer.isBuffer = function isBuffer (b) { - return b != null && b._isBuffer === true && - b !== Buffer.prototype // so Buffer.isBuffer(Buffer.prototype) will be false -} + for (var i = 0; i < this.blockSize; i++) + out[outOff + i] ^= iv[i]; -Buffer.compare = function compare (a, b) { - if (isInstance(a, Uint8Array)) a = Buffer.from(a, a.offset, a.byteLength) - if (isInstance(b, Uint8Array)) b = Buffer.from(b, b.offset, b.byteLength) - if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) { - throw new TypeError( - 'The "buf1", "buf2" arguments must be one of type Buffer or Uint8Array' - ) + for (var i = 0; i < this.blockSize; i++) + iv[i] = inp[inOff + i]; } +}; - if (a === b) return 0 +},{"inherits":200,"minimalistic-assert":259}],139:[function(require,module,exports){ +'use strict'; - var x = a.length - var y = b.length +var assert = require('minimalistic-assert'); - for (var i = 0, len = Math.min(x, y); i < len; ++i) { - if (a[i] !== b[i]) { - x = a[i] - y = b[i] - break - } - } +function Cipher(options) { + this.options = options; - if (x < y) return -1 - if (y < x) return 1 - return 0 -} + this.type = this.options.type; + this.blockSize = 8; + this._init(); -Buffer.isEncoding = function isEncoding (encoding) { - switch (String(encoding).toLowerCase()) { - case 'hex': - case 'utf8': - case 'utf-8': - case 'ascii': - case 'latin1': - case 'binary': - case 'base64': - case 'ucs2': - case 'ucs-2': - case 'utf16le': - case 'utf-16le': - return true - default: - return false - } + this.buffer = new Array(this.blockSize); + this.bufferOff = 0; + this.padding = options.padding !== false } +module.exports = Cipher; -Buffer.concat = function concat (list, length) { - if (!Array.isArray(list)) { - throw new TypeError('"list" argument must be an Array of Buffers') - } +Cipher.prototype._init = function _init() { + // Might be overrided +}; - if (list.length === 0) { - return Buffer.alloc(0) - } +Cipher.prototype.update = function update(data) { + if (data.length === 0) + return []; - var i - if (length === undefined) { - length = 0 - for (i = 0; i < list.length; ++i) { - length += list[i].length - } - } + if (this.type === 'decrypt') + return this._updateDecrypt(data); + else + return this._updateEncrypt(data); +}; - var buffer = Buffer.allocUnsafe(length) - var pos = 0 - for (i = 0; i < list.length; ++i) { - var buf = list[i] - if (isInstance(buf, Uint8Array)) { - buf = Buffer.from(buf) - } - if (!Buffer.isBuffer(buf)) { - throw new TypeError('"list" argument must be an Array of Buffers') - } - buf.copy(buffer, pos) - pos += buf.length - } - return buffer -} +Cipher.prototype._buffer = function _buffer(data, off) { + // Append data to buffer + var min = Math.min(this.buffer.length - this.bufferOff, data.length - off); + for (var i = 0; i < min; i++) + this.buffer[this.bufferOff + i] = data[off + i]; + this.bufferOff += min; -function byteLength (string, encoding) { - if (Buffer.isBuffer(string)) { - return string.length - } - if (ArrayBuffer.isView(string) || isInstance(string, ArrayBuffer)) { - return string.byteLength - } - if (typeof string !== 'string') { - throw new TypeError( - 'The "string" argument must be one of type string, Buffer, or ArrayBuffer. ' + - 'Received type ' + typeof string - ) - } + // Shift next + return min; +}; - var len = string.length - var mustMatch = (arguments.length > 2 && arguments[2] === true) - if (!mustMatch && len === 0) return 0 +Cipher.prototype._flushBuffer = function _flushBuffer(out, off) { + this._update(this.buffer, 0, out, off); + this.bufferOff = 0; + return this.blockSize; +}; - // Use a for loop to avoid recursion - var loweredCase = false - for (;;) { - switch (encoding) { - case 'ascii': - case 'latin1': - case 'binary': - return len - case 'utf8': - case 'utf-8': - return utf8ToBytes(string).length - case 'ucs2': - case 'ucs-2': - case 'utf16le': - case 'utf-16le': - return len * 2 - case 'hex': - return len >>> 1 - case 'base64': - return base64ToBytes(string).length - default: - if (loweredCase) { - return mustMatch ? -1 : utf8ToBytes(string).length // assume utf8 - } - encoding = ('' + encoding).toLowerCase() - loweredCase = true - } - } -} -Buffer.byteLength = byteLength +Cipher.prototype._updateEncrypt = function _updateEncrypt(data) { + var inputOff = 0; + var outputOff = 0; -function slowToString (encoding, start, end) { - var loweredCase = false + var count = ((this.bufferOff + data.length) / this.blockSize) | 0; + var out = new Array(count * this.blockSize); - // No need to verify that "this.length <= MAX_UINT32" since it's a read-only - // property of a typed array. + if (this.bufferOff !== 0) { + inputOff += this._buffer(data, inputOff); - // This behaves neither like String nor Uint8Array in that we set start/end - // to their upper/lower bounds if the value passed is out of range. - // undefined is handled specially as per ECMA-262 6th Edition, - // Section 13.3.3.7 Runtime Semantics: KeyedBindingInitialization. - if (start === undefined || start < 0) { - start = 0 - } - // Return early if start > this.length. Done here to prevent potential uint32 - // coercion fail below. - if (start > this.length) { - return '' + if (this.bufferOff === this.buffer.length) + outputOff += this._flushBuffer(out, outputOff); } - if (end === undefined || end > this.length) { - end = this.length + // Write blocks + var max = data.length - ((data.length - inputOff) % this.blockSize); + for (; inputOff < max; inputOff += this.blockSize) { + this._update(data, inputOff, out, outputOff); + outputOff += this.blockSize; } - if (end <= 0) { - return '' - } + // Queue rest + for (; inputOff < data.length; inputOff++, this.bufferOff++) + this.buffer[this.bufferOff] = data[inputOff]; - // Force coersion to uint32. This will also coerce falsey/NaN values to 0. - end >>>= 0 - start >>>= 0 + return out; +}; - if (end <= start) { - return '' +Cipher.prototype._updateDecrypt = function _updateDecrypt(data) { + var inputOff = 0; + var outputOff = 0; + + var count = Math.ceil((this.bufferOff + data.length) / this.blockSize) - 1; + var out = new Array(count * this.blockSize); + + // TODO(indutny): optimize it, this is far from optimal + for (; count > 0; count--) { + inputOff += this._buffer(data, inputOff); + outputOff += this._flushBuffer(out, outputOff); } - if (!encoding) encoding = 'utf8' + // Buffer rest of the input + inputOff += this._buffer(data, inputOff); - while (true) { - switch (encoding) { - case 'hex': - return hexSlice(this, start, end) + return out; +}; - case 'utf8': - case 'utf-8': - return utf8Slice(this, start, end) +Cipher.prototype.final = function final(buffer) { + var first; + if (buffer) + first = this.update(buffer); - case 'ascii': - return asciiSlice(this, start, end) + var last; + if (this.type === 'encrypt') + last = this._finalEncrypt(); + else + last = this._finalDecrypt(); - case 'latin1': - case 'binary': - return latin1Slice(this, start, end) + if (first) + return first.concat(last); + else + return last; +}; - case 'base64': - return base64Slice(this, start, end) +Cipher.prototype._pad = function _pad(buffer, off) { + if (off === 0) + return false; - case 'ucs2': - case 'ucs-2': - case 'utf16le': - case 'utf-16le': - return utf16leSlice(this, start, end) + while (off < buffer.length) + buffer[off++] = 0; - default: - if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding) - encoding = (encoding + '').toLowerCase() - loweredCase = true - } - } -} + return true; +}; -// This property is used by `Buffer.isBuffer` (and the `is-buffer` npm package) -// to detect a Buffer instance. It's not possible to use `instanceof Buffer` -// reliably in a browserify context because there could be multiple different -// copies of the 'buffer' package in use. This method works even for Buffer -// instances that were created from another copy of the `buffer` package. -// See: https://github.com/feross/buffer/issues/154 -Buffer.prototype._isBuffer = true +Cipher.prototype._finalEncrypt = function _finalEncrypt() { + if (!this._pad(this.buffer, this.bufferOff)) + return []; -function swap (b, n, m) { - var i = b[n] - b[n] = b[m] - b[m] = i -} + var out = new Array(this.blockSize); + this._update(this.buffer, 0, out, 0); + return out; +}; -Buffer.prototype.swap16 = function swap16 () { - var len = this.length - if (len % 2 !== 0) { - throw new RangeError('Buffer size must be a multiple of 16-bits') - } - for (var i = 0; i < len; i += 2) { - swap(this, i, i + 1) - } - return this -} +Cipher.prototype._unpad = function _unpad(buffer) { + return buffer; +}; -Buffer.prototype.swap32 = function swap32 () { - var len = this.length - if (len % 4 !== 0) { - throw new RangeError('Buffer size must be a multiple of 32-bits') - } - for (var i = 0; i < len; i += 4) { - swap(this, i, i + 3) - swap(this, i + 1, i + 2) - } - return this -} +Cipher.prototype._finalDecrypt = function _finalDecrypt() { + assert.equal(this.bufferOff, this.blockSize, 'Not enough data to decrypt'); + var out = new Array(this.blockSize); + this._flushBuffer(out, 0); -Buffer.prototype.swap64 = function swap64 () { - var len = this.length - if (len % 8 !== 0) { - throw new RangeError('Buffer size must be a multiple of 64-bits') - } - for (var i = 0; i < len; i += 8) { - swap(this, i, i + 7) - swap(this, i + 1, i + 6) - swap(this, i + 2, i + 5) - swap(this, i + 3, i + 4) - } - return this -} + return this._unpad(out); +}; -Buffer.prototype.toString = function toString () { - var length = this.length - if (length === 0) return '' - if (arguments.length === 0) return utf8Slice(this, 0, length) - return slowToString.apply(this, arguments) -} +},{"minimalistic-assert":259}],140:[function(require,module,exports){ +'use strict'; -Buffer.prototype.toLocaleString = Buffer.prototype.toString +var assert = require('minimalistic-assert'); +var inherits = require('inherits'); -Buffer.prototype.equals = function equals (b) { - if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer') - if (this === b) return true - return Buffer.compare(this, b) === 0 -} +var utils = require('./utils'); +var Cipher = require('./cipher'); -Buffer.prototype.inspect = function inspect () { - var str = '' - var max = exports.INSPECT_MAX_BYTES - str = this.toString('hex', 0, max).replace(/(.{2})/g, '$1 ').trim() - if (this.length > max) str += ' ... ' - return '' +function DESState() { + this.tmp = new Array(2); + this.keys = null; } -Buffer.prototype.compare = function compare (target, start, end, thisStart, thisEnd) { - if (isInstance(target, Uint8Array)) { - target = Buffer.from(target, target.offset, target.byteLength) - } - if (!Buffer.isBuffer(target)) { - throw new TypeError( - 'The "target" argument must be one of type Buffer or Uint8Array. ' + - 'Received type ' + (typeof target) - ) - } +function DES(options) { + Cipher.call(this, options); - if (start === undefined) { - start = 0 - } - if (end === undefined) { - end = target ? target.length : 0 - } - if (thisStart === undefined) { - thisStart = 0 - } - if (thisEnd === undefined) { - thisEnd = this.length - } + var state = new DESState(); + this._desState = state; - if (start < 0 || end > target.length || thisStart < 0 || thisEnd > this.length) { - throw new RangeError('out of range index') - } + this.deriveKeys(state, options.key); +} +inherits(DES, Cipher); +module.exports = DES; - if (thisStart >= thisEnd && start >= end) { - return 0 - } - if (thisStart >= thisEnd) { - return -1 - } - if (start >= end) { - return 1 - } +DES.create = function create(options) { + return new DES(options); +}; - start >>>= 0 - end >>>= 0 - thisStart >>>= 0 - thisEnd >>>= 0 +var shiftTable = [ + 1, 1, 2, 2, 2, 2, 2, 2, + 1, 2, 2, 2, 2, 2, 2, 1 +]; - if (this === target) return 0 +DES.prototype.deriveKeys = function deriveKeys(state, key) { + state.keys = new Array(16 * 2); - var x = thisEnd - thisStart - var y = end - start - var len = Math.min(x, y) + assert.equal(key.length, this.blockSize, 'Invalid key length'); - var thisCopy = this.slice(thisStart, thisEnd) - var targetCopy = target.slice(start, end) + var kL = utils.readUInt32BE(key, 0); + var kR = utils.readUInt32BE(key, 4); - for (var i = 0; i < len; ++i) { - if (thisCopy[i] !== targetCopy[i]) { - x = thisCopy[i] - y = targetCopy[i] - break - } + utils.pc1(kL, kR, state.tmp, 0); + kL = state.tmp[0]; + kR = state.tmp[1]; + for (var i = 0; i < state.keys.length; i += 2) { + var shift = shiftTable[i >>> 1]; + kL = utils.r28shl(kL, shift); + kR = utils.r28shl(kR, shift); + utils.pc2(kL, kR, state.keys, i); } +}; - if (x < y) return -1 - if (y < x) return 1 - return 0 -} +DES.prototype._update = function _update(inp, inOff, out, outOff) { + var state = this._desState; -// Finds either the first index of `val` in `buffer` at offset >= `byteOffset`, -// OR the last index of `val` in `buffer` at offset <= `byteOffset`. -// -// Arguments: -// - buffer - a Buffer to search -// - val - a string, Buffer, or number -// - byteOffset - an index into `buffer`; will be clamped to an int32 -// - encoding - an optional encoding, relevant is val is a string -// - dir - true for indexOf, false for lastIndexOf -function bidirectionalIndexOf (buffer, val, byteOffset, encoding, dir) { - // Empty buffer means no match - if (buffer.length === 0) return -1 + var l = utils.readUInt32BE(inp, inOff); + var r = utils.readUInt32BE(inp, inOff + 4); - // Normalize byteOffset - if (typeof byteOffset === 'string') { - encoding = byteOffset - byteOffset = 0 - } else if (byteOffset > 0x7fffffff) { - byteOffset = 0x7fffffff - } else if (byteOffset < -0x80000000) { - byteOffset = -0x80000000 - } - byteOffset = +byteOffset // Coerce to Number. - if (numberIsNaN(byteOffset)) { - // byteOffset: it it's undefined, null, NaN, "foo", etc, search whole buffer - byteOffset = dir ? 0 : (buffer.length - 1) - } + // Initial Permutation + utils.ip(l, r, state.tmp, 0); + l = state.tmp[0]; + r = state.tmp[1]; - // Normalize byteOffset: negative offsets start from the end of the buffer - if (byteOffset < 0) byteOffset = buffer.length + byteOffset - if (byteOffset >= buffer.length) { - if (dir) return -1 - else byteOffset = buffer.length - 1 - } else if (byteOffset < 0) { - if (dir) byteOffset = 0 - else return -1 - } + if (this.type === 'encrypt') + this._encrypt(state, l, r, state.tmp, 0); + else + this._decrypt(state, l, r, state.tmp, 0); - // Normalize val - if (typeof val === 'string') { - val = Buffer.from(val, encoding) - } + l = state.tmp[0]; + r = state.tmp[1]; - // Finally, search either indexOf (if dir is true) or lastIndexOf - if (Buffer.isBuffer(val)) { - // Special case: looking for empty string/buffer always fails - if (val.length === 0) { - return -1 - } - return arrayIndexOf(buffer, val, byteOffset, encoding, dir) - } else if (typeof val === 'number') { - val = val & 0xFF // Search for a byte value [0-255] - if (typeof Uint8Array.prototype.indexOf === 'function') { - if (dir) { - return Uint8Array.prototype.indexOf.call(buffer, val, byteOffset) - } else { - return Uint8Array.prototype.lastIndexOf.call(buffer, val, byteOffset) - } - } - return arrayIndexOf(buffer, [ val ], byteOffset, encoding, dir) + utils.writeUInt32BE(out, l, outOff); + utils.writeUInt32BE(out, r, outOff + 4); +}; + +DES.prototype._pad = function _pad(buffer, off) { + if (this.padding === false) { + return false; } - throw new TypeError('val must be string, number or Buffer') -} + var value = buffer.length - off; + for (var i = off; i < buffer.length; i++) + buffer[i] = value; -function arrayIndexOf (arr, val, byteOffset, encoding, dir) { - var indexSize = 1 - var arrLength = arr.length - var valLength = val.length + return true; +}; - if (encoding !== undefined) { - encoding = String(encoding).toLowerCase() - if (encoding === 'ucs2' || encoding === 'ucs-2' || - encoding === 'utf16le' || encoding === 'utf-16le') { - if (arr.length < 2 || val.length < 2) { - return -1 - } - indexSize = 2 - arrLength /= 2 - valLength /= 2 - byteOffset /= 2 - } +DES.prototype._unpad = function _unpad(buffer) { + if (this.padding === false) { + return buffer; } - function read (buf, i) { - if (indexSize === 1) { - return buf[i] - } else { - return buf.readUInt16BE(i * indexSize) - } - } + var pad = buffer[buffer.length - 1]; + for (var i = buffer.length - pad; i < buffer.length; i++) + assert.equal(buffer[i], pad); - var i - if (dir) { - var foundIndex = -1 - for (i = byteOffset; i < arrLength; i++) { - if (read(arr, i) === read(val, foundIndex === -1 ? 0 : i - foundIndex)) { - if (foundIndex === -1) foundIndex = i - if (i - foundIndex + 1 === valLength) return foundIndex * indexSize - } else { - if (foundIndex !== -1) i -= i - foundIndex - foundIndex = -1 - } - } - } else { - if (byteOffset + valLength > arrLength) byteOffset = arrLength - valLength - for (i = byteOffset; i >= 0; i--) { - var found = true - for (var j = 0; j < valLength; j++) { - if (read(arr, i + j) !== read(val, j)) { - found = false - break - } - } - if (found) return i - } - } + return buffer.slice(0, buffer.length - pad); +}; - return -1 -} +DES.prototype._encrypt = function _encrypt(state, lStart, rStart, out, off) { + var l = lStart; + var r = rStart; -Buffer.prototype.includes = function includes (val, byteOffset, encoding) { - return this.indexOf(val, byteOffset, encoding) !== -1 -} + // Apply f() x16 times + for (var i = 0; i < state.keys.length; i += 2) { + var keyL = state.keys[i]; + var keyR = state.keys[i + 1]; -Buffer.prototype.indexOf = function indexOf (val, byteOffset, encoding) { - return bidirectionalIndexOf(this, val, byteOffset, encoding, true) -} + // f(r, k) + utils.expand(r, state.tmp, 0); -Buffer.prototype.lastIndexOf = function lastIndexOf (val, byteOffset, encoding) { - return bidirectionalIndexOf(this, val, byteOffset, encoding, false) -} + keyL ^= state.tmp[0]; + keyR ^= state.tmp[1]; + var s = utils.substitute(keyL, keyR); + var f = utils.permute(s); -function hexWrite (buf, string, offset, length) { - offset = Number(offset) || 0 - var remaining = buf.length - offset - if (!length) { - length = remaining - } else { - length = Number(length) - if (length > remaining) { - length = remaining - } + var t = r; + r = (l ^ f) >>> 0; + l = t; } - var strLen = string.length + // Reverse Initial Permutation + utils.rip(r, l, out, off); +}; - if (length > strLen / 2) { - length = strLen / 2 - } - for (var i = 0; i < length; ++i) { - var parsed = parseInt(string.substr(i * 2, 2), 16) - if (numberIsNaN(parsed)) return i - buf[offset + i] = parsed +DES.prototype._decrypt = function _decrypt(state, lStart, rStart, out, off) { + var l = rStart; + var r = lStart; + + // Apply f() x16 times + for (var i = state.keys.length - 2; i >= 0; i -= 2) { + var keyL = state.keys[i]; + var keyR = state.keys[i + 1]; + + // f(r, k) + utils.expand(l, state.tmp, 0); + + keyL ^= state.tmp[0]; + keyR ^= state.tmp[1]; + var s = utils.substitute(keyL, keyR); + var f = utils.permute(s); + + var t = l; + l = (r ^ f) >>> 0; + r = t; } - return i -} -function utf8Write (buf, string, offset, length) { - return blitBuffer(utf8ToBytes(string, buf.length - offset), buf, offset, length) -} + // Reverse Initial Permutation + utils.rip(l, r, out, off); +}; -function asciiWrite (buf, string, offset, length) { - return blitBuffer(asciiToBytes(string), buf, offset, length) -} +},{"./cipher":139,"./utils":142,"inherits":200,"minimalistic-assert":259}],141:[function(require,module,exports){ +'use strict'; -function latin1Write (buf, string, offset, length) { - return asciiWrite(buf, string, offset, length) -} +var assert = require('minimalistic-assert'); +var inherits = require('inherits'); -function base64Write (buf, string, offset, length) { - return blitBuffer(base64ToBytes(string), buf, offset, length) -} +var Cipher = require('./cipher'); +var DES = require('./des'); -function ucs2Write (buf, string, offset, length) { - return blitBuffer(utf16leToBytes(string, buf.length - offset), buf, offset, length) -} +function EDEState(type, key) { + assert.equal(key.length, 24, 'Invalid key length'); -Buffer.prototype.write = function write (string, offset, length, encoding) { - // Buffer#write(string) - if (offset === undefined) { - encoding = 'utf8' - length = this.length - offset = 0 - // Buffer#write(string, encoding) - } else if (length === undefined && typeof offset === 'string') { - encoding = offset - length = this.length - offset = 0 - // Buffer#write(string, offset[, length][, encoding]) - } else if (isFinite(offset)) { - offset = offset >>> 0 - if (isFinite(length)) { - length = length >>> 0 - if (encoding === undefined) encoding = 'utf8' - } else { - encoding = length - length = undefined - } + var k1 = key.slice(0, 8); + var k2 = key.slice(8, 16); + var k3 = key.slice(16, 24); + + if (type === 'encrypt') { + this.ciphers = [ + DES.create({ type: 'encrypt', key: k1 }), + DES.create({ type: 'decrypt', key: k2 }), + DES.create({ type: 'encrypt', key: k3 }) + ]; } else { - throw new Error( - 'Buffer.write(string, encoding, offset[, length]) is no longer supported' - ) + this.ciphers = [ + DES.create({ type: 'decrypt', key: k3 }), + DES.create({ type: 'encrypt', key: k2 }), + DES.create({ type: 'decrypt', key: k1 }) + ]; } +} - var remaining = this.length - offset - if (length === undefined || length > remaining) length = remaining +function EDE(options) { + Cipher.call(this, options); - if ((string.length > 0 && (length < 0 || offset < 0)) || offset > this.length) { - throw new RangeError('Attempt to write outside buffer bounds') - } + var state = new EDEState(this.type, this.options.key); + this._edeState = state; +} +inherits(EDE, Cipher); - if (!encoding) encoding = 'utf8' +module.exports = EDE; - var loweredCase = false - for (;;) { - switch (encoding) { - case 'hex': - return hexWrite(this, string, offset, length) +EDE.create = function create(options) { + return new EDE(options); +}; - case 'utf8': - case 'utf-8': - return utf8Write(this, string, offset, length) +EDE.prototype._update = function _update(inp, inOff, out, outOff) { + var state = this._edeState; - case 'ascii': - return asciiWrite(this, string, offset, length) + state.ciphers[0]._update(inp, inOff, out, outOff); + state.ciphers[1]._update(out, outOff, out, outOff); + state.ciphers[2]._update(out, outOff, out, outOff); +}; - case 'latin1': - case 'binary': - return latin1Write(this, string, offset, length) +EDE.prototype._pad = DES.prototype._pad; +EDE.prototype._unpad = DES.prototype._unpad; - case 'base64': - // Warning: maxLength not taken into account in base64Write - return base64Write(this, string, offset, length) +},{"./cipher":139,"./des":140,"inherits":200,"minimalistic-assert":259}],142:[function(require,module,exports){ +'use strict'; - case 'ucs2': - case 'ucs-2': - case 'utf16le': - case 'utf-16le': - return ucs2Write(this, string, offset, length) +exports.readUInt32BE = function readUInt32BE(bytes, off) { + var res = (bytes[0 + off] << 24) | + (bytes[1 + off] << 16) | + (bytes[2 + off] << 8) | + bytes[3 + off]; + return res >>> 0; +}; - default: - if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding) - encoding = ('' + encoding).toLowerCase() - loweredCase = true +exports.writeUInt32BE = function writeUInt32BE(bytes, value, off) { + bytes[0 + off] = value >>> 24; + bytes[1 + off] = (value >>> 16) & 0xff; + bytes[2 + off] = (value >>> 8) & 0xff; + bytes[3 + off] = value & 0xff; +}; + +exports.ip = function ip(inL, inR, out, off) { + var outL = 0; + var outR = 0; + + for (var i = 6; i >= 0; i -= 2) { + for (var j = 0; j <= 24; j += 8) { + outL <<= 1; + outL |= (inR >>> (j + i)) & 1; + } + for (var j = 0; j <= 24; j += 8) { + outL <<= 1; + outL |= (inL >>> (j + i)) & 1; } } -} -Buffer.prototype.toJSON = function toJSON () { - return { - type: 'Buffer', - data: Array.prototype.slice.call(this._arr || this, 0) + for (var i = 6; i >= 0; i -= 2) { + for (var j = 1; j <= 25; j += 8) { + outR <<= 1; + outR |= (inR >>> (j + i)) & 1; + } + for (var j = 1; j <= 25; j += 8) { + outR <<= 1; + outR |= (inL >>> (j + i)) & 1; + } } -} -function base64Slice (buf, start, end) { - if (start === 0 && end === buf.length) { - return base64.fromByteArray(buf) - } else { - return base64.fromByteArray(buf.slice(start, end)) - } -} + out[off + 0] = outL >>> 0; + out[off + 1] = outR >>> 0; +}; -function utf8Slice (buf, start, end) { - end = Math.min(buf.length, end) - var res = [] +exports.rip = function rip(inL, inR, out, off) { + var outL = 0; + var outR = 0; - var i = start - while (i < end) { - var firstByte = buf[i] - var codePoint = null - var bytesPerSequence = (firstByte > 0xEF) ? 4 - : (firstByte > 0xDF) ? 3 - : (firstByte > 0xBF) ? 2 - : 1 - - if (i + bytesPerSequence <= end) { - var secondByte, thirdByte, fourthByte, tempCodePoint - - switch (bytesPerSequence) { - case 1: - if (firstByte < 0x80) { - codePoint = firstByte - } - break - case 2: - secondByte = buf[i + 1] - if ((secondByte & 0xC0) === 0x80) { - tempCodePoint = (firstByte & 0x1F) << 0x6 | (secondByte & 0x3F) - if (tempCodePoint > 0x7F) { - codePoint = tempCodePoint - } - } - break - case 3: - secondByte = buf[i + 1] - thirdByte = buf[i + 2] - if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80) { - tempCodePoint = (firstByte & 0xF) << 0xC | (secondByte & 0x3F) << 0x6 | (thirdByte & 0x3F) - if (tempCodePoint > 0x7FF && (tempCodePoint < 0xD800 || tempCodePoint > 0xDFFF)) { - codePoint = tempCodePoint - } - } - break - case 4: - secondByte = buf[i + 1] - thirdByte = buf[i + 2] - fourthByte = buf[i + 3] - if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80 && (fourthByte & 0xC0) === 0x80) { - tempCodePoint = (firstByte & 0xF) << 0x12 | (secondByte & 0x3F) << 0xC | (thirdByte & 0x3F) << 0x6 | (fourthByte & 0x3F) - if (tempCodePoint > 0xFFFF && tempCodePoint < 0x110000) { - codePoint = tempCodePoint - } - } - } + for (var i = 0; i < 4; i++) { + for (var j = 24; j >= 0; j -= 8) { + outL <<= 1; + outL |= (inR >>> (j + i)) & 1; + outL <<= 1; + outL |= (inL >>> (j + i)) & 1; } - - if (codePoint === null) { - // we did not generate a valid codePoint so insert a - // replacement char (U+FFFD) and advance only 1 byte - codePoint = 0xFFFD - bytesPerSequence = 1 - } else if (codePoint > 0xFFFF) { - // encode to utf16 (surrogate pair dance) - codePoint -= 0x10000 - res.push(codePoint >>> 10 & 0x3FF | 0xD800) - codePoint = 0xDC00 | codePoint & 0x3FF + } + for (var i = 4; i < 8; i++) { + for (var j = 24; j >= 0; j -= 8) { + outR <<= 1; + outR |= (inR >>> (j + i)) & 1; + outR <<= 1; + outR |= (inL >>> (j + i)) & 1; } - - res.push(codePoint) - i += bytesPerSequence } - return decodeCodePointsArray(res) -} + out[off + 0] = outL >>> 0; + out[off + 1] = outR >>> 0; +}; -// Based on http://stackoverflow.com/a/22747272/680742, the browser with -// the lowest limit is Chrome, with 0x10000 args. -// We go 1 magnitude less, for safety -var MAX_ARGUMENTS_LENGTH = 0x1000 +exports.pc1 = function pc1(inL, inR, out, off) { + var outL = 0; + var outR = 0; -function decodeCodePointsArray (codePoints) { - var len = codePoints.length - if (len <= MAX_ARGUMENTS_LENGTH) { - return String.fromCharCode.apply(String, codePoints) // avoid extra slice() + // 7, 15, 23, 31, 39, 47, 55, 63 + // 6, 14, 22, 30, 39, 47, 55, 63 + // 5, 13, 21, 29, 39, 47, 55, 63 + // 4, 12, 20, 28 + for (var i = 7; i >= 5; i--) { + for (var j = 0; j <= 24; j += 8) { + outL <<= 1; + outL |= (inR >> (j + i)) & 1; + } + for (var j = 0; j <= 24; j += 8) { + outL <<= 1; + outL |= (inL >> (j + i)) & 1; + } } - - // Decode in chunks to avoid "call stack size exceeded". - var res = '' - var i = 0 - while (i < len) { - res += String.fromCharCode.apply( - String, - codePoints.slice(i, i += MAX_ARGUMENTS_LENGTH) - ) + for (var j = 0; j <= 24; j += 8) { + outL <<= 1; + outL |= (inR >> (j + i)) & 1; } - return res -} - -function asciiSlice (buf, start, end) { - var ret = '' - end = Math.min(buf.length, end) - for (var i = start; i < end; ++i) { - ret += String.fromCharCode(buf[i] & 0x7F) + // 1, 9, 17, 25, 33, 41, 49, 57 + // 2, 10, 18, 26, 34, 42, 50, 58 + // 3, 11, 19, 27, 35, 43, 51, 59 + // 36, 44, 52, 60 + for (var i = 1; i <= 3; i++) { + for (var j = 0; j <= 24; j += 8) { + outR <<= 1; + outR |= (inR >> (j + i)) & 1; + } + for (var j = 0; j <= 24; j += 8) { + outR <<= 1; + outR |= (inL >> (j + i)) & 1; + } } - return ret -} - -function latin1Slice (buf, start, end) { - var ret = '' - end = Math.min(buf.length, end) - - for (var i = start; i < end; ++i) { - ret += String.fromCharCode(buf[i]) + for (var j = 0; j <= 24; j += 8) { + outR <<= 1; + outR |= (inL >> (j + i)) & 1; } - return ret -} -function hexSlice (buf, start, end) { - var len = buf.length + out[off + 0] = outL >>> 0; + out[off + 1] = outR >>> 0; +}; - if (!start || start < 0) start = 0 - if (!end || end < 0 || end > len) end = len +exports.r28shl = function r28shl(num, shift) { + return ((num << shift) & 0xfffffff) | (num >>> (28 - shift)); +}; - var out = '' - for (var i = start; i < end; ++i) { - out += toHex(buf[i]) - } - return out -} +var pc2table = [ + // inL => outL + 14, 11, 17, 4, 27, 23, 25, 0, + 13, 22, 7, 18, 5, 9, 16, 24, + 2, 20, 12, 21, 1, 8, 15, 26, -function utf16leSlice (buf, start, end) { - var bytes = buf.slice(start, end) - var res = '' - for (var i = 0; i < bytes.length; i += 2) { - res += String.fromCharCode(bytes[i] + (bytes[i + 1] * 256)) - } - return res -} + // inR => outR + 15, 4, 25, 19, 9, 1, 26, 16, + 5, 11, 23, 8, 12, 7, 17, 0, + 22, 3, 10, 14, 6, 20, 27, 24 +]; -Buffer.prototype.slice = function slice (start, end) { - var len = this.length - start = ~~start - end = end === undefined ? len : ~~end +exports.pc2 = function pc2(inL, inR, out, off) { + var outL = 0; + var outR = 0; - if (start < 0) { - start += len - if (start < 0) start = 0 - } else if (start > len) { - start = len + var len = pc2table.length >>> 1; + for (var i = 0; i < len; i++) { + outL <<= 1; + outL |= (inL >>> pc2table[i]) & 0x1; } - - if (end < 0) { - end += len - if (end < 0) end = 0 - } else if (end > len) { - end = len + for (var i = len; i < pc2table.length; i++) { + outR <<= 1; + outR |= (inR >>> pc2table[i]) & 0x1; } - if (end < start) end = start - - var newBuf = this.subarray(start, end) - // Return an augmented `Uint8Array` instance - newBuf.__proto__ = Buffer.prototype - return newBuf -} - -/* - * Need to make sure that buffer isn't trying to write out of bounds. - */ -function checkOffset (offset, ext, length) { - if ((offset % 1) !== 0 || offset < 0) throw new RangeError('offset is not uint') - if (offset + ext > length) throw new RangeError('Trying to access beyond buffer length') -} + out[off + 0] = outL >>> 0; + out[off + 1] = outR >>> 0; +}; -Buffer.prototype.readUIntLE = function readUIntLE (offset, byteLength, noAssert) { - offset = offset >>> 0 - byteLength = byteLength >>> 0 - if (!noAssert) checkOffset(offset, byteLength, this.length) +exports.expand = function expand(r, out, off) { + var outL = 0; + var outR = 0; - var val = this[offset] - var mul = 1 - var i = 0 - while (++i < byteLength && (mul *= 0x100)) { - val += this[offset + i] * mul + outL = ((r & 1) << 5) | (r >>> 27); + for (var i = 23; i >= 15; i -= 4) { + outL <<= 6; + outL |= (r >>> i) & 0x3f; } - - return val -} - -Buffer.prototype.readUIntBE = function readUIntBE (offset, byteLength, noAssert) { - offset = offset >>> 0 - byteLength = byteLength >>> 0 - if (!noAssert) { - checkOffset(offset, byteLength, this.length) + for (var i = 11; i >= 3; i -= 4) { + outR |= (r >>> i) & 0x3f; + outR <<= 6; } + outR |= ((r & 0x1f) << 1) | (r >>> 31); - var val = this[offset + --byteLength] - var mul = 1 - while (byteLength > 0 && (mul *= 0x100)) { - val += this[offset + --byteLength] * mul - } + out[off + 0] = outL >>> 0; + out[off + 1] = outR >>> 0; +}; - return val -} +var sTable = [ + 14, 0, 4, 15, 13, 7, 1, 4, 2, 14, 15, 2, 11, 13, 8, 1, + 3, 10, 10, 6, 6, 12, 12, 11, 5, 9, 9, 5, 0, 3, 7, 8, + 4, 15, 1, 12, 14, 8, 8, 2, 13, 4, 6, 9, 2, 1, 11, 7, + 15, 5, 12, 11, 9, 3, 7, 14, 3, 10, 10, 0, 5, 6, 0, 13, -Buffer.prototype.readUInt8 = function readUInt8 (offset, noAssert) { - offset = offset >>> 0 - if (!noAssert) checkOffset(offset, 1, this.length) - return this[offset] -} + 15, 3, 1, 13, 8, 4, 14, 7, 6, 15, 11, 2, 3, 8, 4, 14, + 9, 12, 7, 0, 2, 1, 13, 10, 12, 6, 0, 9, 5, 11, 10, 5, + 0, 13, 14, 8, 7, 10, 11, 1, 10, 3, 4, 15, 13, 4, 1, 2, + 5, 11, 8, 6, 12, 7, 6, 12, 9, 0, 3, 5, 2, 14, 15, 9, -Buffer.prototype.readUInt16LE = function readUInt16LE (offset, noAssert) { - offset = offset >>> 0 - if (!noAssert) checkOffset(offset, 2, this.length) - return this[offset] | (this[offset + 1] << 8) -} + 10, 13, 0, 7, 9, 0, 14, 9, 6, 3, 3, 4, 15, 6, 5, 10, + 1, 2, 13, 8, 12, 5, 7, 14, 11, 12, 4, 11, 2, 15, 8, 1, + 13, 1, 6, 10, 4, 13, 9, 0, 8, 6, 15, 9, 3, 8, 0, 7, + 11, 4, 1, 15, 2, 14, 12, 3, 5, 11, 10, 5, 14, 2, 7, 12, -Buffer.prototype.readUInt16BE = function readUInt16BE (offset, noAssert) { - offset = offset >>> 0 - if (!noAssert) checkOffset(offset, 2, this.length) - return (this[offset] << 8) | this[offset + 1] -} + 7, 13, 13, 8, 14, 11, 3, 5, 0, 6, 6, 15, 9, 0, 10, 3, + 1, 4, 2, 7, 8, 2, 5, 12, 11, 1, 12, 10, 4, 14, 15, 9, + 10, 3, 6, 15, 9, 0, 0, 6, 12, 10, 11, 1, 7, 13, 13, 8, + 15, 9, 1, 4, 3, 5, 14, 11, 5, 12, 2, 7, 8, 2, 4, 14, -Buffer.prototype.readUInt32LE = function readUInt32LE (offset, noAssert) { - offset = offset >>> 0 - if (!noAssert) checkOffset(offset, 4, this.length) + 2, 14, 12, 11, 4, 2, 1, 12, 7, 4, 10, 7, 11, 13, 6, 1, + 8, 5, 5, 0, 3, 15, 15, 10, 13, 3, 0, 9, 14, 8, 9, 6, + 4, 11, 2, 8, 1, 12, 11, 7, 10, 1, 13, 14, 7, 2, 8, 13, + 15, 6, 9, 15, 12, 0, 5, 9, 6, 10, 3, 4, 0, 5, 14, 3, - return ((this[offset]) | - (this[offset + 1] << 8) | - (this[offset + 2] << 16)) + - (this[offset + 3] * 0x1000000) -} + 12, 10, 1, 15, 10, 4, 15, 2, 9, 7, 2, 12, 6, 9, 8, 5, + 0, 6, 13, 1, 3, 13, 4, 14, 14, 0, 7, 11, 5, 3, 11, 8, + 9, 4, 14, 3, 15, 2, 5, 12, 2, 9, 8, 5, 12, 15, 3, 10, + 7, 11, 0, 14, 4, 1, 10, 7, 1, 6, 13, 0, 11, 8, 6, 13, -Buffer.prototype.readUInt32BE = function readUInt32BE (offset, noAssert) { - offset = offset >>> 0 - if (!noAssert) checkOffset(offset, 4, this.length) + 4, 13, 11, 0, 2, 11, 14, 7, 15, 4, 0, 9, 8, 1, 13, 10, + 3, 14, 12, 3, 9, 5, 7, 12, 5, 2, 10, 15, 6, 8, 1, 6, + 1, 6, 4, 11, 11, 13, 13, 8, 12, 1, 3, 4, 7, 10, 14, 7, + 10, 9, 15, 5, 6, 0, 8, 15, 0, 14, 5, 2, 9, 3, 2, 12, - return (this[offset] * 0x1000000) + - ((this[offset + 1] << 16) | - (this[offset + 2] << 8) | - this[offset + 3]) -} + 13, 1, 2, 15, 8, 13, 4, 8, 6, 10, 15, 3, 11, 7, 1, 4, + 10, 12, 9, 5, 3, 6, 14, 11, 5, 0, 0, 14, 12, 9, 7, 2, + 7, 2, 11, 1, 4, 14, 1, 7, 9, 4, 12, 10, 14, 8, 2, 13, + 0, 15, 6, 12, 10, 9, 13, 0, 15, 3, 3, 5, 5, 6, 8, 11 +]; -Buffer.prototype.readIntLE = function readIntLE (offset, byteLength, noAssert) { - offset = offset >>> 0 - byteLength = byteLength >>> 0 - if (!noAssert) checkOffset(offset, byteLength, this.length) +exports.substitute = function substitute(inL, inR) { + var out = 0; + for (var i = 0; i < 4; i++) { + var b = (inL >>> (18 - i * 6)) & 0x3f; + var sb = sTable[i * 0x40 + b]; - var val = this[offset] - var mul = 1 - var i = 0 - while (++i < byteLength && (mul *= 0x100)) { - val += this[offset + i] * mul + out <<= 4; + out |= sb; } - mul *= 0x80 - - if (val >= mul) val -= Math.pow(2, 8 * byteLength) - - return val -} - -Buffer.prototype.readIntBE = function readIntBE (offset, byteLength, noAssert) { - offset = offset >>> 0 - byteLength = byteLength >>> 0 - if (!noAssert) checkOffset(offset, byteLength, this.length) + for (var i = 0; i < 4; i++) { + var b = (inR >>> (18 - i * 6)) & 0x3f; + var sb = sTable[4 * 0x40 + i * 0x40 + b]; - var i = byteLength - var mul = 1 - var val = this[offset + --i] - while (i > 0 && (mul *= 0x100)) { - val += this[offset + --i] * mul + out <<= 4; + out |= sb; } - mul *= 0x80 - - if (val >= mul) val -= Math.pow(2, 8 * byteLength) - - return val -} - -Buffer.prototype.readInt8 = function readInt8 (offset, noAssert) { - offset = offset >>> 0 - if (!noAssert) checkOffset(offset, 1, this.length) - if (!(this[offset] & 0x80)) return (this[offset]) - return ((0xff - this[offset] + 1) * -1) -} - -Buffer.prototype.readInt16LE = function readInt16LE (offset, noAssert) { - offset = offset >>> 0 - if (!noAssert) checkOffset(offset, 2, this.length) - var val = this[offset] | (this[offset + 1] << 8) - return (val & 0x8000) ? val | 0xFFFF0000 : val -} - -Buffer.prototype.readInt16BE = function readInt16BE (offset, noAssert) { - offset = offset >>> 0 - if (!noAssert) checkOffset(offset, 2, this.length) - var val = this[offset + 1] | (this[offset] << 8) - return (val & 0x8000) ? val | 0xFFFF0000 : val -} + return out >>> 0; +}; -Buffer.prototype.readInt32LE = function readInt32LE (offset, noAssert) { - offset = offset >>> 0 - if (!noAssert) checkOffset(offset, 4, this.length) +var permuteTable = [ + 16, 25, 12, 11, 3, 20, 4, 15, 31, 17, 9, 6, 27, 14, 1, 22, + 30, 24, 8, 18, 0, 5, 29, 23, 13, 19, 2, 26, 10, 21, 28, 7 +]; - return (this[offset]) | - (this[offset + 1] << 8) | - (this[offset + 2] << 16) | - (this[offset + 3] << 24) -} +exports.permute = function permute(num) { + var out = 0; + for (var i = 0; i < permuteTable.length; i++) { + out <<= 1; + out |= (num >>> permuteTable[i]) & 0x1; + } + return out >>> 0; +}; -Buffer.prototype.readInt32BE = function readInt32BE (offset, noAssert) { - offset = offset >>> 0 - if (!noAssert) checkOffset(offset, 4, this.length) +exports.padSplit = function padSplit(num, size, group) { + var str = num.toString(2); + while (str.length < size) + str = '0' + str; - return (this[offset] << 24) | - (this[offset + 1] << 16) | - (this[offset + 2] << 8) | - (this[offset + 3]) -} + var out = []; + for (var i = 0; i < size; i += group) + out.push(str.slice(i, i + group)); + return out.join(' '); +}; -Buffer.prototype.readFloatLE = function readFloatLE (offset, noAssert) { - offset = offset >>> 0 - if (!noAssert) checkOffset(offset, 4, this.length) - return ieee754.read(this, offset, true, 23, 4) -} +},{}],143:[function(require,module,exports){ +(function (Buffer){(function (){ +var generatePrime = require('./lib/generatePrime') +var primes = require('./lib/primes.json') -Buffer.prototype.readFloatBE = function readFloatBE (offset, noAssert) { - offset = offset >>> 0 - if (!noAssert) checkOffset(offset, 4, this.length) - return ieee754.read(this, offset, false, 23, 4) -} +var DH = require('./lib/dh') -Buffer.prototype.readDoubleLE = function readDoubleLE (offset, noAssert) { - offset = offset >>> 0 - if (!noAssert) checkOffset(offset, 8, this.length) - return ieee754.read(this, offset, true, 52, 8) -} +function getDiffieHellman (mod) { + var prime = new Buffer(primes[mod].prime, 'hex') + var gen = new Buffer(primes[mod].gen, 'hex') -Buffer.prototype.readDoubleBE = function readDoubleBE (offset, noAssert) { - offset = offset >>> 0 - if (!noAssert) checkOffset(offset, 8, this.length) - return ieee754.read(this, offset, false, 52, 8) + return new DH(prime, gen) } -function checkInt (buf, value, offset, ext, max, min) { - if (!Buffer.isBuffer(buf)) throw new TypeError('"buffer" argument must be a Buffer instance') - if (value > max || value < min) throw new RangeError('"value" argument is out of bounds') - if (offset + ext > buf.length) throw new RangeError('Index out of range') +var ENCODINGS = { + 'binary': true, 'hex': true, 'base64': true } -Buffer.prototype.writeUIntLE = function writeUIntLE (value, offset, byteLength, noAssert) { - value = +value - offset = offset >>> 0 - byteLength = byteLength >>> 0 - if (!noAssert) { - var maxBytes = Math.pow(2, 8 * byteLength) - 1 - checkInt(this, value, offset, byteLength, maxBytes, 0) +function createDiffieHellman (prime, enc, generator, genc) { + if (Buffer.isBuffer(enc) || ENCODINGS[enc] === undefined) { + return createDiffieHellman(prime, 'binary', enc, generator) } - var mul = 1 - var i = 0 - this[offset] = value & 0xFF - while (++i < byteLength && (mul *= 0x100)) { - this[offset + i] = (value / mul) & 0xFF - } + enc = enc || 'binary' + genc = genc || 'binary' + generator = generator || new Buffer([2]) - return offset + byteLength -} + if (!Buffer.isBuffer(generator)) { + generator = new Buffer(generator, genc) + } -Buffer.prototype.writeUIntBE = function writeUIntBE (value, offset, byteLength, noAssert) { - value = +value - offset = offset >>> 0 - byteLength = byteLength >>> 0 - if (!noAssert) { - var maxBytes = Math.pow(2, 8 * byteLength) - 1 - checkInt(this, value, offset, byteLength, maxBytes, 0) + if (typeof prime === 'number') { + return new DH(generatePrime(prime, generator), generator, true) } - var i = byteLength - 1 - var mul = 1 - this[offset + i] = value & 0xFF - while (--i >= 0 && (mul *= 0x100)) { - this[offset + i] = (value / mul) & 0xFF + if (!Buffer.isBuffer(prime)) { + prime = new Buffer(prime, enc) } - return offset + byteLength + return new DH(prime, generator, true) } -Buffer.prototype.writeUInt8 = function writeUInt8 (value, offset, noAssert) { - value = +value - offset = offset >>> 0 - if (!noAssert) checkInt(this, value, offset, 1, 0xff, 0) - this[offset] = (value & 0xff) - return offset + 1 -} - -Buffer.prototype.writeUInt16LE = function writeUInt16LE (value, offset, noAssert) { - value = +value - offset = offset >>> 0 - if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0) - this[offset] = (value & 0xff) - this[offset + 1] = (value >>> 8) - return offset + 2 -} +exports.DiffieHellmanGroup = exports.createDiffieHellmanGroup = exports.getDiffieHellman = getDiffieHellman +exports.createDiffieHellman = exports.DiffieHellman = createDiffieHellman -Buffer.prototype.writeUInt16BE = function writeUInt16BE (value, offset, noAssert) { - value = +value - offset = offset >>> 0 - if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0) - this[offset] = (value >>> 8) - this[offset + 1] = (value & 0xff) - return offset + 2 -} +}).call(this)}).call(this,require("buffer").Buffer) +},{"./lib/dh":144,"./lib/generatePrime":145,"./lib/primes.json":146,"buffer":118}],144:[function(require,module,exports){ +(function (Buffer){(function (){ +var BN = require('bn.js'); +var MillerRabin = require('miller-rabin'); +var millerRabin = new MillerRabin(); +var TWENTYFOUR = new BN(24); +var ELEVEN = new BN(11); +var TEN = new BN(10); +var THREE = new BN(3); +var SEVEN = new BN(7); +var primes = require('./generatePrime'); +var randomBytes = require('randombytes'); +module.exports = DH; -Buffer.prototype.writeUInt32LE = function writeUInt32LE (value, offset, noAssert) { - value = +value - offset = offset >>> 0 - if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0) - this[offset + 3] = (value >>> 24) - this[offset + 2] = (value >>> 16) - this[offset + 1] = (value >>> 8) - this[offset] = (value & 0xff) - return offset + 4 +function setPublicKey(pub, enc) { + enc = enc || 'utf8'; + if (!Buffer.isBuffer(pub)) { + pub = new Buffer(pub, enc); + } + this._pub = new BN(pub); + return this; } -Buffer.prototype.writeUInt32BE = function writeUInt32BE (value, offset, noAssert) { - value = +value - offset = offset >>> 0 - if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0) - this[offset] = (value >>> 24) - this[offset + 1] = (value >>> 16) - this[offset + 2] = (value >>> 8) - this[offset + 3] = (value & 0xff) - return offset + 4 +function setPrivateKey(priv, enc) { + enc = enc || 'utf8'; + if (!Buffer.isBuffer(priv)) { + priv = new Buffer(priv, enc); + } + this._priv = new BN(priv); + return this; } -Buffer.prototype.writeIntLE = function writeIntLE (value, offset, byteLength, noAssert) { - value = +value - offset = offset >>> 0 - if (!noAssert) { - var limit = Math.pow(2, (8 * byteLength) - 1) - - checkInt(this, value, offset, byteLength, limit - 1, -limit) +var primeCache = {}; +function checkPrime(prime, generator) { + var gen = generator.toString('hex'); + var hex = [gen, prime.toString(16)].join('_'); + if (hex in primeCache) { + return primeCache[hex]; } + var error = 0; - var i = 0 - var mul = 1 - var sub = 0 - this[offset] = value & 0xFF - while (++i < byteLength && (mul *= 0x100)) { - if (value < 0 && sub === 0 && this[offset + i - 1] !== 0) { - sub = 1 + if (prime.isEven() || + !primes.simpleSieve || + !primes.fermatTest(prime) || + !millerRabin.test(prime)) { + //not a prime so +1 + error += 1; + + if (gen === '02' || gen === '05') { + // we'd be able to check the generator + // it would fail so +8 + error += 8; + } else { + //we wouldn't be able to test the generator + // so +4 + error += 4; } - this[offset + i] = ((value / mul) >> 0) - sub & 0xFF + primeCache[hex] = error; + return error; } - - return offset + byteLength + if (!millerRabin.test(prime.shrn(1))) { + //not a safe prime + error += 2; + } + var rem; + switch (gen) { + case '02': + if (prime.mod(TWENTYFOUR).cmp(ELEVEN)) { + // unsuidable generator + error += 8; + } + break; + case '05': + rem = prime.mod(TEN); + if (rem.cmp(THREE) && rem.cmp(SEVEN)) { + // prime mod 10 needs to equal 3 or 7 + error += 8; + } + break; + default: + error += 4; + } + primeCache[hex] = error; + return error; } -Buffer.prototype.writeIntBE = function writeIntBE (value, offset, byteLength, noAssert) { - value = +value - offset = offset >>> 0 - if (!noAssert) { - var limit = Math.pow(2, (8 * byteLength) - 1) - - checkInt(this, value, offset, byteLength, limit - 1, -limit) +function DH(prime, generator, malleable) { + this.setGenerator(generator); + this.__prime = new BN(prime); + this._prime = BN.mont(this.__prime); + this._primeLen = prime.length; + this._pub = undefined; + this._priv = undefined; + this._primeCode = undefined; + if (malleable) { + this.setPublicKey = setPublicKey; + this.setPrivateKey = setPrivateKey; + } else { + this._primeCode = 8; } - - var i = byteLength - 1 - var mul = 1 - var sub = 0 - this[offset + i] = value & 0xFF - while (--i >= 0 && (mul *= 0x100)) { - if (value < 0 && sub === 0 && this[offset + i + 1] !== 0) { - sub = 1 +} +Object.defineProperty(DH.prototype, 'verifyError', { + enumerable: true, + get: function () { + if (typeof this._primeCode !== 'number') { + this._primeCode = checkPrime(this.__prime, this.__gen); } - this[offset + i] = ((value / mul) >> 0) - sub & 0xFF + return this._primeCode; } +}); +DH.prototype.generateKeys = function () { + if (!this._priv) { + this._priv = new BN(randomBytes(this._primeLen)); + } + this._pub = this._gen.toRed(this._prime).redPow(this._priv).fromRed(); + return this.getPublicKey(); +}; - return offset + byteLength -} - -Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) { - value = +value - offset = offset >>> 0 - if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80) - if (value < 0) value = 0xff + value + 1 - this[offset] = (value & 0xff) - return offset + 1 -} +DH.prototype.computeSecret = function (other) { + other = new BN(other); + other = other.toRed(this._prime); + var secret = other.redPow(this._priv).fromRed(); + var out = new Buffer(secret.toArray()); + var prime = this.getPrime(); + if (out.length < prime.length) { + var front = new Buffer(prime.length - out.length); + front.fill(0); + out = Buffer.concat([front, out]); + } + return out; +}; -Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) { - value = +value - offset = offset >>> 0 - if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000) - this[offset] = (value & 0xff) - this[offset + 1] = (value >>> 8) - return offset + 2 -} +DH.prototype.getPublicKey = function getPublicKey(enc) { + return formatReturnValue(this._pub, enc); +}; -Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) { - value = +value - offset = offset >>> 0 - if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000) - this[offset] = (value >>> 8) - this[offset + 1] = (value & 0xff) - return offset + 2 -} +DH.prototype.getPrivateKey = function getPrivateKey(enc) { + return formatReturnValue(this._priv, enc); +}; -Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) { - value = +value - offset = offset >>> 0 - if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000) - this[offset] = (value & 0xff) - this[offset + 1] = (value >>> 8) - this[offset + 2] = (value >>> 16) - this[offset + 3] = (value >>> 24) - return offset + 4 -} +DH.prototype.getPrime = function (enc) { + return formatReturnValue(this.__prime, enc); +}; -Buffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) { - value = +value - offset = offset >>> 0 - if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000) - if (value < 0) value = 0xffffffff + value + 1 - this[offset] = (value >>> 24) - this[offset + 1] = (value >>> 16) - this[offset + 2] = (value >>> 8) - this[offset + 3] = (value & 0xff) - return offset + 4 -} +DH.prototype.getGenerator = function (enc) { + return formatReturnValue(this._gen, enc); +}; -function checkIEEE754 (buf, value, offset, ext, max, min) { - if (offset + ext > buf.length) throw new RangeError('Index out of range') - if (offset < 0) throw new RangeError('Index out of range') -} +DH.prototype.setGenerator = function (gen, enc) { + enc = enc || 'utf8'; + if (!Buffer.isBuffer(gen)) { + gen = new Buffer(gen, enc); + } + this.__gen = gen; + this._gen = new BN(gen); + return this; +}; -function writeFloat (buf, value, offset, littleEndian, noAssert) { - value = +value - offset = offset >>> 0 - if (!noAssert) { - checkIEEE754(buf, value, offset, 4, 3.4028234663852886e+38, -3.4028234663852886e+38) +function formatReturnValue(bn, enc) { + var buf = new Buffer(bn.toArray()); + if (!enc) { + return buf; + } else { + return buf.toString(enc); } - ieee754.write(buf, value, offset, littleEndian, 23, 4) - return offset + 4 } -Buffer.prototype.writeFloatLE = function writeFloatLE (value, offset, noAssert) { - return writeFloat(this, value, offset, true, noAssert) -} +}).call(this)}).call(this,require("buffer").Buffer) +},{"./generatePrime":145,"bn.js":86,"buffer":118,"miller-rabin":258,"randombytes":358}],145:[function(require,module,exports){ +var randomBytes = require('randombytes'); +module.exports = findPrime; +findPrime.simpleSieve = simpleSieve; +findPrime.fermatTest = fermatTest; +var BN = require('bn.js'); +var TWENTYFOUR = new BN(24); +var MillerRabin = require('miller-rabin'); +var millerRabin = new MillerRabin(); +var ONE = new BN(1); +var TWO = new BN(2); +var FIVE = new BN(5); +var SIXTEEN = new BN(16); +var EIGHT = new BN(8); +var TEN = new BN(10); +var THREE = new BN(3); +var SEVEN = new BN(7); +var ELEVEN = new BN(11); +var FOUR = new BN(4); +var TWELVE = new BN(12); +var primes = null; -Buffer.prototype.writeFloatBE = function writeFloatBE (value, offset, noAssert) { - return writeFloat(this, value, offset, false, noAssert) -} +function _getPrimes() { + if (primes !== null) + return primes; -function writeDouble (buf, value, offset, littleEndian, noAssert) { - value = +value - offset = offset >>> 0 - if (!noAssert) { - checkIEEE754(buf, value, offset, 8, 1.7976931348623157E+308, -1.7976931348623157E+308) - } - ieee754.write(buf, value, offset, littleEndian, 52, 8) - return offset + 8 -} + var limit = 0x100000; + var res = []; + res[0] = 2; + for (var i = 1, k = 3; k < limit; k += 2) { + var sqrt = Math.ceil(Math.sqrt(k)); + for (var j = 0; j < i && res[j] <= sqrt; j++) + if (k % res[j] === 0) + break; -Buffer.prototype.writeDoubleLE = function writeDoubleLE (value, offset, noAssert) { - return writeDouble(this, value, offset, true, noAssert) -} + if (i !== j && res[j] <= sqrt) + continue; -Buffer.prototype.writeDoubleBE = function writeDoubleBE (value, offset, noAssert) { - return writeDouble(this, value, offset, false, noAssert) + res[i++] = k; + } + primes = res; + return res; } -// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length) -Buffer.prototype.copy = function copy (target, targetStart, start, end) { - if (!Buffer.isBuffer(target)) throw new TypeError('argument should be a Buffer') - if (!start) start = 0 - if (!end && end !== 0) end = this.length - if (targetStart >= target.length) targetStart = target.length - if (!targetStart) targetStart = 0 - if (end > 0 && end < start) end = start - - // Copy 0 bytes; we're done - if (end === start) return 0 - if (target.length === 0 || this.length === 0) return 0 +function simpleSieve(p) { + var primes = _getPrimes(); - // Fatal error conditions - if (targetStart < 0) { - throw new RangeError('targetStart out of bounds') - } - if (start < 0 || start >= this.length) throw new RangeError('Index out of range') - if (end < 0) throw new RangeError('sourceEnd out of bounds') + for (var i = 0; i < primes.length; i++) + if (p.modn(primes[i]) === 0) { + if (p.cmpn(primes[i]) === 0) { + return true; + } else { + return false; + } + } - // Are we oob? - if (end > this.length) end = this.length - if (target.length - targetStart < end - start) { - end = target.length - targetStart + start - } + return true; +} - var len = end - start +function fermatTest(p) { + var red = BN.mont(p); + return TWO.toRed(red).redPow(p.subn(1)).fromRed().cmpn(1) === 0; +} - if (this === target && typeof Uint8Array.prototype.copyWithin === 'function') { - // Use built-in when available, missing from IE11 - this.copyWithin(targetStart, start, end) - } else if (this === target && start < targetStart && targetStart < end) { - // descending copy from end - for (var i = len - 1; i >= 0; --i) { - target[i + targetStart] = this[i + start] +function findPrime(bits, gen) { + if (bits < 16) { + // this is what openssl does + if (gen === 2 || gen === 5) { + return new BN([0x8c, 0x7b]); + } else { + return new BN([0x8c, 0x27]); } - } else { - Uint8Array.prototype.set.call( - target, - this.subarray(start, end), - targetStart - ) } + gen = new BN(gen); - return len -} + var num, n2; -// Usage: -// buffer.fill(number[, offset[, end]]) -// buffer.fill(buffer[, offset[, end]]) -// buffer.fill(string[, offset[, end]][, encoding]) -Buffer.prototype.fill = function fill (val, start, end, encoding) { - // Handle string cases: - if (typeof val === 'string') { - if (typeof start === 'string') { - encoding = start - start = 0 - end = this.length - } else if (typeof end === 'string') { - encoding = end - end = this.length + while (true) { + num = new BN(randomBytes(Math.ceil(bits / 8))); + while (num.bitLength() > bits) { + num.ishrn(1); } - if (encoding !== undefined && typeof encoding !== 'string') { - throw new TypeError('encoding must be a string') + if (num.isEven()) { + num.iadd(ONE); } - if (typeof encoding === 'string' && !Buffer.isEncoding(encoding)) { - throw new TypeError('Unknown encoding: ' + encoding) + if (!num.testn(1)) { + num.iadd(TWO); } - if (val.length === 1) { - var code = val.charCodeAt(0) - if ((encoding === 'utf8' && code < 128) || - encoding === 'latin1') { - // Fast path: If `val` fits into a single byte, use that numeric value. - val = code + if (!gen.cmp(TWO)) { + while (num.mod(TWENTYFOUR).cmp(ELEVEN)) { + num.iadd(FOUR); + } + } else if (!gen.cmp(FIVE)) { + while (num.mod(TEN).cmp(THREE)) { + num.iadd(FOUR); } } - } else if (typeof val === 'number') { - val = val & 255 - } - - // Invalid ranges are not set to a default, so can range check early. - if (start < 0 || this.length < start || this.length < end) { - throw new RangeError('Out of range index') - } - - if (end <= start) { - return this + n2 = num.shrn(1); + if (simpleSieve(n2) && simpleSieve(num) && + fermatTest(n2) && fermatTest(num) && + millerRabin.test(n2) && millerRabin.test(num)) { + return num; + } } - start = start >>> 0 - end = end === undefined ? this.length : end >>> 0 - - if (!val) val = 0 +} - var i - if (typeof val === 'number') { - for (i = start; i < end; ++i) { - this[i] = val - } - } else { - var bytes = Buffer.isBuffer(val) - ? val - : Buffer.from(val, encoding) - var len = bytes.length - if (len === 0) { - throw new TypeError('The value "' + val + - '" is invalid for argument "value"') - } - for (i = 0; i < end - start; ++i) { - this[i + start] = bytes[i % len] +},{"bn.js":86,"miller-rabin":258,"randombytes":358}],146:[function(require,module,exports){ +module.exports={ + "modp1": { + "gen": "02", + "prime": "ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a63a3620ffffffffffffffff" + }, + "modp2": { + "gen": "02", + "prime": "ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece65381ffffffffffffffff" + }, + "modp5": { + "gen": "02", + "prime": "ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca237327ffffffffffffffff" + }, + "modp14": { + "gen": "02", + "prime": "ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca18217c32905e462e36ce3be39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9de2bcbf6955817183995497cea956ae515d2261898fa051015728e5a8aacaa68ffffffffffffffff" + }, + "modp15": { + "gen": "02", + "prime": "ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca18217c32905e462e36ce3be39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9de2bcbf6955817183995497cea956ae515d2261898fa051015728e5a8aaac42dad33170d04507a33a85521abdf1cba64ecfb850458dbef0a8aea71575d060c7db3970f85a6e1e4c7abf5ae8cdb0933d71e8c94e04a25619dcee3d2261ad2ee6bf12ffa06d98a0864d87602733ec86a64521f2b18177b200cbbe117577a615d6c770988c0bad946e208e24fa074e5ab3143db5bfce0fd108e4b82d120a93ad2caffffffffffffffff" + }, + "modp16": { + "gen": "02", + "prime": "ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca18217c32905e462e36ce3be39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9de2bcbf6955817183995497cea956ae515d2261898fa051015728e5a8aaac42dad33170d04507a33a85521abdf1cba64ecfb850458dbef0a8aea71575d060c7db3970f85a6e1e4c7abf5ae8cdb0933d71e8c94e04a25619dcee3d2261ad2ee6bf12ffa06d98a0864d87602733ec86a64521f2b18177b200cbbe117577a615d6c770988c0bad946e208e24fa074e5ab3143db5bfce0fd108e4b82d120a92108011a723c12a787e6d788719a10bdba5b2699c327186af4e23c1a946834b6150bda2583e9ca2ad44ce8dbbbc2db04de8ef92e8efc141fbecaa6287c59474e6bc05d99b2964fa090c3a2233ba186515be7ed1f612970cee2d7afb81bdd762170481cd0069127d5b05aa993b4ea988d8fddc186ffb7dc90a6c08f4df435c934063199ffffffffffffffff" + }, + "modp17": { + "gen": "02", + "prime": "ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca18217c32905e462e36ce3be39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9de2bcbf6955817183995497cea956ae515d2261898fa051015728e5a8aaac42dad33170d04507a33a85521abdf1cba64ecfb850458dbef0a8aea71575d060c7db3970f85a6e1e4c7abf5ae8cdb0933d71e8c94e04a25619dcee3d2261ad2ee6bf12ffa06d98a0864d87602733ec86a64521f2b18177b200cbbe117577a615d6c770988c0bad946e208e24fa074e5ab3143db5bfce0fd108e4b82d120a92108011a723c12a787e6d788719a10bdba5b2699c327186af4e23c1a946834b6150bda2583e9ca2ad44ce8dbbbc2db04de8ef92e8efc141fbecaa6287c59474e6bc05d99b2964fa090c3a2233ba186515be7ed1f612970cee2d7afb81bdd762170481cd0069127d5b05aa993b4ea988d8fddc186ffb7dc90a6c08f4df435c93402849236c3fab4d27c7026c1d4dcb2602646dec9751e763dba37bdf8ff9406ad9e530ee5db382f413001aeb06a53ed9027d831179727b0865a8918da3edbebcf9b14ed44ce6cbaced4bb1bdb7f1447e6cc254b332051512bd7af426fb8f401378cd2bf5983ca01c64b92ecf032ea15d1721d03f482d7ce6e74fef6d55e702f46980c82b5a84031900b1c9e59e7c97fbec7e8f323a97a7e36cc88be0f1d45b7ff585ac54bd407b22b4154aacc8f6d7ebf48e1d814cc5ed20f8037e0a79715eef29be32806a1d58bb7c5da76f550aa3d8a1fbff0eb19ccb1a313d55cda56c9ec2ef29632387fe8d76e3c0468043e8f663f4860ee12bf2d5b0b7474d6e694f91e6dcc4024ffffffffffffffff" + }, + "modp18": { + "gen": "02", + "prime": "ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca18217c32905e462e36ce3be39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9de2bcbf6955817183995497cea956ae515d2261898fa051015728e5a8aaac42dad33170d04507a33a85521abdf1cba64ecfb850458dbef0a8aea71575d060c7db3970f85a6e1e4c7abf5ae8cdb0933d71e8c94e04a25619dcee3d2261ad2ee6bf12ffa06d98a0864d87602733ec86a64521f2b18177b200cbbe117577a615d6c770988c0bad946e208e24fa074e5ab3143db5bfce0fd108e4b82d120a92108011a723c12a787e6d788719a10bdba5b2699c327186af4e23c1a946834b6150bda2583e9ca2ad44ce8dbbbc2db04de8ef92e8efc141fbecaa6287c59474e6bc05d99b2964fa090c3a2233ba186515be7ed1f612970cee2d7afb81bdd762170481cd0069127d5b05aa993b4ea988d8fddc186ffb7dc90a6c08f4df435c93402849236c3fab4d27c7026c1d4dcb2602646dec9751e763dba37bdf8ff9406ad9e530ee5db382f413001aeb06a53ed9027d831179727b0865a8918da3edbebcf9b14ed44ce6cbaced4bb1bdb7f1447e6cc254b332051512bd7af426fb8f401378cd2bf5983ca01c64b92ecf032ea15d1721d03f482d7ce6e74fef6d55e702f46980c82b5a84031900b1c9e59e7c97fbec7e8f323a97a7e36cc88be0f1d45b7ff585ac54bd407b22b4154aacc8f6d7ebf48e1d814cc5ed20f8037e0a79715eef29be32806a1d58bb7c5da76f550aa3d8a1fbff0eb19ccb1a313d55cda56c9ec2ef29632387fe8d76e3c0468043e8f663f4860ee12bf2d5b0b7474d6e694f91e6dbe115974a3926f12fee5e438777cb6a932df8cd8bec4d073b931ba3bc832b68d9dd300741fa7bf8afc47ed2576f6936ba424663aab639c5ae4f5683423b4742bf1c978238f16cbe39d652de3fdb8befc848ad922222e04a4037c0713eb57a81a23f0c73473fc646cea306b4bcbc8862f8385ddfa9d4b7fa2c087e879683303ed5bdd3a062b3cf5b3a278a66d2a13f83f44f82ddf310ee074ab6a364597e899a0255dc164f31cc50846851df9ab48195ded7ea1b1d510bd7ee74d73faf36bc31ecfa268359046f4eb879f924009438b481c6cd7889a002ed5ee382bc9190da6fc026e479558e4475677e9aa9e3050e2765694dfc81f56e880b96e7160c980dd98edd3dfffffffffffffffff" } - } - - return this } +},{}],147:[function(require,module,exports){ +'use strict'; -// HELPER FUNCTIONS -// ================ - -var INVALID_BASE64_RE = /[^+/0-9A-Za-z-_]/g - -function base64clean (str) { - // Node takes equal signs as end of the Base64 encoding - str = str.split('=')[0] - // Node strips out invalid characters like \n and \t from the string, base64-js does not - str = str.trim().replace(INVALID_BASE64_RE, '') - // Node converts strings with length < 2 to '' - if (str.length < 2) return '' - // Node allows for non-padded base64 strings (missing trailing ===), base64-js does not - while (str.length % 4 !== 0) { - str = str + '=' - } - return str -} - -function toHex (n) { - if (n < 16) return '0' + n.toString(16) - return n.toString(16) -} +var elliptic = exports; -function utf8ToBytes (string, units) { - units = units || Infinity - var codePoint - var length = string.length - var leadSurrogate = null - var bytes = [] +elliptic.version = require('../package.json').version; +elliptic.utils = require('./elliptic/utils'); +elliptic.rand = require('brorand'); +elliptic.curve = require('./elliptic/curve'); +elliptic.curves = require('./elliptic/curves'); - for (var i = 0; i < length; ++i) { - codePoint = string.charCodeAt(i) +// Protocols +elliptic.ec = require('./elliptic/ec'); +elliptic.eddsa = require('./elliptic/eddsa'); - // is surrogate component - if (codePoint > 0xD7FF && codePoint < 0xE000) { - // last char was a lead - if (!leadSurrogate) { - // no lead yet - if (codePoint > 0xDBFF) { - // unexpected trail - if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) - continue - } else if (i + 1 === length) { - // unpaired lead - if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) - continue - } +},{"../package.json":162,"./elliptic/curve":150,"./elliptic/curves":153,"./elliptic/ec":154,"./elliptic/eddsa":157,"./elliptic/utils":161,"brorand":87}],148:[function(require,module,exports){ +'use strict'; - // valid lead - leadSurrogate = codePoint +var BN = require('bn.js'); +var utils = require('../utils'); +var getNAF = utils.getNAF; +var getJSF = utils.getJSF; +var assert = utils.assert; - continue - } +function BaseCurve(type, conf) { + this.type = type; + this.p = new BN(conf.p, 16); - // 2 leads in a row - if (codePoint < 0xDC00) { - if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) - leadSurrogate = codePoint - continue - } + // Use Montgomery, when there is no fast reduction for the prime + this.red = conf.prime ? BN.red(conf.prime) : BN.mont(this.p); - // valid surrogate pair - codePoint = (leadSurrogate - 0xD800 << 10 | codePoint - 0xDC00) + 0x10000 - } else if (leadSurrogate) { - // valid bmp char, but last char was a lead - if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) - } + // Useful for many curves + this.zero = new BN(0).toRed(this.red); + this.one = new BN(1).toRed(this.red); + this.two = new BN(2).toRed(this.red); - leadSurrogate = null + // Curve configuration, optional + this.n = conf.n && new BN(conf.n, 16); + this.g = conf.g && this.pointFromJSON(conf.g, conf.gRed); - // encode utf8 - if (codePoint < 0x80) { - if ((units -= 1) < 0) break - bytes.push(codePoint) - } else if (codePoint < 0x800) { - if ((units -= 2) < 0) break - bytes.push( - codePoint >> 0x6 | 0xC0, - codePoint & 0x3F | 0x80 - ) - } else if (codePoint < 0x10000) { - if ((units -= 3) < 0) break - bytes.push( - codePoint >> 0xC | 0xE0, - codePoint >> 0x6 & 0x3F | 0x80, - codePoint & 0x3F | 0x80 - ) - } else if (codePoint < 0x110000) { - if ((units -= 4) < 0) break - bytes.push( - codePoint >> 0x12 | 0xF0, - codePoint >> 0xC & 0x3F | 0x80, - codePoint >> 0x6 & 0x3F | 0x80, - codePoint & 0x3F | 0x80 - ) - } else { - throw new Error('Invalid code point') - } - } + // Temporary arrays + this._wnafT1 = new Array(4); + this._wnafT2 = new Array(4); + this._wnafT3 = new Array(4); + this._wnafT4 = new Array(4); - return bytes -} + this._bitLength = this.n ? this.n.bitLength() : 0; -function asciiToBytes (str) { - var byteArray = [] - for (var i = 0; i < str.length; ++i) { - // Node's code seems to be doing this and not & 0x7F.. - byteArray.push(str.charCodeAt(i) & 0xFF) + // Generalized Greg Maxwell's trick + var adjustCount = this.n && this.p.div(this.n); + if (!adjustCount || adjustCount.cmpn(100) > 0) { + this.redN = null; + } else { + this._maxwellTrick = true; + this.redN = this.n.toRed(this.red); } - return byteArray } +module.exports = BaseCurve; -function utf16leToBytes (str, units) { - var c, hi, lo - var byteArray = [] - for (var i = 0; i < str.length; ++i) { - if ((units -= 2) < 0) break +BaseCurve.prototype.point = function point() { + throw new Error('Not implemented'); +}; - c = str.charCodeAt(i) - hi = c >> 8 - lo = c % 256 - byteArray.push(lo) - byteArray.push(hi) - } +BaseCurve.prototype.validate = function validate() { + throw new Error('Not implemented'); +}; - return byteArray -} +BaseCurve.prototype._fixedNafMul = function _fixedNafMul(p, k) { + assert(p.precomputed); + var doubles = p._getDoubles(); -function base64ToBytes (str) { - return base64.toByteArray(base64clean(str)) -} + var naf = getNAF(k, 1, this._bitLength); + var I = (1 << (doubles.step + 1)) - (doubles.step % 2 === 0 ? 2 : 1); + I /= 3; -function blitBuffer (src, dst, offset, length) { - for (var i = 0; i < length; ++i) { - if ((i + offset >= dst.length) || (i >= src.length)) break - dst[i + offset] = src[i] + // Translate into more windowed form + var repr = []; + var j; + var nafW; + for (j = 0; j < naf.length; j += doubles.step) { + nafW = 0; + for (var l = j + doubles.step - 1; l >= j; l--) + nafW = (nafW << 1) + naf[l]; + repr.push(nafW); } - return i -} - -// ArrayBuffer or Uint8Array objects from other contexts (i.e. iframes) do not pass -// the `instanceof` check but they should be treated as of that type. -// See: https://github.com/feross/buffer/issues/166 -function isInstance (obj, type) { - return obj instanceof type || - (obj != null && obj.constructor != null && obj.constructor.name != null && - obj.constructor.name === type.name) -} -function numberIsNaN (obj) { - // For IE11 support - return obj !== obj // eslint-disable-line no-self-compare -} - -}).call(this)}).call(this,require("buffer").Buffer) -},{"base64-js":90,"buffer":137,"ieee754":255}],138:[function(require,module,exports){ -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - -module.exports = Stream; -var EE = require('events').EventEmitter; -var inherits = require('inherits'); + var a = this.jpoint(null, null, null); + var b = this.jpoint(null, null, null); + for (var i = I; i > 0; i--) { + for (j = 0; j < repr.length; j++) { + nafW = repr[j]; + if (nafW === i) + b = b.mixedAdd(doubles.points[j]); + else if (nafW === -i) + b = b.mixedAdd(doubles.points[j].neg()); + } + a = a.add(b); + } + return a.toP(); +}; -inherits(Stream, EE); -Stream.Readable = require('readable-stream/lib/_stream_readable.js'); -Stream.Writable = require('readable-stream/lib/_stream_writable.js'); -Stream.Duplex = require('readable-stream/lib/_stream_duplex.js'); -Stream.Transform = require('readable-stream/lib/_stream_transform.js'); -Stream.PassThrough = require('readable-stream/lib/_stream_passthrough.js'); -Stream.finished = require('readable-stream/lib/internal/streams/end-of-stream.js') -Stream.pipeline = require('readable-stream/lib/internal/streams/pipeline.js') +BaseCurve.prototype._wnafMul = function _wnafMul(p, k) { + var w = 4; -// Backwards-compat with node 0.4.x -Stream.Stream = Stream; + // Precompute window + var nafPoints = p._getNAFPoints(w); + w = nafPoints.wnd; + var wnd = nafPoints.points; + // Get NAF form + var naf = getNAF(k, w, this._bitLength); + // Add `this`*(N+1) for every w-NAF index + var acc = this.jpoint(null, null, null); + for (var i = naf.length - 1; i >= 0; i--) { + // Count zeroes + for (var l = 0; i >= 0 && naf[i] === 0; i--) + l++; + if (i >= 0) + l++; + acc = acc.dblp(l); -// old-style streams. Note that the pipe method (the only relevant -// part of this class) is overridden in the Readable class. + if (i < 0) + break; + var z = naf[i]; + assert(z !== 0); + if (p.type === 'affine') { + // J +- P + if (z > 0) + acc = acc.mixedAdd(wnd[(z - 1) >> 1]); + else + acc = acc.mixedAdd(wnd[(-z - 1) >> 1].neg()); + } else { + // J +- J + if (z > 0) + acc = acc.add(wnd[(z - 1) >> 1]); + else + acc = acc.add(wnd[(-z - 1) >> 1].neg()); + } + } + return p.type === 'affine' ? acc.toP() : acc; +}; -function Stream() { - EE.call(this); -} +BaseCurve.prototype._wnafMulAdd = function _wnafMulAdd(defW, + points, + coeffs, + len, + jacobianResult) { + var wndWidth = this._wnafT1; + var wnd = this._wnafT2; + var naf = this._wnafT3; -Stream.prototype.pipe = function(dest, options) { - var source = this; + // Fill all arrays + var max = 0; + var i; + var j; + var p; + for (i = 0; i < len; i++) { + p = points[i]; + var nafPoints = p._getNAFPoints(defW); + wndWidth[i] = nafPoints.wnd; + wnd[i] = nafPoints.points; + } - function ondata(chunk) { - if (dest.writable) { - if (false === dest.write(chunk) && source.pause) { - source.pause(); - } + // Comb small window NAFs + for (i = len - 1; i >= 1; i -= 2) { + var a = i - 1; + var b = i; + if (wndWidth[a] !== 1 || wndWidth[b] !== 1) { + naf[a] = getNAF(coeffs[a], wndWidth[a], this._bitLength); + naf[b] = getNAF(coeffs[b], wndWidth[b], this._bitLength); + max = Math.max(naf[a].length, max); + max = Math.max(naf[b].length, max); + continue; } - } - source.on('data', ondata); + var comb = [ + points[a], /* 1 */ + null, /* 3 */ + null, /* 5 */ + points[b], /* 7 */ + ]; - function ondrain() { - if (source.readable && source.resume) { - source.resume(); + // Try to avoid Projective points, if possible + if (points[a].y.cmp(points[b].y) === 0) { + comb[1] = points[a].add(points[b]); + comb[2] = points[a].toJ().mixedAdd(points[b].neg()); + } else if (points[a].y.cmp(points[b].y.redNeg()) === 0) { + comb[1] = points[a].toJ().mixedAdd(points[b]); + comb[2] = points[a].add(points[b].neg()); + } else { + comb[1] = points[a].toJ().mixedAdd(points[b]); + comb[2] = points[a].toJ().mixedAdd(points[b].neg()); } - } - - dest.on('drain', ondrain); - // If the 'end' option is not supplied, dest.end() will be called when - // source gets the 'end' or 'close' events. Only dest.end() once. - if (!dest._isStdio && (!options || options.end !== false)) { - source.on('end', onend); - source.on('close', onclose); - } + var index = [ + -3, /* -1 -1 */ + -1, /* -1 0 */ + -5, /* -1 1 */ + -7, /* 0 -1 */ + 0, /* 0 0 */ + 7, /* 0 1 */ + 5, /* 1 -1 */ + 1, /* 1 0 */ + 3, /* 1 1 */ + ]; - var didOnEnd = false; - function onend() { - if (didOnEnd) return; - didOnEnd = true; + var jsf = getJSF(coeffs[a], coeffs[b]); + max = Math.max(jsf[0].length, max); + naf[a] = new Array(max); + naf[b] = new Array(max); + for (j = 0; j < max; j++) { + var ja = jsf[0][j] | 0; + var jb = jsf[1][j] | 0; - dest.end(); + naf[a][j] = index[(ja + 1) * 3 + (jb + 1)]; + naf[b][j] = 0; + wnd[a] = comb; + } } + var acc = this.jpoint(null, null, null); + var tmp = this._wnafT4; + for (i = max; i >= 0; i--) { + var k = 0; - function onclose() { - if (didOnEnd) return; - didOnEnd = true; + while (i >= 0) { + var zero = true; + for (j = 0; j < len; j++) { + tmp[j] = naf[j][i] | 0; + if (tmp[j] !== 0) + zero = false; + } + if (!zero) + break; + k++; + i--; + } + if (i >= 0) + k++; + acc = acc.dblp(k); + if (i < 0) + break; - if (typeof dest.destroy === 'function') dest.destroy(); - } + for (j = 0; j < len; j++) { + var z = tmp[j]; + p; + if (z === 0) + continue; + else if (z > 0) + p = wnd[j][(z - 1) >> 1]; + else if (z < 0) + p = wnd[j][(-z - 1) >> 1].neg(); - // don't leave dangling pipes when there are errors. - function onerror(er) { - cleanup(); - if (EE.listenerCount(this, 'error') === 0) { - throw er; // Unhandled stream error in pipe. + if (p.type === 'affine') + acc = acc.mixedAdd(p); + else + acc = acc.add(p); } } + // Zeroify references + for (i = 0; i < len; i++) + wnd[i] = null; - source.on('error', onerror); - dest.on('error', onerror); + if (jacobianResult) + return acc; + else + return acc.toP(); +}; - // remove all the event listeners that were added. - function cleanup() { - source.removeListener('data', ondata); - dest.removeListener('drain', ondrain); +function BasePoint(curve, type) { + this.curve = curve; + this.type = type; + this.precomputed = null; +} +BaseCurve.BasePoint = BasePoint; - source.removeListener('end', onend); - source.removeListener('close', onclose); +BasePoint.prototype.eq = function eq(/*other*/) { + throw new Error('Not implemented'); +}; - source.removeListener('error', onerror); - dest.removeListener('error', onerror); +BasePoint.prototype.validate = function validate() { + return this.curve.validate(this); +}; - source.removeListener('end', cleanup); - source.removeListener('close', cleanup); +BaseCurve.prototype.decodePoint = function decodePoint(bytes, enc) { + bytes = utils.toArray(bytes, enc); - dest.removeListener('close', cleanup); - } + var len = this.p.byteLength(); - source.on('end', cleanup); - source.on('close', cleanup); + // uncompressed, hybrid-odd, hybrid-even + if ((bytes[0] === 0x04 || bytes[0] === 0x06 || bytes[0] === 0x07) && + bytes.length - 1 === 2 * len) { + if (bytes[0] === 0x06) + assert(bytes[bytes.length - 1] % 2 === 0); + else if (bytes[0] === 0x07) + assert(bytes[bytes.length - 1] % 2 === 1); - dest.on('close', cleanup); + var res = this.point(bytes.slice(1, 1 + len), + bytes.slice(1 + len, 1 + 2 * len)); - dest.emit('pipe', source); + return res; + } else if ((bytes[0] === 0x02 || bytes[0] === 0x03) && + bytes.length - 1 === len) { + return this.pointFromX(bytes.slice(1, 1 + len), bytes[0] === 0x03); + } + throw new Error('Unknown point format'); +}; - // Allow for unix-like usage: A.pipe(B).pipe(C) - return dest; +BasePoint.prototype.encodeCompressed = function encodeCompressed(enc) { + return this.encode(enc, true); }; -},{"events":211,"inherits":256,"readable-stream/lib/_stream_duplex.js":140,"readable-stream/lib/_stream_passthrough.js":141,"readable-stream/lib/_stream_readable.js":142,"readable-stream/lib/_stream_transform.js":143,"readable-stream/lib/_stream_writable.js":144,"readable-stream/lib/internal/streams/end-of-stream.js":148,"readable-stream/lib/internal/streams/pipeline.js":150}],139:[function(require,module,exports){ -arguments[4][121][0].apply(exports,arguments) -},{"dup":121}],140:[function(require,module,exports){ -arguments[4][122][0].apply(exports,arguments) -},{"./_stream_readable":142,"./_stream_writable":144,"_process":391,"dup":122,"inherits":256}],141:[function(require,module,exports){ -arguments[4][123][0].apply(exports,arguments) -},{"./_stream_transform":143,"dup":123,"inherits":256}],142:[function(require,module,exports){ -arguments[4][124][0].apply(exports,arguments) -},{"../errors":139,"./_stream_duplex":140,"./internal/streams/async_iterator":145,"./internal/streams/buffer_list":146,"./internal/streams/destroy":147,"./internal/streams/from":149,"./internal/streams/state":151,"./internal/streams/stream":152,"_process":391,"buffer":137,"dup":124,"events":211,"inherits":256,"string_decoder/":415,"util":93}],143:[function(require,module,exports){ -arguments[4][125][0].apply(exports,arguments) -},{"../errors":139,"./_stream_duplex":140,"dup":125,"inherits":256}],144:[function(require,module,exports){ -arguments[4][126][0].apply(exports,arguments) -},{"../errors":139,"./_stream_duplex":140,"./internal/streams/destroy":147,"./internal/streams/state":151,"./internal/streams/stream":152,"_process":391,"buffer":137,"dup":126,"inherits":256,"util-deprecate":416}],145:[function(require,module,exports){ -arguments[4][127][0].apply(exports,arguments) -},{"./end-of-stream":148,"_process":391,"dup":127}],146:[function(require,module,exports){ -arguments[4][128][0].apply(exports,arguments) -},{"buffer":137,"dup":128,"util":93}],147:[function(require,module,exports){ -arguments[4][129][0].apply(exports,arguments) -},{"_process":391,"dup":129}],148:[function(require,module,exports){ -arguments[4][130][0].apply(exports,arguments) -},{"../../../errors":139,"dup":130}],149:[function(require,module,exports){ -arguments[4][131][0].apply(exports,arguments) -},{"dup":131}],150:[function(require,module,exports){ -arguments[4][132][0].apply(exports,arguments) -},{"../../../errors":139,"./end-of-stream":148,"dup":132}],151:[function(require,module,exports){ -arguments[4][133][0].apply(exports,arguments) -},{"../../../errors":139,"dup":133}],152:[function(require,module,exports){ -arguments[4][134][0].apply(exports,arguments) -},{"dup":134,"events":211}],153:[function(require,module,exports){ -module.exports = function isBuffer(arg) { - return arg && typeof arg === 'object' - && typeof arg.copy === 'function' - && typeof arg.fill === 'function' - && typeof arg.readUInt8 === 'function'; -} -},{}],154:[function(require,module,exports){ -// Currently in sync with Node.js lib/internal/util/types.js -// https://github.com/nodejs/node/commit/112cc7c27551254aa2b17098fb774867f05ed0d9 +BasePoint.prototype._encode = function _encode(compact) { + var len = this.curve.p.byteLength(); + var x = this.getX().toArray('be', len); -'use strict'; + if (compact) + return [ this.getY().isEven() ? 0x02 : 0x03 ].concat(x); -var isArgumentsObject = require('is-arguments'); -var isGeneratorFunction = require('is-generator-function'); -var whichTypedArray = require('which-typed-array'); -var isTypedArray = require('is-typed-array'); + return [ 0x04 ].concat(x, this.getY().toArray('be', len)); +}; -function uncurryThis(f) { - return f.call.bind(f); -} +BasePoint.prototype.encode = function encode(enc, compact) { + return utils.encode(this._encode(compact), enc); +}; -var BigIntSupported = typeof BigInt !== 'undefined'; -var SymbolSupported = typeof Symbol !== 'undefined'; - -var ObjectToString = uncurryThis(Object.prototype.toString); - -var numberValue = uncurryThis(Number.prototype.valueOf); -var stringValue = uncurryThis(String.prototype.valueOf); -var booleanValue = uncurryThis(Boolean.prototype.valueOf); +BasePoint.prototype.precompute = function precompute(power) { + if (this.precomputed) + return this; -if (BigIntSupported) { - var bigIntValue = uncurryThis(BigInt.prototype.valueOf); -} + var precomputed = { + doubles: null, + naf: null, + beta: null, + }; + precomputed.naf = this._getNAFPoints(8); + precomputed.doubles = this._getDoubles(4, power); + precomputed.beta = this._getBeta(); + this.precomputed = precomputed; -if (SymbolSupported) { - var symbolValue = uncurryThis(Symbol.prototype.valueOf); -} + return this; +}; -function checkBoxedPrimitive(value, prototypeValueOf) { - if (typeof value !== 'object') { +BasePoint.prototype._hasDoubles = function _hasDoubles(k) { + if (!this.precomputed) return false; - } - try { - prototypeValueOf(value); - return true; - } catch(e) { + + var doubles = this.precomputed.doubles; + if (!doubles) return false; - } -} -exports.isArgumentsObject = isArgumentsObject; -exports.isGeneratorFunction = isGeneratorFunction; -exports.isTypedArray = isTypedArray; + return doubles.points.length >= Math.ceil((k.bitLength() + 1) / doubles.step); +}; -// Taken from here and modified for better browser support -// https://github.com/sindresorhus/p-is-promise/blob/cda35a513bda03f977ad5cde3a079d237e82d7ef/index.js -function isPromise(input) { - return ( - ( - typeof Promise !== 'undefined' && - input instanceof Promise - ) || - ( - input !== null && - typeof input === 'object' && - typeof input.then === 'function' && - typeof input.catch === 'function' - ) - ); -} -exports.isPromise = isPromise; +BasePoint.prototype._getDoubles = function _getDoubles(step, power) { + if (this.precomputed && this.precomputed.doubles) + return this.precomputed.doubles; -function isArrayBufferView(value) { - if (typeof ArrayBuffer !== 'undefined' && ArrayBuffer.isView) { - return ArrayBuffer.isView(value); + var doubles = [ this ]; + var acc = this; + for (var i = 0; i < power; i += step) { + for (var j = 0; j < step; j++) + acc = acc.dbl(); + doubles.push(acc); } + return { + step: step, + points: doubles, + }; +}; - return ( - isTypedArray(value) || - isDataView(value) - ); -} -exports.isArrayBufferView = isArrayBufferView; +BasePoint.prototype._getNAFPoints = function _getNAFPoints(wnd) { + if (this.precomputed && this.precomputed.naf) + return this.precomputed.naf; + var res = [ this ]; + var max = (1 << wnd) - 1; + var dbl = max === 1 ? null : this.dbl(); + for (var i = 1; i < max; i++) + res[i] = res[i - 1].add(dbl); + return { + wnd: wnd, + points: res, + }; +}; -function isUint8Array(value) { - return whichTypedArray(value) === 'Uint8Array'; -} -exports.isUint8Array = isUint8Array; +BasePoint.prototype._getBeta = function _getBeta() { + return null; +}; -function isUint8ClampedArray(value) { - return whichTypedArray(value) === 'Uint8ClampedArray'; -} -exports.isUint8ClampedArray = isUint8ClampedArray; +BasePoint.prototype.dblp = function dblp(k) { + var r = this; + for (var i = 0; i < k; i++) + r = r.dbl(); + return r; +}; -function isUint16Array(value) { - return whichTypedArray(value) === 'Uint16Array'; -} -exports.isUint16Array = isUint16Array; +},{"../utils":161,"bn.js":86}],149:[function(require,module,exports){ +'use strict'; -function isUint32Array(value) { - return whichTypedArray(value) === 'Uint32Array'; -} -exports.isUint32Array = isUint32Array; +var utils = require('../utils'); +var BN = require('bn.js'); +var inherits = require('inherits'); +var Base = require('./base'); -function isInt8Array(value) { - return whichTypedArray(value) === 'Int8Array'; -} -exports.isInt8Array = isInt8Array; +var assert = utils.assert; -function isInt16Array(value) { - return whichTypedArray(value) === 'Int16Array'; -} -exports.isInt16Array = isInt16Array; +function EdwardsCurve(conf) { + // NOTE: Important as we are creating point in Base.call() + this.twisted = (conf.a | 0) !== 1; + this.mOneA = this.twisted && (conf.a | 0) === -1; + this.extended = this.mOneA; -function isInt32Array(value) { - return whichTypedArray(value) === 'Int32Array'; -} -exports.isInt32Array = isInt32Array; + Base.call(this, 'edwards', conf); -function isFloat32Array(value) { - return whichTypedArray(value) === 'Float32Array'; -} -exports.isFloat32Array = isFloat32Array; + this.a = new BN(conf.a, 16).umod(this.red.m); + this.a = this.a.toRed(this.red); + this.c = new BN(conf.c, 16).toRed(this.red); + this.c2 = this.c.redSqr(); + this.d = new BN(conf.d, 16).toRed(this.red); + this.dd = this.d.redAdd(this.d); -function isFloat64Array(value) { - return whichTypedArray(value) === 'Float64Array'; + assert(!this.twisted || this.c.fromRed().cmpn(1) === 0); + this.oneC = (conf.c | 0) === 1; } -exports.isFloat64Array = isFloat64Array; +inherits(EdwardsCurve, Base); +module.exports = EdwardsCurve; -function isBigInt64Array(value) { - return whichTypedArray(value) === 'BigInt64Array'; -} -exports.isBigInt64Array = isBigInt64Array; +EdwardsCurve.prototype._mulA = function _mulA(num) { + if (this.mOneA) + return num.redNeg(); + else + return this.a.redMul(num); +}; -function isBigUint64Array(value) { - return whichTypedArray(value) === 'BigUint64Array'; -} -exports.isBigUint64Array = isBigUint64Array; +EdwardsCurve.prototype._mulC = function _mulC(num) { + if (this.oneC) + return num; + else + return this.c.redMul(num); +}; -function isMapToString(value) { - return ObjectToString(value) === '[object Map]'; -} -isMapToString.working = ( - typeof Map !== 'undefined' && - isMapToString(new Map()) -); +// Just for compatibility with Short curve +EdwardsCurve.prototype.jpoint = function jpoint(x, y, z, t) { + return this.point(x, y, z, t); +}; -function isMap(value) { - if (typeof Map === 'undefined') { - return false; - } +EdwardsCurve.prototype.pointFromX = function pointFromX(x, odd) { + x = new BN(x, 16); + if (!x.red) + x = x.toRed(this.red); - return isMapToString.working - ? isMapToString(value) - : value instanceof Map; -} -exports.isMap = isMap; + var x2 = x.redSqr(); + var rhs = this.c2.redSub(this.a.redMul(x2)); + var lhs = this.one.redSub(this.c2.redMul(this.d).redMul(x2)); -function isSetToString(value) { - return ObjectToString(value) === '[object Set]'; -} -isSetToString.working = ( - typeof Set !== 'undefined' && - isSetToString(new Set()) -); -function isSet(value) { - if (typeof Set === 'undefined') { - return false; - } + var y2 = rhs.redMul(lhs.redInvm()); + var y = y2.redSqrt(); + if (y.redSqr().redSub(y2).cmp(this.zero) !== 0) + throw new Error('invalid point'); - return isSetToString.working - ? isSetToString(value) - : value instanceof Set; -} -exports.isSet = isSet; + var isOdd = y.fromRed().isOdd(); + if (odd && !isOdd || !odd && isOdd) + y = y.redNeg(); -function isWeakMapToString(value) { - return ObjectToString(value) === '[object WeakMap]'; -} -isWeakMapToString.working = ( - typeof WeakMap !== 'undefined' && - isWeakMapToString(new WeakMap()) -); -function isWeakMap(value) { - if (typeof WeakMap === 'undefined') { - return false; - } + return this.point(x, y); +}; - return isWeakMapToString.working - ? isWeakMapToString(value) - : value instanceof WeakMap; -} -exports.isWeakMap = isWeakMap; +EdwardsCurve.prototype.pointFromY = function pointFromY(y, odd) { + y = new BN(y, 16); + if (!y.red) + y = y.toRed(this.red); -function isWeakSetToString(value) { - return ObjectToString(value) === '[object WeakSet]'; -} -isWeakSetToString.working = ( - typeof WeakSet !== 'undefined' && - isWeakSetToString(new WeakSet()) -); -function isWeakSet(value) { - return isWeakSetToString(value); -} -exports.isWeakSet = isWeakSet; + // x^2 = (y^2 - c^2) / (c^2 d y^2 - a) + var y2 = y.redSqr(); + var lhs = y2.redSub(this.c2); + var rhs = y2.redMul(this.d).redMul(this.c2).redSub(this.a); + var x2 = lhs.redMul(rhs.redInvm()); -function isArrayBufferToString(value) { - return ObjectToString(value) === '[object ArrayBuffer]'; -} -isArrayBufferToString.working = ( - typeof ArrayBuffer !== 'undefined' && - isArrayBufferToString(new ArrayBuffer()) -); -function isArrayBuffer(value) { - if (typeof ArrayBuffer === 'undefined') { - return false; + if (x2.cmp(this.zero) === 0) { + if (odd) + throw new Error('invalid point'); + else + return this.point(this.zero, y); } - return isArrayBufferToString.working - ? isArrayBufferToString(value) - : value instanceof ArrayBuffer; -} -exports.isArrayBuffer = isArrayBuffer; - -function isDataViewToString(value) { - return ObjectToString(value) === '[object DataView]'; -} -isDataViewToString.working = ( - typeof ArrayBuffer !== 'undefined' && - typeof DataView !== 'undefined' && - isDataViewToString(new DataView(new ArrayBuffer(1), 0, 1)) -); -function isDataView(value) { - if (typeof DataView === 'undefined') { - return false; - } + var x = x2.redSqrt(); + if (x.redSqr().redSub(x2).cmp(this.zero) !== 0) + throw new Error('invalid point'); - return isDataViewToString.working - ? isDataViewToString(value) - : value instanceof DataView; -} -exports.isDataView = isDataView; + if (x.fromRed().isOdd() !== odd) + x = x.redNeg(); -// Store a copy of SharedArrayBuffer in case it's deleted elsewhere -var SharedArrayBufferCopy = typeof SharedArrayBuffer !== 'undefined' ? SharedArrayBuffer : undefined; -function isSharedArrayBufferToString(value) { - return ObjectToString(value) === '[object SharedArrayBuffer]'; -} -function isSharedArrayBuffer(value) { - if (typeof SharedArrayBufferCopy === 'undefined') { - return false; - } + return this.point(x, y); +}; - if (typeof isSharedArrayBufferToString.working === 'undefined') { - isSharedArrayBufferToString.working = isSharedArrayBufferToString(new SharedArrayBufferCopy()); - } +EdwardsCurve.prototype.validate = function validate(point) { + if (point.isInfinity()) + return true; - return isSharedArrayBufferToString.working - ? isSharedArrayBufferToString(value) - : value instanceof SharedArrayBufferCopy; -} -exports.isSharedArrayBuffer = isSharedArrayBuffer; + // Curve: A * X^2 + Y^2 = C^2 * (1 + D * X^2 * Y^2) + point.normalize(); -function isAsyncFunction(value) { - return ObjectToString(value) === '[object AsyncFunction]'; -} -exports.isAsyncFunction = isAsyncFunction; + var x2 = point.x.redSqr(); + var y2 = point.y.redSqr(); + var lhs = x2.redMul(this.a).redAdd(y2); + var rhs = this.c2.redMul(this.one.redAdd(this.d.redMul(x2).redMul(y2))); -function isMapIterator(value) { - return ObjectToString(value) === '[object Map Iterator]'; -} -exports.isMapIterator = isMapIterator; + return lhs.cmp(rhs) === 0; +}; -function isSetIterator(value) { - return ObjectToString(value) === '[object Set Iterator]'; -} -exports.isSetIterator = isSetIterator; +function Point(curve, x, y, z, t) { + Base.BasePoint.call(this, curve, 'projective'); + if (x === null && y === null && z === null) { + this.x = this.curve.zero; + this.y = this.curve.one; + this.z = this.curve.one; + this.t = this.curve.zero; + this.zOne = true; + } else { + this.x = new BN(x, 16); + this.y = new BN(y, 16); + this.z = z ? new BN(z, 16) : this.curve.one; + this.t = t && new BN(t, 16); + if (!this.x.red) + this.x = this.x.toRed(this.curve.red); + if (!this.y.red) + this.y = this.y.toRed(this.curve.red); + if (!this.z.red) + this.z = this.z.toRed(this.curve.red); + if (this.t && !this.t.red) + this.t = this.t.toRed(this.curve.red); + this.zOne = this.z === this.curve.one; -function isGeneratorObject(value) { - return ObjectToString(value) === '[object Generator]'; + // Use extended coordinates + if (this.curve.extended && !this.t) { + this.t = this.x.redMul(this.y); + if (!this.zOne) + this.t = this.t.redMul(this.z.redInvm()); + } + } } -exports.isGeneratorObject = isGeneratorObject; +inherits(Point, Base.BasePoint); -function isWebAssemblyCompiledModule(value) { - return ObjectToString(value) === '[object WebAssembly.Module]'; -} -exports.isWebAssemblyCompiledModule = isWebAssemblyCompiledModule; +EdwardsCurve.prototype.pointFromJSON = function pointFromJSON(obj) { + return Point.fromJSON(this, obj); +}; -function isNumberObject(value) { - return checkBoxedPrimitive(value, numberValue); -} -exports.isNumberObject = isNumberObject; +EdwardsCurve.prototype.point = function point(x, y, z, t) { + return new Point(this, x, y, z, t); +}; -function isStringObject(value) { - return checkBoxedPrimitive(value, stringValue); -} -exports.isStringObject = isStringObject; +Point.fromJSON = function fromJSON(curve, obj) { + return new Point(curve, obj[0], obj[1], obj[2]); +}; -function isBooleanObject(value) { - return checkBoxedPrimitive(value, booleanValue); -} -exports.isBooleanObject = isBooleanObject; +Point.prototype.inspect = function inspect() { + if (this.isInfinity()) + return ''; + return ''; +}; -function isBigIntObject(value) { - return BigIntSupported && checkBoxedPrimitive(value, bigIntValue); -} -exports.isBigIntObject = isBigIntObject; +Point.prototype.isInfinity = function isInfinity() { + // XXX This code assumes that zero is always zero in red + return this.x.cmpn(0) === 0 && + (this.y.cmp(this.z) === 0 || + (this.zOne && this.y.cmp(this.curve.c) === 0)); +}; -function isSymbolObject(value) { - return SymbolSupported && checkBoxedPrimitive(value, symbolValue); -} -exports.isSymbolObject = isSymbolObject; +Point.prototype._extDbl = function _extDbl() { + // hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html + // #doubling-dbl-2008-hwcd + // 4M + 4S -function isBoxedPrimitive(value) { - return ( - isNumberObject(value) || - isStringObject(value) || - isBooleanObject(value) || - isBigIntObject(value) || - isSymbolObject(value) - ); -} -exports.isBoxedPrimitive = isBoxedPrimitive; + // A = X1^2 + var a = this.x.redSqr(); + // B = Y1^2 + var b = this.y.redSqr(); + // C = 2 * Z1^2 + var c = this.z.redSqr(); + c = c.redIAdd(c); + // D = a * A + var d = this.curve._mulA(a); + // E = (X1 + Y1)^2 - A - B + var e = this.x.redAdd(this.y).redSqr().redISub(a).redISub(b); + // G = D + B + var g = d.redAdd(b); + // F = G - C + var f = g.redSub(c); + // H = D - B + var h = d.redSub(b); + // X3 = E * F + var nx = e.redMul(f); + // Y3 = G * H + var ny = g.redMul(h); + // T3 = E * H + var nt = e.redMul(h); + // Z3 = F * G + var nz = f.redMul(g); + return this.curve.point(nx, ny, nz, nt); +}; -function isAnyArrayBuffer(value) { - return typeof Uint8Array !== 'undefined' && ( - isArrayBuffer(value) || - isSharedArrayBuffer(value) - ); -} -exports.isAnyArrayBuffer = isAnyArrayBuffer; +Point.prototype._projDbl = function _projDbl() { + // hyperelliptic.org/EFD/g1p/auto-twisted-projective.html + // #doubling-dbl-2008-bbjlp + // #doubling-dbl-2007-bl + // and others + // Generally 3M + 4S or 2M + 4S -['isProxy', 'isExternal', 'isModuleNamespaceObject'].forEach(function(method) { - Object.defineProperty(exports, method, { - enumerable: false, - value: function() { - throw new Error(method + ' is not supported in userland'); - } - }); -}); + // B = (X1 + Y1)^2 + var b = this.x.redAdd(this.y).redSqr(); + // C = X1^2 + var c = this.x.redSqr(); + // D = Y1^2 + var d = this.y.redSqr(); -},{"is-arguments":258,"is-generator-function":261,"is-typed-array":262,"which-typed-array":417}],155:[function(require,module,exports){ -(function (process){(function (){ -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - -var getOwnPropertyDescriptors = Object.getOwnPropertyDescriptors || - function getOwnPropertyDescriptors(obj) { - var keys = Object.keys(obj); - var descriptors = {}; - for (var i = 0; i < keys.length; i++) { - descriptors[keys[i]] = Object.getOwnPropertyDescriptor(obj, keys[i]); - } - return descriptors; - }; - -var formatRegExp = /%[sdj%]/g; -exports.format = function(f) { - if (!isString(f)) { - var objects = []; - for (var i = 0; i < arguments.length; i++) { - objects.push(inspect(arguments[i])); - } - return objects.join(' '); - } - - var i = 1; - var args = arguments; - var len = args.length; - var str = String(f).replace(formatRegExp, function(x) { - if (x === '%%') return '%'; - if (i >= len) return x; - switch (x) { - case '%s': return String(args[i++]); - case '%d': return Number(args[i++]); - case '%j': - try { - return JSON.stringify(args[i++]); - } catch (_) { - return '[Circular]'; - } - default: - return x; - } - }); - for (var x = args[i]; i < len; x = args[++i]) { - if (isNull(x) || !isObject(x)) { - str += ' ' + x; + var nx; + var ny; + var nz; + var e; + var h; + var j; + if (this.curve.twisted) { + // E = a * C + e = this.curve._mulA(c); + // F = E + D + var f = e.redAdd(d); + if (this.zOne) { + // X3 = (B - C - D) * (F - 2) + nx = b.redSub(c).redSub(d).redMul(f.redSub(this.curve.two)); + // Y3 = F * (E - D) + ny = f.redMul(e.redSub(d)); + // Z3 = F^2 - 2 * F + nz = f.redSqr().redSub(f).redSub(f); } else { - str += ' ' + inspect(x); + // H = Z1^2 + h = this.z.redSqr(); + // J = F - 2 * H + j = f.redSub(h).redISub(h); + // X3 = (B-C-D)*J + nx = b.redSub(c).redISub(d).redMul(j); + // Y3 = F * (E - D) + ny = f.redMul(e.redSub(d)); + // Z3 = F * J + nz = f.redMul(j); } + } else { + // E = C + D + e = c.redAdd(d); + // H = (c * Z1)^2 + h = this.curve._mulC(this.z).redSqr(); + // J = E - 2 * H + j = e.redSub(h).redSub(h); + // X3 = c * (B - E) * J + nx = this.curve._mulC(b.redISub(e)).redMul(j); + // Y3 = c * E * (C - D) + ny = this.curve._mulC(e).redMul(c.redISub(d)); + // Z3 = E * J + nz = e.redMul(j); } - return str; + return this.curve.point(nx, ny, nz); }; +Point.prototype.dbl = function dbl() { + if (this.isInfinity()) + return this; -// Mark that a method should not be used. -// Returns a modified function which warns once by default. -// If --no-deprecation is set, then it is a no-op. -exports.deprecate = function(fn, msg) { - if (typeof process !== 'undefined' && process.noDeprecation === true) { - return fn; - } - - // Allow for deprecating things in the process of starting up. - if (typeof process === 'undefined') { - return function() { - return exports.deprecate(fn, msg).apply(this, arguments); - }; - } + // Double in extended coordinates + if (this.curve.extended) + return this._extDbl(); + else + return this._projDbl(); +}; - var warned = false; - function deprecated() { - if (!warned) { - if (process.throwDeprecation) { - throw new Error(msg); - } else if (process.traceDeprecation) { - console.trace(msg); - } else { - console.error(msg); - } - warned = true; - } - return fn.apply(this, arguments); - } +Point.prototype._extAdd = function _extAdd(p) { + // hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html + // #addition-add-2008-hwcd-3 + // 8M - return deprecated; + // A = (Y1 - X1) * (Y2 - X2) + var a = this.y.redSub(this.x).redMul(p.y.redSub(p.x)); + // B = (Y1 + X1) * (Y2 + X2) + var b = this.y.redAdd(this.x).redMul(p.y.redAdd(p.x)); + // C = T1 * k * T2 + var c = this.t.redMul(this.curve.dd).redMul(p.t); + // D = Z1 * 2 * Z2 + var d = this.z.redMul(p.z.redAdd(p.z)); + // E = B - A + var e = b.redSub(a); + // F = D - C + var f = d.redSub(c); + // G = D + C + var g = d.redAdd(c); + // H = B + A + var h = b.redAdd(a); + // X3 = E * F + var nx = e.redMul(f); + // Y3 = G * H + var ny = g.redMul(h); + // T3 = E * H + var nt = e.redMul(h); + // Z3 = F * G + var nz = f.redMul(g); + return this.curve.point(nx, ny, nz, nt); }; +Point.prototype._projAdd = function _projAdd(p) { + // hyperelliptic.org/EFD/g1p/auto-twisted-projective.html + // #addition-add-2008-bbjlp + // #addition-add-2007-bl + // 10M + 1S -var debugs = {}; -var debugEnvRegex = /^$/; - -if (process.env.NODE_DEBUG) { - var debugEnv = process.env.NODE_DEBUG; - debugEnv = debugEnv.replace(/[|\\{}()[\]^$+?.]/g, '\\$&') - .replace(/\*/g, '.*') - .replace(/,/g, '$|^') - .toUpperCase(); - debugEnvRegex = new RegExp('^' + debugEnv + '$', 'i'); -} -exports.debuglog = function(set) { - set = set.toUpperCase(); - if (!debugs[set]) { - if (debugEnvRegex.test(set)) { - var pid = process.pid; - debugs[set] = function() { - var msg = exports.format.apply(exports, arguments); - console.error('%s %d: %s', set, pid, msg); - }; - } else { - debugs[set] = function() {}; - } + // A = Z1 * Z2 + var a = this.z.redMul(p.z); + // B = A^2 + var b = a.redSqr(); + // C = X1 * X2 + var c = this.x.redMul(p.x); + // D = Y1 * Y2 + var d = this.y.redMul(p.y); + // E = d * C * D + var e = this.curve.d.redMul(c).redMul(d); + // F = B - E + var f = b.redSub(e); + // G = B + E + var g = b.redAdd(e); + // X3 = A * F * ((X1 + Y1) * (X2 + Y2) - C - D) + var tmp = this.x.redAdd(this.y).redMul(p.x.redAdd(p.y)).redISub(c).redISub(d); + var nx = a.redMul(f).redMul(tmp); + var ny; + var nz; + if (this.curve.twisted) { + // Y3 = A * G * (D - a * C) + ny = a.redMul(g).redMul(d.redSub(this.curve._mulA(c))); + // Z3 = F * G + nz = f.redMul(g); + } else { + // Y3 = A * G * (D - C) + ny = a.redMul(g).redMul(d.redSub(c)); + // Z3 = c * F * G + nz = this.curve._mulC(f).redMul(g); } - return debugs[set]; + return this.curve.point(nx, ny, nz); }; +Point.prototype.add = function add(p) { + if (this.isInfinity()) + return p; + if (p.isInfinity()) + return this; -/** - * Echos the value of a value. Trys to print the value out - * in the best way possible given the different types. - * - * @param {Object} obj The object to print out. - * @param {Object} opts Optional options object that alters the output. - */ -/* legacy: obj, showHidden, depth, colors*/ -function inspect(obj, opts) { - // default options - var ctx = { - seen: [], - stylize: stylizeNoColor - }; - // legacy... - if (arguments.length >= 3) ctx.depth = arguments[2]; - if (arguments.length >= 4) ctx.colors = arguments[3]; - if (isBoolean(opts)) { - // legacy... - ctx.showHidden = opts; - } else if (opts) { - // got an "options" object - exports._extend(ctx, opts); - } - // set default options - if (isUndefined(ctx.showHidden)) ctx.showHidden = false; - if (isUndefined(ctx.depth)) ctx.depth = 2; - if (isUndefined(ctx.colors)) ctx.colors = false; - if (isUndefined(ctx.customInspect)) ctx.customInspect = true; - if (ctx.colors) ctx.stylize = stylizeWithColor; - return formatValue(ctx, obj, ctx.depth); -} -exports.inspect = inspect; + if (this.curve.extended) + return this._extAdd(p); + else + return this._projAdd(p); +}; +Point.prototype.mul = function mul(k) { + if (this._hasDoubles(k)) + return this.curve._fixedNafMul(this, k); + else + return this.curve._wnafMul(this, k); +}; -// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics -inspect.colors = { - 'bold' : [1, 22], - 'italic' : [3, 23], - 'underline' : [4, 24], - 'inverse' : [7, 27], - 'white' : [37, 39], - 'grey' : [90, 39], - 'black' : [30, 39], - 'blue' : [34, 39], - 'cyan' : [36, 39], - 'green' : [32, 39], - 'magenta' : [35, 39], - 'red' : [31, 39], - 'yellow' : [33, 39] +Point.prototype.mulAdd = function mulAdd(k1, p, k2) { + return this.curve._wnafMulAdd(1, [ this, p ], [ k1, k2 ], 2, false); }; -// Don't use 'blue' not visible on cmd.exe -inspect.styles = { - 'special': 'cyan', - 'number': 'yellow', - 'boolean': 'yellow', - 'undefined': 'grey', - 'null': 'bold', - 'string': 'green', - 'date': 'magenta', - // "name": intentionally not styling - 'regexp': 'red' +Point.prototype.jmulAdd = function jmulAdd(k1, p, k2) { + return this.curve._wnafMulAdd(1, [ this, p ], [ k1, k2 ], 2, true); }; +Point.prototype.normalize = function normalize() { + if (this.zOne) + return this; -function stylizeWithColor(str, styleType) { - var style = inspect.styles[styleType]; + // Normalize coordinates + var zi = this.z.redInvm(); + this.x = this.x.redMul(zi); + this.y = this.y.redMul(zi); + if (this.t) + this.t = this.t.redMul(zi); + this.z = this.curve.one; + this.zOne = true; + return this; +}; - if (style) { - return '\u001b[' + inspect.colors[style][0] + 'm' + str + - '\u001b[' + inspect.colors[style][1] + 'm'; - } else { - return str; - } -} +Point.prototype.neg = function neg() { + return this.curve.point(this.x.redNeg(), + this.y, + this.z, + this.t && this.t.redNeg()); +}; +Point.prototype.getX = function getX() { + this.normalize(); + return this.x.fromRed(); +}; -function stylizeNoColor(str, styleType) { - return str; -} +Point.prototype.getY = function getY() { + this.normalize(); + return this.y.fromRed(); +}; +Point.prototype.eq = function eq(other) { + return this === other || + this.getX().cmp(other.getX()) === 0 && + this.getY().cmp(other.getY()) === 0; +}; -function arrayToHash(array) { - var hash = {}; +Point.prototype.eqXToP = function eqXToP(x) { + var rx = x.toRed(this.curve.red).redMul(this.z); + if (this.x.cmp(rx) === 0) + return true; - array.forEach(function(val, idx) { - hash[val] = true; - }); + var xc = x.clone(); + var t = this.curve.redN.redMul(this.z); + for (;;) { + xc.iadd(this.curve.n); + if (xc.cmp(this.curve.p) >= 0) + return false; - return hash; -} + rx.redIAdd(t); + if (this.x.cmp(rx) === 0) + return true; + } +}; +// Compatibility with BaseCurve +Point.prototype.toP = Point.prototype.normalize; +Point.prototype.mixedAdd = Point.prototype.add; -function formatValue(ctx, value, recurseTimes) { - // Provide a hook for user-specified inspect functions. - // Check that value is an object with an inspect function on it - if (ctx.customInspect && - value && - isFunction(value.inspect) && - // Filter out the util module, it's inspect function is special - value.inspect !== exports.inspect && - // Also filter out any prototype objects using the circular check. - !(value.constructor && value.constructor.prototype === value)) { - var ret = value.inspect(recurseTimes, ctx); - if (!isString(ret)) { - ret = formatValue(ctx, ret, recurseTimes); - } - return ret; - } +},{"../utils":161,"./base":148,"bn.js":86,"inherits":200}],150:[function(require,module,exports){ +'use strict'; - // Primitive types cannot have properties - var primitive = formatPrimitive(ctx, value); - if (primitive) { - return primitive; - } +var curve = exports; - // Look up the keys of the object. - var keys = Object.keys(value); - var visibleKeys = arrayToHash(keys); +curve.base = require('./base'); +curve.short = require('./short'); +curve.mont = require('./mont'); +curve.edwards = require('./edwards'); - if (ctx.showHidden) { - keys = Object.getOwnPropertyNames(value); - } +},{"./base":148,"./edwards":149,"./mont":151,"./short":152}],151:[function(require,module,exports){ +'use strict'; - // IE doesn't make error fields non-enumerable - // http://msdn.microsoft.com/en-us/library/ie/dww52sbt(v=vs.94).aspx - if (isError(value) - && (keys.indexOf('message') >= 0 || keys.indexOf('description') >= 0)) { - return formatError(value); - } +var BN = require('bn.js'); +var inherits = require('inherits'); +var Base = require('./base'); - // Some type of object without properties can be shortcutted. - if (keys.length === 0) { - if (isFunction(value)) { - var name = value.name ? ': ' + value.name : ''; - return ctx.stylize('[Function' + name + ']', 'special'); - } - if (isRegExp(value)) { - return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); - } - if (isDate(value)) { - return ctx.stylize(Date.prototype.toString.call(value), 'date'); - } - if (isError(value)) { - return formatError(value); - } - } +var utils = require('../utils'); - var base = '', array = false, braces = ['{', '}']; +function MontCurve(conf) { + Base.call(this, 'mont', conf); - // Make Array say that they are Array - if (isArray(value)) { - array = true; - braces = ['[', ']']; - } + this.a = new BN(conf.a, 16).toRed(this.red); + this.b = new BN(conf.b, 16).toRed(this.red); + this.i4 = new BN(4).toRed(this.red).redInvm(); + this.two = new BN(2).toRed(this.red); + this.a24 = this.i4.redMul(this.a.redAdd(this.two)); +} +inherits(MontCurve, Base); +module.exports = MontCurve; - // Make functions say that they are functions - if (isFunction(value)) { - var n = value.name ? ': ' + value.name : ''; - base = ' [Function' + n + ']'; - } +MontCurve.prototype.validate = function validate(point) { + var x = point.normalize().x; + var x2 = x.redSqr(); + var rhs = x2.redMul(x).redAdd(x2.redMul(this.a)).redAdd(x); + var y = rhs.redSqrt(); - // Make RegExps say that they are RegExps - if (isRegExp(value)) { - base = ' ' + RegExp.prototype.toString.call(value); - } + return y.redSqr().cmp(rhs) === 0; +}; - // Make dates with properties first say the date - if (isDate(value)) { - base = ' ' + Date.prototype.toUTCString.call(value); +function Point(curve, x, z) { + Base.BasePoint.call(this, curve, 'projective'); + if (x === null && z === null) { + this.x = this.curve.one; + this.z = this.curve.zero; + } else { + this.x = new BN(x, 16); + this.z = new BN(z, 16); + if (!this.x.red) + this.x = this.x.toRed(this.curve.red); + if (!this.z.red) + this.z = this.z.toRed(this.curve.red); } +} +inherits(Point, Base.BasePoint); - // Make error with message first say the error - if (isError(value)) { - base = ' ' + formatError(value); - } +MontCurve.prototype.decodePoint = function decodePoint(bytes, enc) { + return this.point(utils.toArray(bytes, enc), 1); +}; - if (keys.length === 0 && (!array || value.length == 0)) { - return braces[0] + base + braces[1]; - } +MontCurve.prototype.point = function point(x, z) { + return new Point(this, x, z); +}; - if (recurseTimes < 0) { - if (isRegExp(value)) { - return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); - } else { - return ctx.stylize('[Object]', 'special'); - } - } +MontCurve.prototype.pointFromJSON = function pointFromJSON(obj) { + return Point.fromJSON(this, obj); +}; - ctx.seen.push(value); +Point.prototype.precompute = function precompute() { + // No-op +}; - var output; - if (array) { - output = formatArray(ctx, value, recurseTimes, visibleKeys, keys); - } else { - output = keys.map(function(key) { - return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array); - }); - } +Point.prototype._encode = function _encode() { + return this.getX().toArray('be', this.curve.p.byteLength()); +}; - ctx.seen.pop(); +Point.fromJSON = function fromJSON(curve, obj) { + return new Point(curve, obj[0], obj[1] || curve.one); +}; - return reduceToSingleString(output, base, braces); -} +Point.prototype.inspect = function inspect() { + if (this.isInfinity()) + return ''; + return ''; +}; +Point.prototype.isInfinity = function isInfinity() { + // XXX This code assumes that zero is always zero in red + return this.z.cmpn(0) === 0; +}; -function formatPrimitive(ctx, value) { - if (isUndefined(value)) - return ctx.stylize('undefined', 'undefined'); - if (isString(value)) { - var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '') - .replace(/'/g, "\\'") - .replace(/\\"/g, '"') + '\''; - return ctx.stylize(simple, 'string'); - } - if (isNumber(value)) - return ctx.stylize('' + value, 'number'); - if (isBoolean(value)) - return ctx.stylize('' + value, 'boolean'); - // For some reason typeof null is "object", so special case here. - if (isNull(value)) - return ctx.stylize('null', 'null'); -} +Point.prototype.dbl = function dbl() { + // http://hyperelliptic.org/EFD/g1p/auto-montgom-xz.html#doubling-dbl-1987-m-3 + // 2M + 2S + 4A + // A = X1 + Z1 + var a = this.x.redAdd(this.z); + // AA = A^2 + var aa = a.redSqr(); + // B = X1 - Z1 + var b = this.x.redSub(this.z); + // BB = B^2 + var bb = b.redSqr(); + // C = AA - BB + var c = aa.redSub(bb); + // X3 = AA * BB + var nx = aa.redMul(bb); + // Z3 = C * (BB + A24 * C) + var nz = c.redMul(bb.redAdd(this.curve.a24.redMul(c))); + return this.curve.point(nx, nz); +}; -function formatError(value) { - return '[' + Error.prototype.toString.call(value) + ']'; -} +Point.prototype.add = function add() { + throw new Error('Not supported on Montgomery curve'); +}; +Point.prototype.diffAdd = function diffAdd(p, diff) { + // http://hyperelliptic.org/EFD/g1p/auto-montgom-xz.html#diffadd-dadd-1987-m-3 + // 4M + 2S + 6A -function formatArray(ctx, value, recurseTimes, visibleKeys, keys) { - var output = []; - for (var i = 0, l = value.length; i < l; ++i) { - if (hasOwnProperty(value, String(i))) { - output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, - String(i), true)); - } else { - output.push(''); - } - } - keys.forEach(function(key) { - if (!key.match(/^\d+$/)) { - output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, - key, true)); - } - }); - return output; -} + // A = X2 + Z2 + var a = this.x.redAdd(this.z); + // B = X2 - Z2 + var b = this.x.redSub(this.z); + // C = X3 + Z3 + var c = p.x.redAdd(p.z); + // D = X3 - Z3 + var d = p.x.redSub(p.z); + // DA = D * A + var da = d.redMul(a); + // CB = C * B + var cb = c.redMul(b); + // X5 = Z1 * (DA + CB)^2 + var nx = diff.z.redMul(da.redAdd(cb).redSqr()); + // Z5 = X1 * (DA - CB)^2 + var nz = diff.x.redMul(da.redISub(cb).redSqr()); + return this.curve.point(nx, nz); +}; +Point.prototype.mul = function mul(k) { + var t = k.clone(); + var a = this; // (N / 2) * Q + Q + var b = this.curve.point(null, null); // (N / 2) * Q + var c = this; // Q -function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) { - var name, str, desc; - desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] }; - if (desc.get) { - if (desc.set) { - str = ctx.stylize('[Getter/Setter]', 'special'); - } else { - str = ctx.stylize('[Getter]', 'special'); - } - } else { - if (desc.set) { - str = ctx.stylize('[Setter]', 'special'); - } - } - if (!hasOwnProperty(visibleKeys, key)) { - name = '[' + key + ']'; - } - if (!str) { - if (ctx.seen.indexOf(desc.value) < 0) { - if (isNull(recurseTimes)) { - str = formatValue(ctx, desc.value, null); - } else { - str = formatValue(ctx, desc.value, recurseTimes - 1); - } - if (str.indexOf('\n') > -1) { - if (array) { - str = str.split('\n').map(function(line) { - return ' ' + line; - }).join('\n').substr(2); - } else { - str = '\n' + str.split('\n').map(function(line) { - return ' ' + line; - }).join('\n'); - } - } - } else { - str = ctx.stylize('[Circular]', 'special'); - } - } - if (isUndefined(name)) { - if (array && key.match(/^\d+$/)) { - return str; - } - name = JSON.stringify('' + key); - if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) { - name = name.substr(1, name.length - 2); - name = ctx.stylize(name, 'name'); + for (var bits = []; t.cmpn(0) !== 0; t.iushrn(1)) + bits.push(t.andln(1)); + + for (var i = bits.length - 1; i >= 0; i--) { + if (bits[i] === 0) { + // N * Q + Q = ((N / 2) * Q + Q)) + (N / 2) * Q + a = a.diffAdd(b, c); + // N * Q = 2 * ((N / 2) * Q + Q)) + b = b.dbl(); } else { - name = name.replace(/'/g, "\\'") - .replace(/\\"/g, '"') - .replace(/(^"|"$)/g, "'"); - name = ctx.stylize(name, 'string'); + // N * Q = ((N / 2) * Q + Q) + ((N / 2) * Q) + b = a.diffAdd(b, c); + // N * Q + Q = 2 * ((N / 2) * Q + Q) + a = a.dbl(); } } + return b; +}; - return name + ': ' + str; -} - +Point.prototype.mulAdd = function mulAdd() { + throw new Error('Not supported on Montgomery curve'); +}; -function reduceToSingleString(output, base, braces) { - var numLinesEst = 0; - var length = output.reduce(function(prev, cur) { - numLinesEst++; - if (cur.indexOf('\n') >= 0) numLinesEst++; - return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1; - }, 0); +Point.prototype.jumlAdd = function jumlAdd() { + throw new Error('Not supported on Montgomery curve'); +}; - if (length > 60) { - return braces[0] + - (base === '' ? '' : base + '\n ') + - ' ' + - output.join(',\n ') + - ' ' + - braces[1]; - } +Point.prototype.eq = function eq(other) { + return this.getX().cmp(other.getX()) === 0; +}; - return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1]; -} +Point.prototype.normalize = function normalize() { + this.x = this.x.redMul(this.z.redInvm()); + this.z = this.curve.one; + return this; +}; +Point.prototype.getX = function getX() { + // Normalize coordinates + this.normalize(); -// NOTE: These type checking functions intentionally don't use `instanceof` -// because it is fragile and can be easily faked with `Object.create()`. -exports.types = require('./support/types'); + return this.x.fromRed(); +}; -function isArray(ar) { - return Array.isArray(ar); -} -exports.isArray = isArray; +},{"../utils":161,"./base":148,"bn.js":86,"inherits":200}],152:[function(require,module,exports){ +'use strict'; -function isBoolean(arg) { - return typeof arg === 'boolean'; -} -exports.isBoolean = isBoolean; +var utils = require('../utils'); +var BN = require('bn.js'); +var inherits = require('inherits'); +var Base = require('./base'); -function isNull(arg) { - return arg === null; -} -exports.isNull = isNull; +var assert = utils.assert; -function isNullOrUndefined(arg) { - return arg == null; -} -exports.isNullOrUndefined = isNullOrUndefined; +function ShortCurve(conf) { + Base.call(this, 'short', conf); -function isNumber(arg) { - return typeof arg === 'number'; -} -exports.isNumber = isNumber; + this.a = new BN(conf.a, 16).toRed(this.red); + this.b = new BN(conf.b, 16).toRed(this.red); + this.tinv = this.two.redInvm(); -function isString(arg) { - return typeof arg === 'string'; -} -exports.isString = isString; + this.zeroA = this.a.fromRed().cmpn(0) === 0; + this.threeA = this.a.fromRed().sub(this.p).cmpn(-3) === 0; -function isSymbol(arg) { - return typeof arg === 'symbol'; + // If the curve is endomorphic, precalculate beta and lambda + this.endo = this._getEndomorphism(conf); + this._endoWnafT1 = new Array(4); + this._endoWnafT2 = new Array(4); } -exports.isSymbol = isSymbol; +inherits(ShortCurve, Base); +module.exports = ShortCurve; -function isUndefined(arg) { - return arg === void 0; -} -exports.isUndefined = isUndefined; +ShortCurve.prototype._getEndomorphism = function _getEndomorphism(conf) { + // No efficient endomorphism + if (!this.zeroA || !this.g || !this.n || this.p.modn(3) !== 1) + return; -function isRegExp(re) { - return isObject(re) && objectToString(re) === '[object RegExp]'; -} -exports.isRegExp = isRegExp; -exports.types.isRegExp = isRegExp; + // Compute beta and lambda, that lambda * P = (beta * Px; Py) + var beta; + var lambda; + if (conf.beta) { + beta = new BN(conf.beta, 16).toRed(this.red); + } else { + var betas = this._getEndoRoots(this.p); + // Choose the smallest beta + beta = betas[0].cmp(betas[1]) < 0 ? betas[0] : betas[1]; + beta = beta.toRed(this.red); + } + if (conf.lambda) { + lambda = new BN(conf.lambda, 16); + } else { + // Choose the lambda that is matching selected beta + var lambdas = this._getEndoRoots(this.n); + if (this.g.mul(lambdas[0]).x.cmp(this.g.x.redMul(beta)) === 0) { + lambda = lambdas[0]; + } else { + lambda = lambdas[1]; + assert(this.g.mul(lambda).x.cmp(this.g.x.redMul(beta)) === 0); + } + } -function isObject(arg) { - return typeof arg === 'object' && arg !== null; -} -exports.isObject = isObject; + // Get basis vectors, used for balanced length-two representation + var basis; + if (conf.basis) { + basis = conf.basis.map(function(vec) { + return { + a: new BN(vec.a, 16), + b: new BN(vec.b, 16), + }; + }); + } else { + basis = this._getEndoBasis(lambda); + } -function isDate(d) { - return isObject(d) && objectToString(d) === '[object Date]'; -} -exports.isDate = isDate; -exports.types.isDate = isDate; + return { + beta: beta, + lambda: lambda, + basis: basis, + }; +}; -function isError(e) { - return isObject(e) && - (objectToString(e) === '[object Error]' || e instanceof Error); -} -exports.isError = isError; -exports.types.isNativeError = isError; +ShortCurve.prototype._getEndoRoots = function _getEndoRoots(num) { + // Find roots of for x^2 + x + 1 in F + // Root = (-1 +- Sqrt(-3)) / 2 + // + var red = num === this.p ? this.red : BN.mont(num); + var tinv = new BN(2).toRed(red).redInvm(); + var ntinv = tinv.redNeg(); -function isFunction(arg) { - return typeof arg === 'function'; -} -exports.isFunction = isFunction; + var s = new BN(3).toRed(red).redNeg().redSqrt().redMul(tinv); -function isPrimitive(arg) { - return arg === null || - typeof arg === 'boolean' || - typeof arg === 'number' || - typeof arg === 'string' || - typeof arg === 'symbol' || // ES6 symbol - typeof arg === 'undefined'; -} -exports.isPrimitive = isPrimitive; + var l1 = ntinv.redAdd(s).fromRed(); + var l2 = ntinv.redSub(s).fromRed(); + return [ l1, l2 ]; +}; -exports.isBuffer = require('./support/isBuffer'); +ShortCurve.prototype._getEndoBasis = function _getEndoBasis(lambda) { + // aprxSqrt >= sqrt(this.n) + var aprxSqrt = this.n.ushrn(Math.floor(this.n.bitLength() / 2)); -function objectToString(o) { - return Object.prototype.toString.call(o); -} + // 3.74 + // Run EGCD, until r(L + 1) < aprxSqrt + var u = lambda; + var v = this.n.clone(); + var x1 = new BN(1); + var y1 = new BN(0); + var x2 = new BN(0); + var y2 = new BN(1); + // NOTE: all vectors are roots of: a + b * lambda = 0 (mod n) + var a0; + var b0; + // First vector + var a1; + var b1; + // Second vector + var a2; + var b2; -function pad(n) { - return n < 10 ? '0' + n.toString(10) : n.toString(10); -} + var prevR; + var i = 0; + var r; + var x; + while (u.cmpn(0) !== 0) { + var q = v.div(u); + r = v.sub(q.mul(u)); + x = x2.sub(q.mul(x1)); + var y = y2.sub(q.mul(y1)); + if (!a1 && r.cmp(aprxSqrt) < 0) { + a0 = prevR.neg(); + b0 = x1; + a1 = r.neg(); + b1 = x; + } else if (a1 && ++i === 2) { + break; + } + prevR = r; -var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', - 'Oct', 'Nov', 'Dec']; + v = u; + u = r; + x2 = x1; + x1 = x; + y2 = y1; + y1 = y; + } + a2 = r.neg(); + b2 = x; -// 26 Feb 16:19:34 -function timestamp() { - var d = new Date(); - var time = [pad(d.getHours()), - pad(d.getMinutes()), - pad(d.getSeconds())].join(':'); - return [d.getDate(), months[d.getMonth()], time].join(' '); -} + var len1 = a1.sqr().add(b1.sqr()); + var len2 = a2.sqr().add(b2.sqr()); + if (len2.cmp(len1) >= 0) { + a2 = a0; + b2 = b0; + } + // Normalize signs + if (a1.negative) { + a1 = a1.neg(); + b1 = b1.neg(); + } + if (a2.negative) { + a2 = a2.neg(); + b2 = b2.neg(); + } -// log is just a thin wrapper to console.log that prepends a timestamp -exports.log = function() { - console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments)); + return [ + { a: a1, b: b1 }, + { a: a2, b: b2 }, + ]; }; +ShortCurve.prototype._endoSplit = function _endoSplit(k) { + var basis = this.endo.basis; + var v1 = basis[0]; + var v2 = basis[1]; -/** - * Inherit the prototype methods from one constructor into another. - * - * The Function.prototype.inherits from lang.js rewritten as a standalone - * function (not on Function.prototype). NOTE: If this file is to be loaded - * during bootstrapping this function needs to be rewritten using some native - * functions as prototype setup using normal JavaScript does not work as - * expected during bootstrapping (see mirror.js in r114903). - * - * @param {function} ctor Constructor function which needs to inherit the - * prototype. - * @param {function} superCtor Constructor function to inherit prototype from. - */ -exports.inherits = require('inherits'); + var c1 = v2.b.mul(k).divRound(this.n); + var c2 = v1.b.neg().mul(k).divRound(this.n); -exports._extend = function(origin, add) { - // Don't do anything if add isn't an object - if (!add || !isObject(add)) return origin; + var p1 = c1.mul(v1.a); + var p2 = c2.mul(v2.a); + var q1 = c1.mul(v1.b); + var q2 = c2.mul(v2.b); - var keys = Object.keys(add); - var i = keys.length; - while (i--) { - origin[keys[i]] = add[keys[i]]; - } - return origin; + // Calculate answer + var k1 = k.sub(p1).sub(p2); + var k2 = q1.add(q2).neg(); + return { k1: k1, k2: k2 }; }; -function hasOwnProperty(obj, prop) { - return Object.prototype.hasOwnProperty.call(obj, prop); -} +ShortCurve.prototype.pointFromX = function pointFromX(x, odd) { + x = new BN(x, 16); + if (!x.red) + x = x.toRed(this.red); -var kCustomPromisifiedSymbol = typeof Symbol !== 'undefined' ? Symbol('util.promisify.custom') : undefined; + var y2 = x.redSqr().redMul(x).redIAdd(x.redMul(this.a)).redIAdd(this.b); + var y = y2.redSqrt(); + if (y.redSqr().redSub(y2).cmp(this.zero) !== 0) + throw new Error('invalid point'); -exports.promisify = function promisify(original) { - if (typeof original !== 'function') - throw new TypeError('The "original" argument must be of type Function'); + // XXX Is there any way to tell if the number is odd without converting it + // to non-red form? + var isOdd = y.fromRed().isOdd(); + if (odd && !isOdd || !odd && isOdd) + y = y.redNeg(); - if (kCustomPromisifiedSymbol && original[kCustomPromisifiedSymbol]) { - var fn = original[kCustomPromisifiedSymbol]; - if (typeof fn !== 'function') { - throw new TypeError('The "util.promisify.custom" argument must be of type Function'); - } - Object.defineProperty(fn, kCustomPromisifiedSymbol, { - value: fn, enumerable: false, writable: false, configurable: true - }); - return fn; - } + return this.point(x, y); +}; - function fn() { - var promiseResolve, promiseReject; - var promise = new Promise(function (resolve, reject) { - promiseResolve = resolve; - promiseReject = reject; - }); +ShortCurve.prototype.validate = function validate(point) { + if (point.inf) + return true; - var args = []; - for (var i = 0; i < arguments.length; i++) { - args.push(arguments[i]); - } - args.push(function (err, value) { - if (err) { - promiseReject(err); - } else { - promiseResolve(value); - } - }); + var x = point.x; + var y = point.y; - try { - original.apply(this, args); - } catch (err) { - promiseReject(err); - } + var ax = this.a.redMul(x); + var rhs = x.redSqr().redMul(x).redIAdd(ax).redIAdd(this.b); + return y.redSqr().redISub(rhs).cmpn(0) === 0; +}; - return promise; - } +ShortCurve.prototype._endoWnafMulAdd = + function _endoWnafMulAdd(points, coeffs, jacobianResult) { + var npoints = this._endoWnafT1; + var ncoeffs = this._endoWnafT2; + for (var i = 0; i < points.length; i++) { + var split = this._endoSplit(coeffs[i]); + var p = points[i]; + var beta = p._getBeta(); - Object.setPrototypeOf(fn, Object.getPrototypeOf(original)); + if (split.k1.negative) { + split.k1.ineg(); + p = p.neg(true); + } + if (split.k2.negative) { + split.k2.ineg(); + beta = beta.neg(true); + } - if (kCustomPromisifiedSymbol) Object.defineProperty(fn, kCustomPromisifiedSymbol, { - value: fn, enumerable: false, writable: false, configurable: true - }); - return Object.defineProperties( - fn, - getOwnPropertyDescriptors(original) - ); -} + npoints[i * 2] = p; + npoints[i * 2 + 1] = beta; + ncoeffs[i * 2] = split.k1; + ncoeffs[i * 2 + 1] = split.k2; + } + var res = this._wnafMulAdd(1, npoints, ncoeffs, i * 2, jacobianResult); -exports.promisify.custom = kCustomPromisifiedSymbol + // Clean-up references to points and coefficients + for (var j = 0; j < i * 2; j++) { + npoints[j] = null; + ncoeffs[j] = null; + } + return res; + }; -function callbackifyOnRejected(reason, cb) { - // `!reason` guard inspired by bluebird (Ref: https://goo.gl/t5IS6M). - // Because `null` is a special error value in callbacks which means "no error - // occurred", we error-wrap so the callback consumer can distinguish between - // "the promise rejected with null" or "the promise fulfilled with undefined". - if (!reason) { - var newReason = new Error('Promise was rejected with a falsy value'); - newReason.reason = reason; - reason = newReason; +function Point(curve, x, y, isRed) { + Base.BasePoint.call(this, curve, 'affine'); + if (x === null && y === null) { + this.x = null; + this.y = null; + this.inf = true; + } else { + this.x = new BN(x, 16); + this.y = new BN(y, 16); + // Force redgomery representation when loading from JSON + if (isRed) { + this.x.forceRed(this.curve.red); + this.y.forceRed(this.curve.red); + } + if (!this.x.red) + this.x = this.x.toRed(this.curve.red); + if (!this.y.red) + this.y = this.y.toRed(this.curve.red); + this.inf = false; } - return cb(reason); } +inherits(Point, Base.BasePoint); -function callbackify(original) { - if (typeof original !== 'function') { - throw new TypeError('The "original" argument must be of type Function'); - } +ShortCurve.prototype.point = function point(x, y, isRed) { + return new Point(this, x, y, isRed); +}; - // We DO NOT return the promise as it gives the user a false sense that - // the promise is actually somehow related to the callback's execution - // and that the callback throwing will reject the promise. - function callbackified() { - var args = []; - for (var i = 0; i < arguments.length; i++) { - args.push(arguments[i]); - } +ShortCurve.prototype.pointFromJSON = function pointFromJSON(obj, red) { + return Point.fromJSON(this, obj, red); +}; - var maybeCb = args.pop(); - if (typeof maybeCb !== 'function') { - throw new TypeError('The last argument must be of type Function'); - } - var self = this; - var cb = function() { - return maybeCb.apply(self, arguments); +Point.prototype._getBeta = function _getBeta() { + if (!this.curve.endo) + return; + + var pre = this.precomputed; + if (pre && pre.beta) + return pre.beta; + + var beta = this.curve.point(this.x.redMul(this.curve.endo.beta), this.y); + if (pre) { + var curve = this.curve; + var endoMul = function(p) { + return curve.point(p.x.redMul(curve.endo.beta), p.y); + }; + pre.beta = beta; + beta.precomputed = { + beta: null, + naf: pre.naf && { + wnd: pre.naf.wnd, + points: pre.naf.points.map(endoMul), + }, + doubles: pre.doubles && { + step: pre.doubles.step, + points: pre.doubles.points.map(endoMul), + }, }; - // In true node style we process the callback on `nextTick` with all the - // implications (stack, `uncaughtException`, `async_hooks`) - original.apply(this, args) - .then(function(ret) { process.nextTick(cb.bind(null, null, ret)) }, - function(rej) { process.nextTick(callbackifyOnRejected.bind(null, rej, cb)) }); } + return beta; +}; - Object.setPrototypeOf(callbackified, Object.getPrototypeOf(original)); - Object.defineProperties(callbackified, - getOwnPropertyDescriptors(original)); - return callbackified; -} -exports.callbackify = callbackify; +Point.prototype.toJSON = function toJSON() { + if (!this.precomputed) + return [ this.x, this.y ]; -}).call(this)}).call(this,require('_process')) -},{"./support/isBuffer":153,"./support/types":154,"_process":391,"inherits":256}],156:[function(require,module,exports){ -(function (Buffer){(function (){ -module.exports = function xor (a, b) { - var length = Math.min(a.length, b.length) - var buffer = new Buffer(length) + return [ this.x, this.y, this.precomputed && { + doubles: this.precomputed.doubles && { + step: this.precomputed.doubles.step, + points: this.precomputed.doubles.points.slice(1), + }, + naf: this.precomputed.naf && { + wnd: this.precomputed.naf.wnd, + points: this.precomputed.naf.points.slice(1), + }, + } ]; +}; - for (var i = 0; i < length; ++i) { - buffer[i] = a[i] ^ b[i] +Point.fromJSON = function fromJSON(curve, obj, red) { + if (typeof obj === 'string') + obj = JSON.parse(obj); + var res = curve.point(obj[0], obj[1], red); + if (!obj[2]) + return res; + + function obj2point(obj) { + return curve.point(obj[0], obj[1], red); } - return buffer -} + var pre = obj[2]; + res.precomputed = { + beta: null, + doubles: pre.doubles && { + step: pre.doubles.step, + points: [ res ].concat(pre.doubles.points.map(obj2point)), + }, + naf: pre.naf && { + wnd: pre.naf.wnd, + points: [ res ].concat(pre.naf.points.map(obj2point)), + }, + }; + return res; +}; -}).call(this)}).call(this,require("buffer").Buffer) -},{"buffer":137}],157:[function(require,module,exports){ -'use strict'; +Point.prototype.inspect = function inspect() { + if (this.isInfinity()) + return ''; + return ''; +}; -var GetIntrinsic = require('get-intrinsic'); +Point.prototype.isInfinity = function isInfinity() { + return this.inf; +}; -var callBind = require('./'); +Point.prototype.add = function add(p) { + // O + P = P + if (this.inf) + return p; -var $indexOf = callBind(GetIntrinsic('String.prototype.indexOf')); + // P + O = P + if (p.inf) + return this; -module.exports = function callBoundIntrinsic(name, allowMissing) { - var intrinsic = GetIntrinsic(name, !!allowMissing); - if (typeof intrinsic === 'function' && $indexOf(name, '.prototype.') > -1) { - return callBind(intrinsic); - } - return intrinsic; + // P + P = 2P + if (this.eq(p)) + return this.dbl(); + + // P + (-P) = O + if (this.neg().eq(p)) + return this.curve.point(null, null); + + // P + Q = O + if (this.x.cmp(p.x) === 0) + return this.curve.point(null, null); + + var c = this.y.redSub(p.y); + if (c.cmpn(0) !== 0) + c = c.redMul(this.x.redSub(p.x).redInvm()); + var nx = c.redSqr().redISub(this.x).redISub(p.x); + var ny = c.redMul(this.x.redSub(nx)).redISub(this.y); + return this.curve.point(nx, ny); }; -},{"./":158,"get-intrinsic":217}],158:[function(require,module,exports){ -'use strict'; +Point.prototype.dbl = function dbl() { + if (this.inf) + return this; -var bind = require('function-bind'); -var GetIntrinsic = require('get-intrinsic'); -var setFunctionLength = require('set-function-length'); + // 2P = O + var ys1 = this.y.redAdd(this.y); + if (ys1.cmpn(0) === 0) + return this.curve.point(null, null); -var $TypeError = require('es-errors/type'); -var $apply = GetIntrinsic('%Function.prototype.apply%'); -var $call = GetIntrinsic('%Function.prototype.call%'); -var $reflectApply = GetIntrinsic('%Reflect.apply%', true) || bind.call($call, $apply); + var a = this.curve.a; -var $defineProperty = require('es-define-property'); -var $max = GetIntrinsic('%Math.max%'); + var x2 = this.x.redSqr(); + var dyinv = ys1.redInvm(); + var c = x2.redAdd(x2).redIAdd(x2).redIAdd(a).redMul(dyinv); -module.exports = function callBind(originalFunction) { - if (typeof originalFunction !== 'function') { - throw new $TypeError('a function is required'); - } - var func = $reflectApply(bind, $call, arguments); - return setFunctionLength( - func, - 1 + $max(0, originalFunction.length - (arguments.length - 1)), - true - ); + var nx = c.redSqr().redISub(this.x.redAdd(this.x)); + var ny = c.redMul(this.x.redSub(nx)).redISub(this.y); + return this.curve.point(nx, ny); }; -var applyBind = function applyBind() { - return $reflectApply(bind, $apply, arguments); +Point.prototype.getX = function getX() { + return this.x.fromRed(); }; -if ($defineProperty) { - $defineProperty(module.exports, 'apply', { value: applyBind }); -} else { - module.exports.apply = applyBind; -} - -},{"es-define-property":203,"es-errors/type":209,"function-bind":216,"get-intrinsic":217,"set-function-length":406}],159:[function(require,module,exports){ -'use strict' +Point.prototype.getY = function getY() { + return this.y.fromRed(); +}; -var nextTick = require('./next-tick') +Point.prototype.mul = function mul(k) { + k = new BN(k, 16); + if (this.isInfinity()) + return this; + else if (this._hasDoubles(k)) + return this.curve._fixedNafMul(this, k); + else if (this.curve.endo) + return this.curve._endoWnafMulAdd([ this ], [ k ]); + else + return this.curve._wnafMul(this, k); +}; -exports.fromCallback = function (callback, symbol) { - if (callback === undefined) { - var promise = new Promise(function (resolve, reject) { - callback = function (err, res) { - if (err) reject(err) - else resolve(res) - } - }) +Point.prototype.mulAdd = function mulAdd(k1, p2, k2) { + var points = [ this, p2 ]; + var coeffs = [ k1, k2 ]; + if (this.curve.endo) + return this.curve._endoWnafMulAdd(points, coeffs); + else + return this.curve._wnafMulAdd(1, points, coeffs, 2); +}; - callback[symbol !== undefined ? symbol : 'promise'] = promise - } else if (typeof callback !== 'function') { - throw new TypeError('Callback must be a function') - } +Point.prototype.jmulAdd = function jmulAdd(k1, p2, k2) { + var points = [ this, p2 ]; + var coeffs = [ k1, k2 ]; + if (this.curve.endo) + return this.curve._endoWnafMulAdd(points, coeffs, true); + else + return this.curve._wnafMulAdd(1, points, coeffs, 2, true); +}; - return callback -} +Point.prototype.eq = function eq(p) { + return this === p || + this.inf === p.inf && + (this.inf || this.x.cmp(p.x) === 0 && this.y.cmp(p.y) === 0); +}; -exports.fromPromise = function (promise, callback) { - if (callback === undefined) return promise +Point.prototype.neg = function neg(_precompute) { + if (this.inf) + return this; - promise - .then(function (res) { nextTick(() => callback(null, res)) }) - .catch(function (err) { nextTick(() => callback(err)) }) -} + var res = this.curve.point(this.x, this.y.redNeg()); + if (_precompute && this.precomputed) { + var pre = this.precomputed; + var negate = function(p) { + return p.neg(); + }; + res.precomputed = { + naf: pre.naf && { + wnd: pre.naf.wnd, + points: pre.naf.points.map(negate), + }, + doubles: pre.doubles && { + step: pre.doubles.step, + points: pre.doubles.points.map(negate), + }, + }; + } + return res; +}; -},{"./next-tick":160}],160:[function(require,module,exports){ -module.exports = typeof queueMicrotask === 'function' ? queueMicrotask : (fn) => Promise.resolve().then(fn) +Point.prototype.toJ = function toJ() { + if (this.inf) + return this.curve.jpoint(null, null, null); -},{}],161:[function(require,module,exports){ -var Buffer = require('safe-buffer').Buffer -var Transform = require('stream').Transform -var StringDecoder = require('string_decoder').StringDecoder -var inherits = require('inherits') + var res = this.curve.jpoint(this.x, this.y, this.curve.one); + return res; +}; -function CipherBase (hashMode) { - Transform.call(this) - this.hashMode = typeof hashMode === 'string' - if (this.hashMode) { - this[hashMode] = this._finalOrDigest +function JPoint(curve, x, y, z) { + Base.BasePoint.call(this, curve, 'jacobian'); + if (x === null && y === null && z === null) { + this.x = this.curve.one; + this.y = this.curve.one; + this.z = new BN(0); } else { - this.final = this._finalOrDigest - } - if (this._final) { - this.__final = this._final - this._final = null + this.x = new BN(x, 16); + this.y = new BN(y, 16); + this.z = new BN(z, 16); } - this._decoder = null - this._encoding = null + if (!this.x.red) + this.x = this.x.toRed(this.curve.red); + if (!this.y.red) + this.y = this.y.toRed(this.curve.red); + if (!this.z.red) + this.z = this.z.toRed(this.curve.red); + + this.zOne = this.z === this.curve.one; } -inherits(CipherBase, Transform) +inherits(JPoint, Base.BasePoint); -CipherBase.prototype.update = function (data, inputEnc, outputEnc) { - if (typeof data === 'string') { - data = Buffer.from(data, inputEnc) - } +ShortCurve.prototype.jpoint = function jpoint(x, y, z) { + return new JPoint(this, x, y, z); +}; - var outData = this._update(data) - if (this.hashMode) return this +JPoint.prototype.toP = function toP() { + if (this.isInfinity()) + return this.curve.point(null, null); - if (outputEnc) { - outData = this._toString(outData, outputEnc) - } + var zinv = this.z.redInvm(); + var zinv2 = zinv.redSqr(); + var ax = this.x.redMul(zinv2); + var ay = this.y.redMul(zinv2).redMul(zinv); - return outData -} + return this.curve.point(ax, ay); +}; -CipherBase.prototype.setAutoPadding = function () {} -CipherBase.prototype.getAuthTag = function () { - throw new Error('trying to get auth tag in unsupported state') -} +JPoint.prototype.neg = function neg() { + return this.curve.jpoint(this.x, this.y.redNeg(), this.z); +}; -CipherBase.prototype.setAuthTag = function () { - throw new Error('trying to set auth tag in unsupported state') -} +JPoint.prototype.add = function add(p) { + // O + P = P + if (this.isInfinity()) + return p; -CipherBase.prototype.setAAD = function () { - throw new Error('trying to set aad in unsupported state') -} + // P + O = P + if (p.isInfinity()) + return this; -CipherBase.prototype._transform = function (data, _, next) { - var err - try { - if (this.hashMode) { - this._update(data) - } else { - this.push(this._update(data)) - } - } catch (e) { - err = e - } finally { - next(err) - } -} -CipherBase.prototype._flush = function (done) { - var err - try { - this.push(this.__final()) - } catch (e) { - err = e - } + // 12M + 4S + 7A + var pz2 = p.z.redSqr(); + var z2 = this.z.redSqr(); + var u1 = this.x.redMul(pz2); + var u2 = p.x.redMul(z2); + var s1 = this.y.redMul(pz2.redMul(p.z)); + var s2 = p.y.redMul(z2.redMul(this.z)); - done(err) -} -CipherBase.prototype._finalOrDigest = function (outputEnc) { - var outData = this.__final() || Buffer.alloc(0) - if (outputEnc) { - outData = this._toString(outData, outputEnc, true) + var h = u1.redSub(u2); + var r = s1.redSub(s2); + if (h.cmpn(0) === 0) { + if (r.cmpn(0) !== 0) + return this.curve.jpoint(null, null, null); + else + return this.dbl(); } - return outData -} -CipherBase.prototype._toString = function (value, enc, fin) { - if (!this._decoder) { - this._decoder = new StringDecoder(enc) - this._encoding = enc - } - - if (this._encoding !== enc) throw new Error('can\'t switch encodings') + var h2 = h.redSqr(); + var h3 = h2.redMul(h); + var v = u1.redMul(h2); - var out = this._decoder.write(value) - if (fin) { - out += this._decoder.end() - } + var nx = r.redSqr().redIAdd(h3).redISub(v).redISub(v); + var ny = r.redMul(v.redISub(nx)).redISub(s1.redMul(h3)); + var nz = this.z.redMul(p.z).redMul(h); - return out -} + return this.curve.jpoint(nx, ny, nz); +}; -module.exports = CipherBase +JPoint.prototype.mixedAdd = function mixedAdd(p) { + // O + P = P + if (this.isInfinity()) + return p.toJ(); -},{"inherits":256,"safe-buffer":404,"stream":138,"string_decoder":415}],162:[function(require,module,exports){ -(function (Buffer){(function (){ -var elliptic = require('elliptic') -var BN = require('bn.js') + // P + O = P + if (p.isInfinity()) + return this; -module.exports = function createECDH (curve) { - return new ECDH(curve) -} + // 8M + 3S + 7A + var z2 = this.z.redSqr(); + var u1 = this.x; + var u2 = p.x.redMul(z2); + var s1 = this.y; + var s2 = p.y.redMul(z2).redMul(this.z); -var aliases = { - secp256k1: { - name: 'secp256k1', - byteLength: 32 - }, - secp224r1: { - name: 'p224', - byteLength: 28 - }, - prime256v1: { - name: 'p256', - byteLength: 32 - }, - prime192v1: { - name: 'p192', - byteLength: 24 - }, - ed25519: { - name: 'ed25519', - byteLength: 32 - }, - secp384r1: { - name: 'p384', - byteLength: 48 - }, - secp521r1: { - name: 'p521', - byteLength: 66 + var h = u1.redSub(u2); + var r = s1.redSub(s2); + if (h.cmpn(0) === 0) { + if (r.cmpn(0) !== 0) + return this.curve.jpoint(null, null, null); + else + return this.dbl(); } -} -aliases.p224 = aliases.secp224r1 -aliases.p256 = aliases.secp256r1 = aliases.prime256v1 -aliases.p192 = aliases.secp192r1 = aliases.prime192v1 -aliases.p384 = aliases.secp384r1 -aliases.p521 = aliases.secp521r1 + var h2 = h.redSqr(); + var h3 = h2.redMul(h); + var v = u1.redMul(h2); -function ECDH (curve) { - this.curveType = aliases[curve] - if (!this.curveType) { - this.curveType = { - name: curve - } - } - this.curve = new elliptic.ec(this.curveType.name) // eslint-disable-line new-cap - this.keys = void 0 -} + var nx = r.redSqr().redIAdd(h3).redISub(v).redISub(v); + var ny = r.redMul(v.redISub(nx)).redISub(s1.redMul(h3)); + var nz = this.z.redMul(h); -ECDH.prototype.generateKeys = function (enc, format) { - this.keys = this.curve.genKeyPair() - return this.getPublicKey(enc, format) -} + return this.curve.jpoint(nx, ny, nz); +}; -ECDH.prototype.computeSecret = function (other, inenc, enc) { - inenc = inenc || 'utf8' - if (!Buffer.isBuffer(other)) { - other = new Buffer(other, inenc) - } - var otherPub = this.curve.keyFromPublic(other).getPublic() - var out = otherPub.mul(this.keys.getPrivate()).getX() - return formatReturnValue(out, enc, this.curveType.byteLength) -} +JPoint.prototype.dblp = function dblp(pow) { + if (pow === 0) + return this; + if (this.isInfinity()) + return this; + if (!pow) + return this.dbl(); -ECDH.prototype.getPublicKey = function (enc, format) { - var key = this.keys.getPublic(format === 'compressed', true) - if (format === 'hybrid') { - if (key[key.length - 1] % 2) { - key[0] = 7 - } else { - key[0] = 6 - } + var i; + if (this.curve.zeroA || this.curve.threeA) { + var r = this; + for (i = 0; i < pow; i++) + r = r.dbl(); + return r; } - return formatReturnValue(key, enc) -} -ECDH.prototype.getPrivateKey = function (enc) { - return formatReturnValue(this.keys.getPrivate(), enc) -} + // 1M + 2S + 1A + N * (4S + 5M + 8A) + // N = 1 => 6M + 6S + 9A + var a = this.curve.a; + var tinv = this.curve.tinv; -ECDH.prototype.setPublicKey = function (pub, enc) { - enc = enc || 'utf8' - if (!Buffer.isBuffer(pub)) { - pub = new Buffer(pub, enc) - } - this.keys._importPublic(pub) - return this -} + var jx = this.x; + var jy = this.y; + var jz = this.z; + var jz4 = jz.redSqr().redSqr(); -ECDH.prototype.setPrivateKey = function (priv, enc) { - enc = enc || 'utf8' - if (!Buffer.isBuffer(priv)) { - priv = new Buffer(priv, enc) - } + // Reuse results + var jyd = jy.redAdd(jy); + for (i = 0; i < pow; i++) { + var jx2 = jx.redSqr(); + var jyd2 = jyd.redSqr(); + var jyd4 = jyd2.redSqr(); + var c = jx2.redAdd(jx2).redIAdd(jx2).redIAdd(a.redMul(jz4)); - var _priv = new BN(priv) - _priv = _priv.toString(16) - this.keys = this.curve.genKeyPair() - this.keys._importPrivate(_priv) - return this -} + var t1 = jx.redMul(jyd2); + var nx = c.redSqr().redISub(t1.redAdd(t1)); + var t2 = t1.redISub(nx); + var dny = c.redMul(t2); + dny = dny.redIAdd(dny).redISub(jyd4); + var nz = jyd.redMul(jz); + if (i + 1 < pow) + jz4 = jz4.redMul(jyd4); -function formatReturnValue (bn, enc, len) { - if (!Array.isArray(bn)) { - bn = bn.toArray() - } - var buf = new Buffer(bn) - if (len && buf.length < len) { - var zeros = new Buffer(len - buf.length) - zeros.fill(0) - buf = Buffer.concat([zeros, buf]) - } - if (!enc) { - return buf - } else { - return buf.toString(enc) + jx = nx; + jz = nz; + jyd = dny; } -} -}).call(this)}).call(this,require("buffer").Buffer) -},{"bn.js":163,"buffer":137,"elliptic":185}],163:[function(require,module,exports){ -arguments[4][47][0].apply(exports,arguments) -},{"buffer":93,"dup":47}],164:[function(require,module,exports){ -'use strict' -var inherits = require('inherits') -var MD5 = require('md5.js') -var RIPEMD160 = require('ripemd160') -var sha = require('sha.js') -var Base = require('cipher-base') + return this.curve.jpoint(jx, jyd.redMul(tinv), jz); +}; -function Hash (hash) { - Base.call(this, 'digest') +JPoint.prototype.dbl = function dbl() { + if (this.isInfinity()) + return this; - this._hash = hash -} + if (this.curve.zeroA) + return this._zeroDbl(); + else if (this.curve.threeA) + return this._threeDbl(); + else + return this._dbl(); +}; -inherits(Hash, Base) +JPoint.prototype._zeroDbl = function _zeroDbl() { + var nx; + var ny; + var nz; + // Z = 1 + if (this.zOne) { + // hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html + // #doubling-mdbl-2007-bl + // 1M + 5S + 14A -Hash.prototype._update = function (data) { - this._hash.update(data) -} + // XX = X1^2 + var xx = this.x.redSqr(); + // YY = Y1^2 + var yy = this.y.redSqr(); + // YYYY = YY^2 + var yyyy = yy.redSqr(); + // S = 2 * ((X1 + YY)^2 - XX - YYYY) + var s = this.x.redAdd(yy).redSqr().redISub(xx).redISub(yyyy); + s = s.redIAdd(s); + // M = 3 * XX + a; a = 0 + var m = xx.redAdd(xx).redIAdd(xx); + // T = M ^ 2 - 2*S + var t = m.redSqr().redISub(s).redISub(s); -Hash.prototype._final = function () { - return this._hash.digest() -} + // 8 * YYYY + var yyyy8 = yyyy.redIAdd(yyyy); + yyyy8 = yyyy8.redIAdd(yyyy8); + yyyy8 = yyyy8.redIAdd(yyyy8); -module.exports = function createHash (alg) { - alg = alg.toLowerCase() - if (alg === 'md5') return new MD5() - if (alg === 'rmd160' || alg === 'ripemd160') return new RIPEMD160() + // X3 = T + nx = t; + // Y3 = M * (S - T) - 8 * YYYY + ny = m.redMul(s.redISub(t)).redISub(yyyy8); + // Z3 = 2*Y1 + nz = this.y.redAdd(this.y); + } else { + // hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html + // #doubling-dbl-2009-l + // 2M + 5S + 13A - return new Hash(sha(alg)) -} + // A = X1^2 + var a = this.x.redSqr(); + // B = Y1^2 + var b = this.y.redSqr(); + // C = B^2 + var c = b.redSqr(); + // D = 2 * ((X1 + B)^2 - A - C) + var d = this.x.redAdd(b).redSqr().redISub(a).redISub(c); + d = d.redIAdd(d); + // E = 3 * A + var e = a.redAdd(a).redIAdd(a); + // F = E^2 + var f = e.redSqr(); -},{"cipher-base":161,"inherits":256,"md5.js":298,"ripemd160":402,"sha.js":408}],165:[function(require,module,exports){ -var MD5 = require('md5.js') + // 8 * C + var c8 = c.redIAdd(c); + c8 = c8.redIAdd(c8); + c8 = c8.redIAdd(c8); -module.exports = function (buffer) { - return new MD5().update(buffer).digest() -} + // X3 = F - 2 * D + nx = f.redISub(d).redISub(d); + // Y3 = E * (D - X3) - 8 * C + ny = e.redMul(d.redISub(nx)).redISub(c8); + // Z3 = 2 * Y1 * Z1 + nz = this.y.redMul(this.z); + nz = nz.redIAdd(nz); + } -},{"md5.js":298}],166:[function(require,module,exports){ -'use strict' -var inherits = require('inherits') -var Legacy = require('./legacy') -var Base = require('cipher-base') -var Buffer = require('safe-buffer').Buffer -var md5 = require('create-hash/md5') -var RIPEMD160 = require('ripemd160') + return this.curve.jpoint(nx, ny, nz); +}; -var sha = require('sha.js') +JPoint.prototype._threeDbl = function _threeDbl() { + var nx; + var ny; + var nz; + // Z = 1 + if (this.zOne) { + // hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html + // #doubling-mdbl-2007-bl + // 1M + 5S + 15A -var ZEROS = Buffer.alloc(128) + // XX = X1^2 + var xx = this.x.redSqr(); + // YY = Y1^2 + var yy = this.y.redSqr(); + // YYYY = YY^2 + var yyyy = yy.redSqr(); + // S = 2 * ((X1 + YY)^2 - XX - YYYY) + var s = this.x.redAdd(yy).redSqr().redISub(xx).redISub(yyyy); + s = s.redIAdd(s); + // M = 3 * XX + a + var m = xx.redAdd(xx).redIAdd(xx).redIAdd(this.curve.a); + // T = M^2 - 2 * S + var t = m.redSqr().redISub(s).redISub(s); + // X3 = T + nx = t; + // Y3 = M * (S - T) - 8 * YYYY + var yyyy8 = yyyy.redIAdd(yyyy); + yyyy8 = yyyy8.redIAdd(yyyy8); + yyyy8 = yyyy8.redIAdd(yyyy8); + ny = m.redMul(s.redISub(t)).redISub(yyyy8); + // Z3 = 2 * Y1 + nz = this.y.redAdd(this.y); + } else { + // hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2001-b + // 3M + 5S -function Hmac (alg, key) { - Base.call(this, 'digest') - if (typeof key === 'string') { - key = Buffer.from(key) + // delta = Z1^2 + var delta = this.z.redSqr(); + // gamma = Y1^2 + var gamma = this.y.redSqr(); + // beta = X1 * gamma + var beta = this.x.redMul(gamma); + // alpha = 3 * (X1 - delta) * (X1 + delta) + var alpha = this.x.redSub(delta).redMul(this.x.redAdd(delta)); + alpha = alpha.redAdd(alpha).redIAdd(alpha); + // X3 = alpha^2 - 8 * beta + var beta4 = beta.redIAdd(beta); + beta4 = beta4.redIAdd(beta4); + var beta8 = beta4.redAdd(beta4); + nx = alpha.redSqr().redISub(beta8); + // Z3 = (Y1 + Z1)^2 - gamma - delta + nz = this.y.redAdd(this.z).redSqr().redISub(gamma).redISub(delta); + // Y3 = alpha * (4 * beta - X3) - 8 * gamma^2 + var ggamma8 = gamma.redSqr(); + ggamma8 = ggamma8.redIAdd(ggamma8); + ggamma8 = ggamma8.redIAdd(ggamma8); + ggamma8 = ggamma8.redIAdd(ggamma8); + ny = alpha.redMul(beta4.redISub(nx)).redISub(ggamma8); } - var blocksize = (alg === 'sha512' || alg === 'sha384') ? 128 : 64 + return this.curve.jpoint(nx, ny, nz); +}; - this._alg = alg - this._key = key - if (key.length > blocksize) { - var hash = alg === 'rmd160' ? new RIPEMD160() : sha(alg) - key = hash.update(key).digest() - } else if (key.length < blocksize) { - key = Buffer.concat([key, ZEROS], blocksize) - } +JPoint.prototype._dbl = function _dbl() { + var a = this.curve.a; - var ipad = this._ipad = Buffer.allocUnsafe(blocksize) - var opad = this._opad = Buffer.allocUnsafe(blocksize) + // 4M + 6S + 10A + var jx = this.x; + var jy = this.y; + var jz = this.z; + var jz4 = jz.redSqr().redSqr(); - for (var i = 0; i < blocksize; i++) { - ipad[i] = key[i] ^ 0x36 - opad[i] = key[i] ^ 0x5C - } - this._hash = alg === 'rmd160' ? new RIPEMD160() : sha(alg) - this._hash.update(ipad) -} + var jx2 = jx.redSqr(); + var jy2 = jy.redSqr(); -inherits(Hmac, Base) + var c = jx2.redAdd(jx2).redIAdd(jx2).redIAdd(a.redMul(jz4)); -Hmac.prototype._update = function (data) { - this._hash.update(data) -} + var jxd4 = jx.redAdd(jx); + jxd4 = jxd4.redIAdd(jxd4); + var t1 = jxd4.redMul(jy2); + var nx = c.redSqr().redISub(t1.redAdd(t1)); + var t2 = t1.redISub(nx); -Hmac.prototype._final = function () { - var h = this._hash.digest() - var hash = this._alg === 'rmd160' ? new RIPEMD160() : sha(this._alg) - return hash.update(this._opad).update(h).digest() -} + var jyd8 = jy2.redSqr(); + jyd8 = jyd8.redIAdd(jyd8); + jyd8 = jyd8.redIAdd(jyd8); + jyd8 = jyd8.redIAdd(jyd8); + var ny = c.redMul(t2).redISub(jyd8); + var nz = jy.redAdd(jy).redMul(jz); -module.exports = function createHmac (alg, key) { - alg = alg.toLowerCase() - if (alg === 'rmd160' || alg === 'ripemd160') { - return new Hmac('rmd160', key) - } - if (alg === 'md5') { - return new Legacy(md5, key) - } - return new Hmac(alg, key) -} + return this.curve.jpoint(nx, ny, nz); +}; -},{"./legacy":167,"cipher-base":161,"create-hash/md5":165,"inherits":256,"ripemd160":402,"safe-buffer":404,"sha.js":408}],167:[function(require,module,exports){ -'use strict' -var inherits = require('inherits') -var Buffer = require('safe-buffer').Buffer +JPoint.prototype.trpl = function trpl() { + if (!this.curve.zeroA) + return this.dbl().add(this); -var Base = require('cipher-base') + // hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#tripling-tpl-2007-bl + // 5M + 10S + ... -var ZEROS = Buffer.alloc(128) -var blocksize = 64 + // XX = X1^2 + var xx = this.x.redSqr(); + // YY = Y1^2 + var yy = this.y.redSqr(); + // ZZ = Z1^2 + var zz = this.z.redSqr(); + // YYYY = YY^2 + var yyyy = yy.redSqr(); + // M = 3 * XX + a * ZZ2; a = 0 + var m = xx.redAdd(xx).redIAdd(xx); + // MM = M^2 + var mm = m.redSqr(); + // E = 6 * ((X1 + YY)^2 - XX - YYYY) - MM + var e = this.x.redAdd(yy).redSqr().redISub(xx).redISub(yyyy); + e = e.redIAdd(e); + e = e.redAdd(e).redIAdd(e); + e = e.redISub(mm); + // EE = E^2 + var ee = e.redSqr(); + // T = 16*YYYY + var t = yyyy.redIAdd(yyyy); + t = t.redIAdd(t); + t = t.redIAdd(t); + t = t.redIAdd(t); + // U = (M + E)^2 - MM - EE - T + var u = m.redIAdd(e).redSqr().redISub(mm).redISub(ee).redISub(t); + // X3 = 4 * (X1 * EE - 4 * YY * U) + var yyu4 = yy.redMul(u); + yyu4 = yyu4.redIAdd(yyu4); + yyu4 = yyu4.redIAdd(yyu4); + var nx = this.x.redMul(ee).redISub(yyu4); + nx = nx.redIAdd(nx); + nx = nx.redIAdd(nx); + // Y3 = 8 * Y1 * (U * (T - U) - E * EE) + var ny = this.y.redMul(u.redMul(t.redISub(u)).redISub(e.redMul(ee))); + ny = ny.redIAdd(ny); + ny = ny.redIAdd(ny); + ny = ny.redIAdd(ny); + // Z3 = (Z1 + E)^2 - ZZ - EE + var nz = this.z.redAdd(e).redSqr().redISub(zz).redISub(ee); -function Hmac (alg, key) { - Base.call(this, 'digest') - if (typeof key === 'string') { - key = Buffer.from(key) - } + return this.curve.jpoint(nx, ny, nz); +}; - this._alg = alg - this._key = key +JPoint.prototype.mul = function mul(k, kbase) { + k = new BN(k, kbase); - if (key.length > blocksize) { - key = alg(key) - } else if (key.length < blocksize) { - key = Buffer.concat([key, ZEROS], blocksize) - } + return this.curve._wnafMul(this, k); +}; - var ipad = this._ipad = Buffer.allocUnsafe(blocksize) - var opad = this._opad = Buffer.allocUnsafe(blocksize) +JPoint.prototype.eq = function eq(p) { + if (p.type === 'affine') + return this.eq(p.toJ()); - for (var i = 0; i < blocksize; i++) { - ipad[i] = key[i] ^ 0x36 - opad[i] = key[i] ^ 0x5C - } + if (this === p) + return true; - this._hash = [ipad] -} - -inherits(Hmac, Base) + // x1 * z2^2 == x2 * z1^2 + var z2 = this.z.redSqr(); + var pz2 = p.z.redSqr(); + if (this.x.redMul(pz2).redISub(p.x.redMul(z2)).cmpn(0) !== 0) + return false; -Hmac.prototype._update = function (data) { - this._hash.push(data) -} + // y1 * z2^3 == y2 * z1^3 + var z3 = z2.redMul(this.z); + var pz3 = pz2.redMul(p.z); + return this.y.redMul(pz3).redISub(p.y.redMul(z3)).cmpn(0) === 0; +}; -Hmac.prototype._final = function () { - var h = this._alg(Buffer.concat(this._hash)) - return this._alg(Buffer.concat([this._opad, h])) -} -module.exports = Hmac +JPoint.prototype.eqXToP = function eqXToP(x) { + var zs = this.z.redSqr(); + var rx = x.toRed(this.curve.red).redMul(zs); + if (this.x.cmp(rx) === 0) + return true; -},{"cipher-base":161,"inherits":256,"safe-buffer":404}],168:[function(require,module,exports){ -'use strict' + var xc = x.clone(); + var t = this.curve.redN.redMul(zs); + for (;;) { + xc.iadd(this.curve.n); + if (xc.cmp(this.curve.p) >= 0) + return false; -exports.randomBytes = exports.rng = exports.pseudoRandomBytes = exports.prng = require('randombytes') -exports.createHash = exports.Hash = require('create-hash') -exports.createHmac = exports.Hmac = require('create-hmac') + rx.redIAdd(t); + if (this.x.cmp(rx) === 0) + return true; + } +}; -var algos = require('browserify-sign/algos') -var algoKeys = Object.keys(algos) -var hashes = ['sha1', 'sha224', 'sha256', 'sha384', 'sha512', 'md5', 'rmd160'].concat(algoKeys) -exports.getHashes = function () { - return hashes -} +JPoint.prototype.inspect = function inspect() { + if (this.isInfinity()) + return ''; + return ''; +}; -var p = require('pbkdf2') -exports.pbkdf2 = p.pbkdf2 -exports.pbkdf2Sync = p.pbkdf2Sync +JPoint.prototype.isInfinity = function isInfinity() { + // XXX This code assumes that zero is always zero in red + return this.z.cmpn(0) === 0; +}; -var aes = require('browserify-cipher') +},{"../utils":161,"./base":148,"bn.js":86,"inherits":200}],153:[function(require,module,exports){ +'use strict'; -exports.Cipher = aes.Cipher -exports.createCipher = aes.createCipher -exports.Cipheriv = aes.Cipheriv -exports.createCipheriv = aes.createCipheriv -exports.Decipher = aes.Decipher -exports.createDecipher = aes.createDecipher -exports.Decipheriv = aes.Decipheriv -exports.createDecipheriv = aes.createDecipheriv -exports.getCiphers = aes.getCiphers -exports.listCiphers = aes.listCiphers +var curves = exports; -var dh = require('diffie-hellman') +var hash = require('hash.js'); +var curve = require('./curve'); +var utils = require('./utils'); -exports.DiffieHellmanGroup = dh.DiffieHellmanGroup -exports.createDiffieHellmanGroup = dh.createDiffieHellmanGroup -exports.getDiffieHellman = dh.getDiffieHellman -exports.createDiffieHellman = dh.createDiffieHellman -exports.DiffieHellman = dh.DiffieHellman +var assert = utils.assert; -var sign = require('browserify-sign') +function PresetCurve(options) { + if (options.type === 'short') + this.curve = new curve.short(options); + else if (options.type === 'edwards') + this.curve = new curve.edwards(options); + else + this.curve = new curve.mont(options); + this.g = this.curve.g; + this.n = this.curve.n; + this.hash = options.hash; -exports.createSign = sign.createSign -exports.Sign = sign.Sign -exports.createVerify = sign.createVerify -exports.Verify = sign.Verify + assert(this.g.validate(), 'Invalid curve'); + assert(this.g.mul(this.n).isInfinity(), 'Invalid curve, G*N != O'); +} +curves.PresetCurve = PresetCurve; -exports.createECDH = require('create-ecdh') +function defineCurve(name, options) { + Object.defineProperty(curves, name, { + configurable: true, + enumerable: true, + get: function() { + var curve = new PresetCurve(options); + Object.defineProperty(curves, name, { + configurable: true, + enumerable: true, + value: curve, + }); + return curve; + }, + }); +} -var publicEncrypt = require('public-encrypt') +defineCurve('p192', { + type: 'short', + prime: 'p192', + p: 'ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff', + a: 'ffffffff ffffffff ffffffff fffffffe ffffffff fffffffc', + b: '64210519 e59c80e7 0fa7e9ab 72243049 feb8deec c146b9b1', + n: 'ffffffff ffffffff ffffffff 99def836 146bc9b1 b4d22831', + hash: hash.sha256, + gRed: false, + g: [ + '188da80e b03090f6 7cbf20eb 43a18800 f4ff0afd 82ff1012', + '07192b95 ffc8da78 631011ed 6b24cdd5 73f977a1 1e794811', + ], +}); -exports.publicEncrypt = publicEncrypt.publicEncrypt -exports.privateEncrypt = publicEncrypt.privateEncrypt -exports.publicDecrypt = publicEncrypt.publicDecrypt -exports.privateDecrypt = publicEncrypt.privateDecrypt +defineCurve('p224', { + type: 'short', + prime: 'p224', + p: 'ffffffff ffffffff ffffffff ffffffff 00000000 00000000 00000001', + a: 'ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff fffffffe', + b: 'b4050a85 0c04b3ab f5413256 5044b0b7 d7bfd8ba 270b3943 2355ffb4', + n: 'ffffffff ffffffff ffffffff ffff16a2 e0b8f03e 13dd2945 5c5c2a3d', + hash: hash.sha256, + gRed: false, + g: [ + 'b70e0cbd 6bb4bf7f 321390b9 4a03c1d3 56c21122 343280d6 115c1d21', + 'bd376388 b5f723fb 4c22dfe6 cd4375a0 5a074764 44d58199 85007e34', + ], +}); -// the least I can do is make error messages for the rest of the node.js/crypto api. -// ;[ -// 'createCredentials' -// ].forEach(function (name) { -// exports[name] = function () { -// throw new Error([ -// 'sorry, ' + name + ' is not implemented yet', -// 'we accept pull requests', -// 'https://github.com/crypto-browserify/crypto-browserify' -// ].join('\n')) -// } -// }) +defineCurve('p256', { + type: 'short', + prime: null, + p: 'ffffffff 00000001 00000000 00000000 00000000 ffffffff ffffffff ffffffff', + a: 'ffffffff 00000001 00000000 00000000 00000000 ffffffff ffffffff fffffffc', + b: '5ac635d8 aa3a93e7 b3ebbd55 769886bc 651d06b0 cc53b0f6 3bce3c3e 27d2604b', + n: 'ffffffff 00000000 ffffffff ffffffff bce6faad a7179e84 f3b9cac2 fc632551', + hash: hash.sha256, + gRed: false, + g: [ + '6b17d1f2 e12c4247 f8bce6e5 63a440f2 77037d81 2deb33a0 f4a13945 d898c296', + '4fe342e2 fe1a7f9b 8ee7eb4a 7c0f9e16 2bce3357 6b315ece cbb64068 37bf51f5', + ], +}); -var rf = require('randomfill') +defineCurve('p384', { + type: 'short', + prime: null, + p: 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ' + + 'fffffffe ffffffff 00000000 00000000 ffffffff', + a: 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ' + + 'fffffffe ffffffff 00000000 00000000 fffffffc', + b: 'b3312fa7 e23ee7e4 988e056b e3f82d19 181d9c6e fe814112 0314088f ' + + '5013875a c656398d 8a2ed19d 2a85c8ed d3ec2aef', + n: 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff c7634d81 ' + + 'f4372ddf 581a0db2 48b0a77a ecec196a ccc52973', + hash: hash.sha384, + gRed: false, + g: [ + 'aa87ca22 be8b0537 8eb1c71e f320ad74 6e1d3b62 8ba79b98 59f741e0 82542a38 ' + + '5502f25d bf55296c 3a545e38 72760ab7', + '3617de4a 96262c6f 5d9e98bf 9292dc29 f8f41dbd 289a147c e9da3113 b5f0b8c0 ' + + '0a60b1ce 1d7e819d 7a431d7c 90ea0e5f', + ], +}); -exports.randomFill = rf.randomFill -exports.randomFillSync = rf.randomFillSync +defineCurve('p521', { + type: 'short', + prime: null, + p: '000001ff ffffffff ffffffff ffffffff ffffffff ffffffff ' + + 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ' + + 'ffffffff ffffffff ffffffff ffffffff ffffffff', + a: '000001ff ffffffff ffffffff ffffffff ffffffff ffffffff ' + + 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ' + + 'ffffffff ffffffff ffffffff ffffffff fffffffc', + b: '00000051 953eb961 8e1c9a1f 929a21a0 b68540ee a2da725b ' + + '99b315f3 b8b48991 8ef109e1 56193951 ec7e937b 1652c0bd ' + + '3bb1bf07 3573df88 3d2c34f1 ef451fd4 6b503f00', + n: '000001ff ffffffff ffffffff ffffffff ffffffff ffffffff ' + + 'ffffffff ffffffff fffffffa 51868783 bf2f966b 7fcc0148 ' + + 'f709a5d0 3bb5c9b8 899c47ae bb6fb71e 91386409', + hash: hash.sha512, + gRed: false, + g: [ + '000000c6 858e06b7 0404e9cd 9e3ecb66 2395b442 9c648139 ' + + '053fb521 f828af60 6b4d3dba a14b5e77 efe75928 fe1dc127 ' + + 'a2ffa8de 3348b3c1 856a429b f97e7e31 c2e5bd66', + '00000118 39296a78 9a3bc004 5c8a5fb4 2c7d1bd9 98f54449 ' + + '579b4468 17afbd17 273e662c 97ee7299 5ef42640 c550b901 ' + + '3fad0761 353c7086 a272c240 88be9476 9fd16650', + ], +}); -exports.createCredentials = function () { - throw new Error([ - 'sorry, createCredentials is not implemented yet', - 'we accept pull requests', - 'https://github.com/crypto-browserify/crypto-browserify' - ].join('\n')) -} +defineCurve('curve25519', { + type: 'mont', + prime: 'p25519', + p: '7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed', + a: '76d06', + b: '1', + n: '1000000000000000 0000000000000000 14def9dea2f79cd6 5812631a5cf5d3ed', + hash: hash.sha256, + gRed: false, + g: [ + '9', + ], +}); -exports.constants = { - 'DH_CHECK_P_NOT_SAFE_PRIME': 2, - 'DH_CHECK_P_NOT_PRIME': 1, - 'DH_UNABLE_TO_CHECK_GENERATOR': 4, - 'DH_NOT_SUITABLE_GENERATOR': 8, - 'NPN_ENABLED': 1, - 'ALPN_ENABLED': 1, - 'RSA_PKCS1_PADDING': 1, - 'RSA_SSLV23_PADDING': 2, - 'RSA_NO_PADDING': 3, - 'RSA_PKCS1_OAEP_PADDING': 4, - 'RSA_X931_PADDING': 5, - 'RSA_PKCS1_PSS_PADDING': 6, - 'POINT_CONVERSION_COMPRESSED': 2, - 'POINT_CONVERSION_UNCOMPRESSED': 4, - 'POINT_CONVERSION_HYBRID': 6 -} +defineCurve('ed25519', { + type: 'edwards', + prime: 'p25519', + p: '7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed', + a: '-1', + c: '1', + // -121665 * (121666^(-1)) (mod P) + d: '52036cee2b6ffe73 8cc740797779e898 00700a4d4141d8ab 75eb4dca135978a3', + n: '1000000000000000 0000000000000000 14def9dea2f79cd6 5812631a5cf5d3ed', + hash: hash.sha256, + gRed: false, + g: [ + '216936d3cd6e53fec0a4e231fdd6dc5c692cc7609525a7b2c9562d608f25d51a', -},{"browserify-cipher":111,"browserify-sign":118,"browserify-sign/algos":115,"create-ecdh":162,"create-hash":164,"create-hmac":166,"diffie-hellman":180,"pbkdf2":384,"public-encrypt":392,"randombytes":400,"randomfill":401}],169:[function(require,module,exports){ -'use strict' + // 4/5 + '6666666666666666666666666666666666666666666666666666666666666658', + ], +}); -const { AbstractChainedBatch } = require('abstract-leveldown') -const kOperations = Symbol('operations') +var pre; +try { + pre = require('./precomputed/secp256k1'); +} catch (e) { + pre = undefined; +} -module.exports = class DeferredChainedBatch extends AbstractChainedBatch { - constructor (db) { - super(db) - this[kOperations] = [] - } +defineCurve('secp256k1', { + type: 'short', + prime: 'k256', + p: 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe fffffc2f', + a: '0', + b: '7', + n: 'ffffffff ffffffff ffffffff fffffffe baaedce6 af48a03b bfd25e8c d0364141', + h: '1', + hash: hash.sha256, - _put (key, value, options) { - this[kOperations].push({ ...options, type: 'put', key, value }) - } + // Precomputed endomorphism + beta: '7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee', + lambda: '5363ad4cc05c30e0a5261c028812645a122e22ea20816678df02967c1b23bd72', + basis: [ + { + a: '3086d221a7d46bcde86c90e49284eb15', + b: '-e4437ed6010e88286f547fa90abfe4c3', + }, + { + a: '114ca50f7a8e2f3f657c1108d9d44cfd8', + b: '3086d221a7d46bcde86c90e49284eb15', + }, + ], - _del (key, options) { - this[kOperations].push({ ...options, type: 'del', key }) - } + gRed: false, + g: [ + '79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798', + '483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8', + pre, + ], +}); - _clear () { - this[kOperations] = [] - } +},{"./curve":150,"./precomputed/secp256k1":160,"./utils":161,"hash.js":185}],154:[function(require,module,exports){ +'use strict'; - _write (options, callback) { - // AbstractChainedBatch would call _batch(), we call batch() - this.db.batch(this[kOperations], options, callback) - } -} +var BN = require('bn.js'); +var HmacDRBG = require('hmac-drbg'); +var utils = require('../utils'); +var curves = require('../curves'); +var rand = require('brorand'); +var assert = utils.assert; -},{"abstract-leveldown":30}],170:[function(require,module,exports){ -'use strict' +var KeyPair = require('./key'); +var Signature = require('./signature'); -const { AbstractIterator } = require('abstract-leveldown') -const inherits = require('inherits') -const getCallback = require('./util').getCallback +function EC(options) { + if (!(this instanceof EC)) + return new EC(options); -const kOptions = Symbol('options') -const kIterator = Symbol('iterator') -const kOperations = Symbol('operations') -const kPromise = Symbol('promise') + // Shortcut `elliptic.ec(curve-name)` + if (typeof options === 'string') { + assert(Object.prototype.hasOwnProperty.call(curves, options), + 'Unknown curve ' + options); -function DeferredIterator (db, options) { - AbstractIterator.call(this, db) + options = curves[options]; + } - this[kOptions] = options - this[kIterator] = null - this[kOperations] = [] -} + // Shortcut for `elliptic.ec(elliptic.curves.curveName)` + if (options instanceof curves.PresetCurve) + options = { curve: options }; -inherits(DeferredIterator, AbstractIterator) + this.curve = options.curve.curve; + this.n = this.curve.n; + this.nh = this.n.ushrn(1); + this.g = this.curve.g; -DeferredIterator.prototype.setDb = function (db) { - this[kIterator] = db.iterator(this[kOptions]) + // Point on curve + this.g = options.curve.g; + this.g.precompute(options.curve.n.bitLength() + 1); - for (const op of this[kOperations].splice(0, this[kOperations].length)) { - this[kIterator][op.method](...op.args) - } + // Hash for function for DRBG + this.hash = options.hash || options.curve.hash; } +module.exports = EC; -DeferredIterator.prototype.next = function (...args) { - if (this.db.status === 'open') { - return this[kIterator].next(...args) - } - - const callback = getCallback(args, kPromise, function map (key, value) { - if (key === undefined && value === undefined) { - return undefined - } else { - return [key, value] - } - }) +EC.prototype.keyPair = function keyPair(options) { + return new KeyPair(this, options); +}; - if (this.db.status === 'opening') { - this[kOperations].push({ method: 'next', args }) - } else { - this._nextTick(callback, new Error('Database is not open')) - } +EC.prototype.keyFromPrivate = function keyFromPrivate(priv, enc) { + return KeyPair.fromPrivate(this, priv, enc); +}; - return callback[kPromise] || this -} +EC.prototype.keyFromPublic = function keyFromPublic(pub, enc) { + return KeyPair.fromPublic(this, pub, enc); +}; -DeferredIterator.prototype.seek = function (...args) { - if (this.db.status === 'open') { - this[kIterator].seek(...args) - } else if (this.db.status === 'opening') { - this[kOperations].push({ method: 'seek', args }) - } else { - throw new Error('Database is not open') - } -} +EC.prototype.genKeyPair = function genKeyPair(options) { + if (!options) + options = {}; -DeferredIterator.prototype.end = function (...args) { - if (this.db.status === 'open') { - return this[kIterator].end(...args) - } + // Instantiate Hmac_DRBG + var drbg = new HmacDRBG({ + hash: this.hash, + pers: options.pers, + persEnc: options.persEnc || 'utf8', + entropy: options.entropy || rand(this.hash.hmacStrength), + entropyEnc: options.entropy && options.entropyEnc || 'utf8', + nonce: this.n.toArray(), + }); - const callback = getCallback(args, kPromise) + var bytes = this.n.byteLength(); + var ns2 = this.n.sub(new BN(2)); + for (;;) { + var priv = new BN(drbg.generate(bytes)); + if (priv.cmp(ns2) > 0) + continue; - if (this.db.status === 'opening') { - this[kOperations].push({ method: 'end', args }) - } else { - this._nextTick(callback, new Error('Database is not open')) + priv.iaddn(1); + return this.keyFromPrivate(priv); } +}; - return callback[kPromise] || this -} +EC.prototype._truncateToN = function _truncateToN(msg, truncOnly) { + var delta = msg.byteLength() * 8 - this.n.bitLength(); + if (delta > 0) + msg = msg.ushrn(delta); + if (!truncOnly && msg.cmp(this.n) >= 0) + return msg.sub(this.n); + else + return msg; +}; -for (const method of ['next', 'seek', 'end']) { - DeferredIterator.prototype['_' + method] = function () { - /* istanbul ignore next: assertion */ - throw new Error('Did not expect private method to be called: ' + method) +EC.prototype.sign = function sign(msg, key, enc, options) { + if (typeof enc === 'object') { + options = enc; + enc = null; } -} - -module.exports = DeferredIterator + if (!options) + options = {}; -},{"./util":172,"abstract-leveldown":30,"inherits":256}],171:[function(require,module,exports){ -'use strict' + key = this.keyFromPrivate(key, enc); + msg = this._truncateToN(new BN(msg, 16)); -const { AbstractLevelDOWN } = require('abstract-leveldown') -const inherits = require('inherits') -const DeferredIterator = require('./deferred-iterator') -const DeferredChainedBatch = require('./deferred-chained-batch') -const getCallback = require('./util').getCallback + // Zero-extend key to provide enough entropy + var bytes = this.n.byteLength(); + var bkey = key.getPrivate().toArray('be', bytes); -const deferrables = ['put', 'get', 'getMany', 'del', 'batch', 'clear'] -const optionalDeferrables = ['approximateSize', 'compactRange'] + // Zero-extend nonce to have the same byte size as N + var nonce = msg.toArray('be', bytes); -const kInnerDb = Symbol('innerDb') -const kOperations = Symbol('operations') -const kPromise = Symbol('promise') + // Instantiate Hmac_DRBG + var drbg = new HmacDRBG({ + hash: this.hash, + entropy: bkey, + nonce: nonce, + pers: options.pers, + persEnc: options.persEnc || 'utf8', + }); -function DeferredLevelDOWN (db) { - AbstractLevelDOWN.call(this, db.supports || {}) + // Number of bytes to generate + var ns1 = this.n.sub(new BN(1)); - // TODO (future major): remove this fallback; db must have manifest that - // declares approximateSize and compactRange in additionalMethods. - for (const m of optionalDeferrables) { - if (typeof db[m] === 'function' && !this.supports.additionalMethods[m]) { - this.supports.additionalMethods[m] = true - } - } + for (var iter = 0; ; iter++) { + var k = options.k ? + options.k(iter) : + new BN(drbg.generate(this.n.byteLength())); + k = this._truncateToN(k, true); + if (k.cmpn(1) <= 0 || k.cmp(ns1) >= 0) + continue; - this[kInnerDb] = db - this[kOperations] = [] + var kp = this.g.mul(k); + if (kp.isInfinity()) + continue; - implement(this) -} + var kpX = kp.getX(); + var r = kpX.umod(this.n); + if (r.cmpn(0) === 0) + continue; -inherits(DeferredLevelDOWN, AbstractLevelDOWN) + var s = k.invm(this.n).mul(r.mul(key.getPrivate()).iadd(msg)); + s = s.umod(this.n); + if (s.cmpn(0) === 0) + continue; -DeferredLevelDOWN.prototype.type = 'deferred-leveldown' + var recoveryParam = (kp.getY().isOdd() ? 1 : 0) | + (kpX.cmp(r) !== 0 ? 2 : 0); -// Backwards compatibility for reachdown and subleveldown -Object.defineProperty(DeferredLevelDOWN.prototype, '_db', { - enumerable: true, - get () { - return this[kInnerDb] + // Use complement of `s`, if it is > `n / 2` + if (options.canonical && s.cmp(this.nh) > 0) { + s = this.n.sub(s); + recoveryParam ^= 1; + } + + return new Signature({ r: r, s: s, recoveryParam: recoveryParam }); } -}) +}; -DeferredLevelDOWN.prototype._open = function (options, callback) { - const onopen = (err) => { - if (err || this[kInnerDb].status !== 'open') { - // TODO: reject scheduled operations - return callback(err || new Error('Database is not open')) - } +EC.prototype.verify = function verify(msg, signature, key, enc) { + msg = this._truncateToN(new BN(msg, 16)); + key = this.keyFromPublic(key, enc); + signature = new Signature(signature, 'hex'); - const operations = this[kOperations] - this[kOperations] = [] + // Perform primitive values validation + var r = signature.r; + var s = signature.s; + if (r.cmpn(1) < 0 || r.cmp(this.n) >= 0) + return false; + if (s.cmpn(1) < 0 || s.cmp(this.n) >= 0) + return false; - for (const op of operations) { - if (op.iterator) { - op.iterator.setDb(this[kInnerDb]) - } else { - this[kInnerDb][op.method](...op.args) - } - } + // Validate signature + var sinv = s.invm(this.n); + var u1 = sinv.mul(msg).umod(this.n); + var u2 = sinv.mul(r).umod(this.n); + var p; - /* istanbul ignore if: assertion */ - if (this[kOperations].length > 0) { - throw new Error('Did not expect further operations') - } + if (!this.curve._maxwellTrick) { + p = this.g.mulAdd(u1, key.getPublic(), u2); + if (p.isInfinity()) + return false; - callback() + return p.getX().umod(this.n).cmp(r) === 0; } - if (this[kInnerDb].status === 'new' || this[kInnerDb].status === 'closed') { - this[kInnerDb].open(options, onopen) - } else { - this._nextTick(onopen) - } -} + // NOTE: Greg Maxwell's trick, inspired by: + // https://git.io/vad3K -DeferredLevelDOWN.prototype._close = function (callback) { - this[kInnerDb].close(callback) -} + p = this.g.jmulAdd(u1, key.getPublic(), u2); + if (p.isInfinity()) + return false; -DeferredLevelDOWN.prototype._isOperational = function () { - return this.status === 'opening' -} + // Compare `p.x` of Jacobian point with `r`, + // this will do `p.x == r * p.z^2` instead of multiplying `p.x` by the + // inverse of `p.z^2` + return p.eqXToP(r); +}; -function implement (self) { - const additionalMethods = Object.keys(self.supports.additionalMethods) +EC.prototype.recoverPubKey = function(msg, signature, j, enc) { + assert((3 & j) === j, 'The recovery param is more than two bits'); + signature = new Signature(signature, enc); - for (const method of deferrables.concat(additionalMethods)) { - // Override the public rather than private methods to cover cases where abstract-leveldown - // has a fast-path like on db.batch([]) which bypasses _batch() because the array is empty. - self[method] = function (...args) { - if (method === 'batch' && args.length === 0) { - return new DeferredChainedBatch(this) - } else if (this.status === 'open') { - return this[kInnerDb][method](...args) - } + var n = this.n; + var e = new BN(msg); + var r = signature.r; + var s = signature.s; - const callback = getCallback(args, kPromise) + // A set LSB signifies that the y-coordinate is odd + var isYOdd = j & 1; + var isSecondKey = j >> 1; + if (r.cmp(this.curve.p.umod(this.curve.n)) >= 0 && isSecondKey) + throw new Error('Unable to find sencond key candinate'); - if (this.status === 'opening') { - this[kOperations].push({ method, args }) - } else { - this._nextTick(callback, new Error('Database is not open')) - } + // 1.1. Let x = r + jn. + if (isSecondKey) + r = this.curve.pointFromX(r.add(this.curve.n), isYOdd); + else + r = this.curve.pointFromX(r, isYOdd); - return callback[kPromise] - } - } + var rInv = signature.r.invm(n); + var s1 = n.sub(e).mul(rInv).umod(n); + var s2 = s.mul(rInv).umod(n); - self.iterator = function (options) { - if (this.status === 'open') { - return this[kInnerDb].iterator(options) - } else if (this.status === 'opening') { - const iterator = new DeferredIterator(this, options) - this[kOperations].push({ iterator }) - return iterator - } else { - throw new Error('Database is not open') - } - } + // 1.6.1 Compute Q = r^-1 (sR - eG) + // Q = r^-1 (sR + -eG) + return this.g.mulAdd(s1, r, s2); +}; - for (const method of deferrables.concat(['iterator'])) { - self['_' + method] = function () { - /* istanbul ignore next: assertion */ - throw new Error('Did not expect private method to be called: ' + method) - } - } -} +EC.prototype.getKeyRecoveryParam = function(e, signature, Q, enc) { + signature = new Signature(signature, enc); + if (signature.recoveryParam !== null) + return signature.recoveryParam; -module.exports = DeferredLevelDOWN -module.exports.DeferredIterator = DeferredIterator + for (var i = 0; i < 4; i++) { + var Qprime; + try { + Qprime = this.recoverPubKey(e, signature, i); + } catch (e) { + continue; + } -},{"./deferred-chained-batch":169,"./deferred-iterator":170,"./util":172,"abstract-leveldown":30,"inherits":256}],172:[function(require,module,exports){ -'use strict' + if (Qprime.eq(Q)) + return i; + } + throw new Error('Unable to find valid recovery factor'); +}; -exports.getCallback = function (args, symbol, map) { - let callback = args[args.length - 1] +},{"../curves":153,"../utils":161,"./key":155,"./signature":156,"bn.js":86,"brorand":87,"hmac-drbg":198}],155:[function(require,module,exports){ +'use strict'; - if (typeof callback !== 'function') { - const promise = new Promise((resolve, reject) => { - args.push(callback = function (err, ...results) { - if (err) reject(err) - else resolve(map ? map(...results) : results[0]) - }) - }) +var BN = require('bn.js'); +var utils = require('../utils'); +var assert = utils.assert; - callback[symbol] = promise - } +function KeyPair(ec, options) { + this.ec = ec; + this.priv = null; + this.pub = null; - return callback + // KeyPair(ec, { priv: ..., pub: ... }) + if (options.priv) + this._importPrivate(options.priv, options.privEnc); + if (options.pub) + this._importPublic(options.pub, options.pubEnc); } +module.exports = KeyPair; -},{}],173:[function(require,module,exports){ -'use strict'; - -var $defineProperty = require('es-define-property'); +KeyPair.fromPublic = function fromPublic(ec, pub, enc) { + if (pub instanceof KeyPair) + return pub; -var $SyntaxError = require('es-errors/syntax'); -var $TypeError = require('es-errors/type'); + return new KeyPair(ec, { + pub: pub, + pubEnc: enc, + }); +}; -var gopd = require('gopd'); +KeyPair.fromPrivate = function fromPrivate(ec, priv, enc) { + if (priv instanceof KeyPair) + return priv; -/** @type {import('.')} */ -module.exports = function defineDataProperty( - obj, - property, - value -) { - if (!obj || (typeof obj !== 'object' && typeof obj !== 'function')) { - throw new $TypeError('`obj` must be an object or a function`'); - } - if (typeof property !== 'string' && typeof property !== 'symbol') { - throw new $TypeError('`property` must be a string or a symbol`'); - } - if (arguments.length > 3 && typeof arguments[3] !== 'boolean' && arguments[3] !== null) { - throw new $TypeError('`nonEnumerable`, if provided, must be a boolean or null'); - } - if (arguments.length > 4 && typeof arguments[4] !== 'boolean' && arguments[4] !== null) { - throw new $TypeError('`nonWritable`, if provided, must be a boolean or null'); - } - if (arguments.length > 5 && typeof arguments[5] !== 'boolean' && arguments[5] !== null) { - throw new $TypeError('`nonConfigurable`, if provided, must be a boolean or null'); - } - if (arguments.length > 6 && typeof arguments[6] !== 'boolean') { - throw new $TypeError('`loose`, if provided, must be a boolean'); - } + return new KeyPair(ec, { + priv: priv, + privEnc: enc, + }); +}; - var nonEnumerable = arguments.length > 3 ? arguments[3] : null; - var nonWritable = arguments.length > 4 ? arguments[4] : null; - var nonConfigurable = arguments.length > 5 ? arguments[5] : null; - var loose = arguments.length > 6 ? arguments[6] : false; +KeyPair.prototype.validate = function validate() { + var pub = this.getPublic(); - /* @type {false | TypedPropertyDescriptor} */ - var desc = !!gopd && gopd(obj, property); + if (pub.isInfinity()) + return { result: false, reason: 'Invalid public key' }; + if (!pub.validate()) + return { result: false, reason: 'Public key is not a point' }; + if (!pub.mul(this.ec.curve.n).isInfinity()) + return { result: false, reason: 'Public key * N != O' }; - if ($defineProperty) { - $defineProperty(obj, property, { - configurable: nonConfigurable === null && desc ? desc.configurable : !nonConfigurable, - enumerable: nonEnumerable === null && desc ? desc.enumerable : !nonEnumerable, - value: value, - writable: nonWritable === null && desc ? desc.writable : !nonWritable - }); - } else if (loose || (!nonEnumerable && !nonWritable && !nonConfigurable)) { - // must fall back to [[Set]], and was not explicitly asked to make non-enumerable, non-writable, or non-configurable - obj[property] = value; // eslint-disable-line no-param-reassign - } else { - throw new $SyntaxError('This environment does not support defining a property as non-configurable, non-writable, or non-enumerable.'); - } + return { result: true, reason: null }; }; -},{"es-define-property":203,"es-errors/syntax":208,"es-errors/type":209,"gopd":218}],174:[function(require,module,exports){ -'use strict'; +KeyPair.prototype.getPublic = function getPublic(compact, enc) { + // compact is optional argument + if (typeof compact === 'string') { + enc = compact; + compact = null; + } -exports.utils = require('./des/utils'); -exports.Cipher = require('./des/cipher'); -exports.DES = require('./des/des'); -exports.CBC = require('./des/cbc'); -exports.EDE = require('./des/ede'); + if (!this.pub) + this.pub = this.ec.g.mul(this.priv); -},{"./des/cbc":175,"./des/cipher":176,"./des/des":177,"./des/ede":178,"./des/utils":179}],175:[function(require,module,exports){ -'use strict'; + if (!enc) + return this.pub; -var assert = require('minimalistic-assert'); -var inherits = require('inherits'); + return this.pub.encode(enc, compact); +}; -var proto = {}; +KeyPair.prototype.getPrivate = function getPrivate(enc) { + if (enc === 'hex') + return this.priv.toString(16, 2); + else + return this.priv; +}; -function CBCState(iv) { - assert.equal(iv.length, 8, 'Invalid IV length'); +KeyPair.prototype._importPrivate = function _importPrivate(key, enc) { + this.priv = new BN(key, enc || 16); - this.iv = new Array(8); - for (var i = 0; i < this.iv.length; i++) - this.iv[i] = iv[i]; -} + // Ensure that the priv won't be bigger than n, otherwise we may fail + // in fixed multiplication method + this.priv = this.priv.umod(this.ec.curve.n); +}; -function instantiate(Base) { - function CBC(options) { - Base.call(this, options); - this._cbcInit(); +KeyPair.prototype._importPublic = function _importPublic(key, enc) { + if (key.x || key.y) { + // Montgomery points only have an `x` coordinate. + // Weierstrass/Edwards points on the other hand have both `x` and + // `y` coordinates. + if (this.ec.curve.type === 'mont') { + assert(key.x, 'Need x coordinate'); + } else if (this.ec.curve.type === 'short' || + this.ec.curve.type === 'edwards') { + assert(key.x && key.y, 'Need both x and y coordinate'); + } + this.pub = this.ec.curve.point(key.x, key.y); + return; } - inherits(CBC, Base); + this.pub = this.ec.curve.decodePoint(key, enc); +}; - var keys = Object.keys(proto); - for (var i = 0; i < keys.length; i++) { - var key = keys[i]; - CBC.prototype[key] = proto[key]; +// ECDH +KeyPair.prototype.derive = function derive(pub) { + if(!pub.validate()) { + assert(pub.validate(), 'public point not validated'); } - - CBC.create = function create(options) { - return new CBC(options); - }; - - return CBC; -} - -exports.instantiate = instantiate; - -proto._cbcInit = function _cbcInit() { - var state = new CBCState(this.options.iv); - this._cbcState = state; + return pub.mul(this.priv).getX(); }; -proto._update = function _update(inp, inOff, out, outOff) { - var state = this._cbcState; - var superProto = this.constructor.super_.prototype; - - var iv = state.iv; - if (this.type === 'encrypt') { - for (var i = 0; i < this.blockSize; i++) - iv[i] ^= inp[inOff + i]; - - superProto._update.call(this, iv, 0, out, outOff); - - for (var i = 0; i < this.blockSize; i++) - iv[i] = out[outOff + i]; - } else { - superProto._update.call(this, inp, inOff, out, outOff); +// ECDSA +KeyPair.prototype.sign = function sign(msg, enc, options) { + return this.ec.sign(msg, this, enc, options); +}; - for (var i = 0; i < this.blockSize; i++) - out[outOff + i] ^= iv[i]; +KeyPair.prototype.verify = function verify(msg, signature) { + return this.ec.verify(msg, signature, this); +}; - for (var i = 0; i < this.blockSize; i++) - iv[i] = inp[inOff + i]; - } +KeyPair.prototype.inspect = function inspect() { + return ''; }; -},{"inherits":256,"minimalistic-assert":301}],176:[function(require,module,exports){ +},{"../utils":161,"bn.js":86}],156:[function(require,module,exports){ 'use strict'; -var assert = require('minimalistic-assert'); - -function Cipher(options) { - this.options = options; - - this.type = this.options.type; - this.blockSize = 8; - this._init(); +var BN = require('bn.js'); - this.buffer = new Array(this.blockSize); - this.bufferOff = 0; -} -module.exports = Cipher; +var utils = require('../utils'); +var assert = utils.assert; -Cipher.prototype._init = function _init() { - // Might be overrided -}; +function Signature(options, enc) { + if (options instanceof Signature) + return options; -Cipher.prototype.update = function update(data) { - if (data.length === 0) - return []; + if (this._importDER(options, enc)) + return; - if (this.type === 'decrypt') - return this._updateDecrypt(data); + assert(options.r && options.s, 'Signature without r or s'); + this.r = new BN(options.r, 16); + this.s = new BN(options.s, 16); + if (options.recoveryParam === undefined) + this.recoveryParam = null; else - return this._updateEncrypt(data); -}; - -Cipher.prototype._buffer = function _buffer(data, off) { - // Append data to buffer - var min = Math.min(this.buffer.length - this.bufferOff, data.length - off); - for (var i = 0; i < min; i++) - this.buffer[this.bufferOff + i] = data[off + i]; - this.bufferOff += min; - - // Shift next - return min; -}; + this.recoveryParam = options.recoveryParam; +} +module.exports = Signature; -Cipher.prototype._flushBuffer = function _flushBuffer(out, off) { - this._update(this.buffer, 0, out, off); - this.bufferOff = 0; - return this.blockSize; -}; +function Position() { + this.place = 0; +} -Cipher.prototype._updateEncrypt = function _updateEncrypt(data) { - var inputOff = 0; - var outputOff = 0; +function getLength(buf, p) { + var initial = buf[p.place++]; + if (!(initial & 0x80)) { + return initial; + } + var octetLen = initial & 0xf; - var count = ((this.bufferOff + data.length) / this.blockSize) | 0; - var out = new Array(count * this.blockSize); + // Indefinite length or overflow + if (octetLen === 0 || octetLen > 4) { + return false; + } - if (this.bufferOff !== 0) { - inputOff += this._buffer(data, inputOff); + if(buf[p.place] === 0x00) { + return false; + } - if (this.bufferOff === this.buffer.length) - outputOff += this._flushBuffer(out, outputOff); + var val = 0; + for (var i = 0, off = p.place; i < octetLen; i++, off++) { + val <<= 8; + val |= buf[off]; + val >>>= 0; } - // Write blocks - var max = data.length - ((data.length - inputOff) % this.blockSize); - for (; inputOff < max; inputOff += this.blockSize) { - this._update(data, inputOff, out, outputOff); - outputOff += this.blockSize; + // Leading zeroes + if (val <= 0x7f) { + return false; } - // Queue rest - for (; inputOff < data.length; inputOff++, this.bufferOff++) - this.buffer[this.bufferOff] = data[inputOff]; + p.place = off; + return val; +} - return out; -}; +function rmPadding(buf) { + var i = 0; + var len = buf.length - 1; + while (!buf[i] && !(buf[i + 1] & 0x80) && i < len) { + i++; + } + if (i === 0) { + return buf; + } + return buf.slice(i); +} -Cipher.prototype._updateDecrypt = function _updateDecrypt(data) { - var inputOff = 0; - var outputOff = 0; - - var count = Math.ceil((this.bufferOff + data.length) / this.blockSize) - 1; - var out = new Array(count * this.blockSize); - - // TODO(indutny): optimize it, this is far from optimal - for (; count > 0; count--) { - inputOff += this._buffer(data, inputOff); - outputOff += this._flushBuffer(out, outputOff); +Signature.prototype._importDER = function _importDER(data, enc) { + data = utils.toArray(data, enc); + var p = new Position(); + if (data[p.place++] !== 0x30) { + return false; } - - // Buffer rest of the input - inputOff += this._buffer(data, inputOff); - - return out; -}; - -Cipher.prototype.final = function final(buffer) { - var first; - if (buffer) - first = this.update(buffer); - - var last; - if (this.type === 'encrypt') - last = this._finalEncrypt(); - else - last = this._finalDecrypt(); - - if (first) - return first.concat(last); - else - return last; -}; - -Cipher.prototype._pad = function _pad(buffer, off) { - if (off === 0) + var len = getLength(data, p); + if (len === false) { + return false; + } + if ((len + p.place) !== data.length) { + return false; + } + if (data[p.place++] !== 0x02) { + return false; + } + var rlen = getLength(data, p); + if (rlen === false) { + return false; + } + if ((data[p.place] & 128) !== 0) { + return false; + } + var r = data.slice(p.place, rlen + p.place); + p.place += rlen; + if (data[p.place++] !== 0x02) { + return false; + } + var slen = getLength(data, p); + if (slen === false) { + return false; + } + if (data.length !== slen + p.place) { return false; + } + if ((data[p.place] & 128) !== 0) { + return false; + } + var s = data.slice(p.place, slen + p.place); + if (r[0] === 0) { + if (r[1] & 0x80) { + r = r.slice(1); + } else { + // Leading zeroes + return false; + } + } + if (s[0] === 0) { + if (s[1] & 0x80) { + s = s.slice(1); + } else { + // Leading zeroes + return false; + } + } - while (off < buffer.length) - buffer[off++] = 0; + this.r = new BN(r); + this.s = new BN(s); + this.recoveryParam = null; return true; }; -Cipher.prototype._finalEncrypt = function _finalEncrypt() { - if (!this._pad(this.buffer, this.bufferOff)) - return []; +function constructLength(arr, len) { + if (len < 0x80) { + arr.push(len); + return; + } + var octets = 1 + (Math.log(len) / Math.LN2 >>> 3); + arr.push(octets | 0x80); + while (--octets) { + arr.push((len >>> (octets << 3)) & 0xff); + } + arr.push(len); +} - var out = new Array(this.blockSize); - this._update(this.buffer, 0, out, 0); - return out; -}; +Signature.prototype.toDER = function toDER(enc) { + var r = this.r.toArray(); + var s = this.s.toArray(); -Cipher.prototype._unpad = function _unpad(buffer) { - return buffer; -}; + // Pad values + if (r[0] & 0x80) + r = [ 0 ].concat(r); + // Pad values + if (s[0] & 0x80) + s = [ 0 ].concat(s); -Cipher.prototype._finalDecrypt = function _finalDecrypt() { - assert.equal(this.bufferOff, this.blockSize, 'Not enough data to decrypt'); - var out = new Array(this.blockSize); - this._flushBuffer(out, 0); + r = rmPadding(r); + s = rmPadding(s); - return this._unpad(out); + while (!s[0] && !(s[1] & 0x80)) { + s = s.slice(1); + } + var arr = [ 0x02 ]; + constructLength(arr, r.length); + arr = arr.concat(r); + arr.push(0x02); + constructLength(arr, s.length); + var backHalf = arr.concat(s); + var res = [ 0x30 ]; + constructLength(res, backHalf.length); + res = res.concat(backHalf); + return utils.encode(res, enc); }; -},{"minimalistic-assert":301}],177:[function(require,module,exports){ +},{"../utils":161,"bn.js":86}],157:[function(require,module,exports){ 'use strict'; -var assert = require('minimalistic-assert'); -var inherits = require('inherits'); - -var utils = require('./utils'); -var Cipher = require('./cipher'); +var hash = require('hash.js'); +var curves = require('../curves'); +var utils = require('../utils'); +var assert = utils.assert; +var parseBytes = utils.parseBytes; +var KeyPair = require('./key'); +var Signature = require('./signature'); -function DESState() { - this.tmp = new Array(2); - this.keys = null; -} +function EDDSA(curve) { + assert(curve === 'ed25519', 'only tested with ed25519 so far'); -function DES(options) { - Cipher.call(this, options); + if (!(this instanceof EDDSA)) + return new EDDSA(curve); - var state = new DESState(); - this._desState = state; + curve = curves[curve].curve; + this.curve = curve; + this.g = curve.g; + this.g.precompute(curve.n.bitLength() + 1); - this.deriveKeys(state, options.key); + this.pointClass = curve.point().constructor; + this.encodingLength = Math.ceil(curve.n.bitLength() / 8); + this.hash = hash.sha512; } -inherits(DES, Cipher); -module.exports = DES; -DES.create = function create(options) { - return new DES(options); +module.exports = EDDSA; + +/** +* @param {Array|String} message - message bytes +* @param {Array|String|KeyPair} secret - secret bytes or a keypair +* @returns {Signature} - signature +*/ +EDDSA.prototype.sign = function sign(message, secret) { + message = parseBytes(message); + var key = this.keyFromSecret(secret); + var r = this.hashInt(key.messagePrefix(), message); + var R = this.g.mul(r); + var Rencoded = this.encodePoint(R); + var s_ = this.hashInt(Rencoded, key.pubBytes(), message) + .mul(key.priv()); + var S = r.add(s_).umod(this.curve.n); + return this.makeSignature({ R: R, S: S, Rencoded: Rencoded }); }; -var shiftTable = [ - 1, 1, 2, 2, 2, 2, 2, 2, - 1, 2, 2, 2, 2, 2, 2, 1 -]; +/** +* @param {Array} message - message bytes +* @param {Array|String|Signature} sig - sig bytes +* @param {Array|String|Point|KeyPair} pub - public key +* @returns {Boolean} - true if public key matches sig of message +*/ +EDDSA.prototype.verify = function verify(message, sig, pub) { + message = parseBytes(message); + sig = this.makeSignature(sig); + if (sig.S().gte(sig.eddsa.curve.n) || sig.S().isNeg()) { + return false; + } + var key = this.keyFromPublic(pub); + var h = this.hashInt(sig.Rencoded(), key.pubBytes(), message); + var SG = this.g.mul(sig.S()); + var RplusAh = sig.R().add(key.pub().mul(h)); + return RplusAh.eq(SG); +}; -DES.prototype.deriveKeys = function deriveKeys(state, key) { - state.keys = new Array(16 * 2); +EDDSA.prototype.hashInt = function hashInt() { + var hash = this.hash(); + for (var i = 0; i < arguments.length; i++) + hash.update(arguments[i]); + return utils.intFromLE(hash.digest()).umod(this.curve.n); +}; - assert.equal(key.length, this.blockSize, 'Invalid key length'); +EDDSA.prototype.keyFromPublic = function keyFromPublic(pub) { + return KeyPair.fromPublic(this, pub); +}; - var kL = utils.readUInt32BE(key, 0); - var kR = utils.readUInt32BE(key, 4); +EDDSA.prototype.keyFromSecret = function keyFromSecret(secret) { + return KeyPair.fromSecret(this, secret); +}; - utils.pc1(kL, kR, state.tmp, 0); - kL = state.tmp[0]; - kR = state.tmp[1]; - for (var i = 0; i < state.keys.length; i += 2) { - var shift = shiftTable[i >>> 1]; - kL = utils.r28shl(kL, shift); - kR = utils.r28shl(kR, shift); - utils.pc2(kL, kR, state.keys, i); - } +EDDSA.prototype.makeSignature = function makeSignature(sig) { + if (sig instanceof Signature) + return sig; + return new Signature(this, sig); }; -DES.prototype._update = function _update(inp, inOff, out, outOff) { - var state = this._desState; +/** +* * https://tools.ietf.org/html/draft-josefsson-eddsa-ed25519-03#section-5.2 +* +* EDDSA defines methods for encoding and decoding points and integers. These are +* helper convenience methods, that pass along to utility functions implied +* parameters. +* +*/ +EDDSA.prototype.encodePoint = function encodePoint(point) { + var enc = point.getY().toArray('le', this.encodingLength); + enc[this.encodingLength - 1] |= point.getX().isOdd() ? 0x80 : 0; + return enc; +}; - var l = utils.readUInt32BE(inp, inOff); - var r = utils.readUInt32BE(inp, inOff + 4); +EDDSA.prototype.decodePoint = function decodePoint(bytes) { + bytes = utils.parseBytes(bytes); - // Initial Permutation - utils.ip(l, r, state.tmp, 0); - l = state.tmp[0]; - r = state.tmp[1]; + var lastIx = bytes.length - 1; + var normed = bytes.slice(0, lastIx).concat(bytes[lastIx] & ~0x80); + var xIsOdd = (bytes[lastIx] & 0x80) !== 0; - if (this.type === 'encrypt') - this._encrypt(state, l, r, state.tmp, 0); - else - this._decrypt(state, l, r, state.tmp, 0); + var y = utils.intFromLE(normed); + return this.curve.pointFromY(y, xIsOdd); +}; - l = state.tmp[0]; - r = state.tmp[1]; +EDDSA.prototype.encodeInt = function encodeInt(num) { + return num.toArray('le', this.encodingLength); +}; - utils.writeUInt32BE(out, l, outOff); - utils.writeUInt32BE(out, r, outOff + 4); +EDDSA.prototype.decodeInt = function decodeInt(bytes) { + return utils.intFromLE(bytes); }; -DES.prototype._pad = function _pad(buffer, off) { - var value = buffer.length - off; - for (var i = off; i < buffer.length; i++) - buffer[i] = value; +EDDSA.prototype.isPoint = function isPoint(val) { + return val instanceof this.pointClass; +}; - return true; +},{"../curves":153,"../utils":161,"./key":158,"./signature":159,"hash.js":185}],158:[function(require,module,exports){ +'use strict'; + +var utils = require('../utils'); +var assert = utils.assert; +var parseBytes = utils.parseBytes; +var cachedProperty = utils.cachedProperty; + +/** +* @param {EDDSA} eddsa - instance +* @param {Object} params - public/private key parameters +* +* @param {Array} [params.secret] - secret seed bytes +* @param {Point} [params.pub] - public key point (aka `A` in eddsa terms) +* @param {Array} [params.pub] - public key point encoded as bytes +* +*/ +function KeyPair(eddsa, params) { + this.eddsa = eddsa; + this._secret = parseBytes(params.secret); + if (eddsa.isPoint(params.pub)) + this._pub = params.pub; + else + this._pubBytes = parseBytes(params.pub); +} + +KeyPair.fromPublic = function fromPublic(eddsa, pub) { + if (pub instanceof KeyPair) + return pub; + return new KeyPair(eddsa, { pub: pub }); }; -DES.prototype._unpad = function _unpad(buffer) { - var pad = buffer[buffer.length - 1]; - for (var i = buffer.length - pad; i < buffer.length; i++) - assert.equal(buffer[i], pad); +KeyPair.fromSecret = function fromSecret(eddsa, secret) { + if (secret instanceof KeyPair) + return secret; + return new KeyPair(eddsa, { secret: secret }); +}; - return buffer.slice(0, buffer.length - pad); +KeyPair.prototype.secret = function secret() { + return this._secret; }; -DES.prototype._encrypt = function _encrypt(state, lStart, rStart, out, off) { - var l = lStart; - var r = rStart; +cachedProperty(KeyPair, 'pubBytes', function pubBytes() { + return this.eddsa.encodePoint(this.pub()); +}); - // Apply f() x16 times - for (var i = 0; i < state.keys.length; i += 2) { - var keyL = state.keys[i]; - var keyR = state.keys[i + 1]; +cachedProperty(KeyPair, 'pub', function pub() { + if (this._pubBytes) + return this.eddsa.decodePoint(this._pubBytes); + return this.eddsa.g.mul(this.priv()); +}); - // f(r, k) - utils.expand(r, state.tmp, 0); +cachedProperty(KeyPair, 'privBytes', function privBytes() { + var eddsa = this.eddsa; + var hash = this.hash(); + var lastIx = eddsa.encodingLength - 1; - keyL ^= state.tmp[0]; - keyR ^= state.tmp[1]; - var s = utils.substitute(keyL, keyR); - var f = utils.permute(s); + var a = hash.slice(0, eddsa.encodingLength); + a[0] &= 248; + a[lastIx] &= 127; + a[lastIx] |= 64; - var t = r; - r = (l ^ f) >>> 0; - l = t; - } + return a; +}); - // Reverse Initial Permutation - utils.rip(r, l, out, off); -}; +cachedProperty(KeyPair, 'priv', function priv() { + return this.eddsa.decodeInt(this.privBytes()); +}); -DES.prototype._decrypt = function _decrypt(state, lStart, rStart, out, off) { - var l = rStart; - var r = lStart; +cachedProperty(KeyPair, 'hash', function hash() { + return this.eddsa.hash().update(this.secret()).digest(); +}); - // Apply f() x16 times - for (var i = state.keys.length - 2; i >= 0; i -= 2) { - var keyL = state.keys[i]; - var keyR = state.keys[i + 1]; +cachedProperty(KeyPair, 'messagePrefix', function messagePrefix() { + return this.hash().slice(this.eddsa.encodingLength); +}); - // f(r, k) - utils.expand(l, state.tmp, 0); +KeyPair.prototype.sign = function sign(message) { + assert(this._secret, 'KeyPair can only verify'); + return this.eddsa.sign(message, this); +}; - keyL ^= state.tmp[0]; - keyR ^= state.tmp[1]; - var s = utils.substitute(keyL, keyR); - var f = utils.permute(s); +KeyPair.prototype.verify = function verify(message, sig) { + return this.eddsa.verify(message, sig, this); +}; - var t = l; - l = (r ^ f) >>> 0; - r = t; - } +KeyPair.prototype.getSecret = function getSecret(enc) { + assert(this._secret, 'KeyPair is public only'); + return utils.encode(this.secret(), enc); +}; - // Reverse Initial Permutation - utils.rip(l, r, out, off); +KeyPair.prototype.getPublic = function getPublic(enc) { + return utils.encode(this.pubBytes(), enc); }; -},{"./cipher":176,"./utils":179,"inherits":256,"minimalistic-assert":301}],178:[function(require,module,exports){ -'use strict'; +module.exports = KeyPair; -var assert = require('minimalistic-assert'); -var inherits = require('inherits'); +},{"../utils":161}],159:[function(require,module,exports){ +'use strict'; -var Cipher = require('./cipher'); -var DES = require('./des'); +var BN = require('bn.js'); +var utils = require('../utils'); +var assert = utils.assert; +var cachedProperty = utils.cachedProperty; +var parseBytes = utils.parseBytes; -function EDEState(type, key) { - assert.equal(key.length, 24, 'Invalid key length'); +/** +* @param {EDDSA} eddsa - eddsa instance +* @param {Array|Object} sig - +* @param {Array|Point} [sig.R] - R point as Point or bytes +* @param {Array|bn} [sig.S] - S scalar as bn or bytes +* @param {Array} [sig.Rencoded] - R point encoded +* @param {Array} [sig.Sencoded] - S scalar encoded +*/ +function Signature(eddsa, sig) { + this.eddsa = eddsa; - var k1 = key.slice(0, 8); - var k2 = key.slice(8, 16); - var k3 = key.slice(16, 24); + if (typeof sig !== 'object') + sig = parseBytes(sig); - if (type === 'encrypt') { - this.ciphers = [ - DES.create({ type: 'encrypt', key: k1 }), - DES.create({ type: 'decrypt', key: k2 }), - DES.create({ type: 'encrypt', key: k3 }) - ]; - } else { - this.ciphers = [ - DES.create({ type: 'decrypt', key: k3 }), - DES.create({ type: 'encrypt', key: k2 }), - DES.create({ type: 'decrypt', key: k1 }) - ]; + if (Array.isArray(sig)) { + assert(sig.length === eddsa.encodingLength * 2, 'Signature has invalid size'); + sig = { + R: sig.slice(0, eddsa.encodingLength), + S: sig.slice(eddsa.encodingLength), + }; } -} -function EDE(options) { - Cipher.call(this, options); + assert(sig.R && sig.S, 'Signature without R or S'); - var state = new EDEState(this.type, this.options.key); - this._edeState = state; + if (eddsa.isPoint(sig.R)) + this._R = sig.R; + if (sig.S instanceof BN) + this._S = sig.S; + + this._Rencoded = Array.isArray(sig.R) ? sig.R : sig.Rencoded; + this._Sencoded = Array.isArray(sig.S) ? sig.S : sig.Sencoded; } -inherits(EDE, Cipher); -module.exports = EDE; +cachedProperty(Signature, 'S', function S() { + return this.eddsa.decodeInt(this.Sencoded()); +}); -EDE.create = function create(options) { - return new EDE(options); -}; +cachedProperty(Signature, 'R', function R() { + return this.eddsa.decodePoint(this.Rencoded()); +}); -EDE.prototype._update = function _update(inp, inOff, out, outOff) { - var state = this._edeState; +cachedProperty(Signature, 'Rencoded', function Rencoded() { + return this.eddsa.encodePoint(this.R()); +}); - state.ciphers[0]._update(inp, inOff, out, outOff); - state.ciphers[1]._update(out, outOff, out, outOff); - state.ciphers[2]._update(out, outOff, out, outOff); +cachedProperty(Signature, 'Sencoded', function Sencoded() { + return this.eddsa.encodeInt(this.S()); +}); + +Signature.prototype.toBytes = function toBytes() { + return this.Rencoded().concat(this.Sencoded()); }; -EDE.prototype._pad = DES.prototype._pad; -EDE.prototype._unpad = DES.prototype._unpad; +Signature.prototype.toHex = function toHex() { + return utils.encode(this.toBytes(), 'hex').toUpperCase(); +}; -},{"./cipher":176,"./des":177,"inherits":256,"minimalistic-assert":301}],179:[function(require,module,exports){ -'use strict'; +module.exports = Signature; -exports.readUInt32BE = function readUInt32BE(bytes, off) { - var res = (bytes[0 + off] << 24) | - (bytes[1 + off] << 16) | - (bytes[2 + off] << 8) | - bytes[3 + off]; - return res >>> 0; -}; - -exports.writeUInt32BE = function writeUInt32BE(bytes, value, off) { - bytes[0 + off] = value >>> 24; - bytes[1 + off] = (value >>> 16) & 0xff; - bytes[2 + off] = (value >>> 8) & 0xff; - bytes[3 + off] = value & 0xff; -}; - -exports.ip = function ip(inL, inR, out, off) { - var outL = 0; - var outR = 0; - - for (var i = 6; i >= 0; i -= 2) { - for (var j = 0; j <= 24; j += 8) { - outL <<= 1; - outL |= (inR >>> (j + i)) & 1; - } - for (var j = 0; j <= 24; j += 8) { - outL <<= 1; - outL |= (inL >>> (j + i)) & 1; - } - } - - for (var i = 6; i >= 0; i -= 2) { - for (var j = 1; j <= 25; j += 8) { - outR <<= 1; - outR |= (inR >>> (j + i)) & 1; - } - for (var j = 1; j <= 25; j += 8) { - outR <<= 1; - outR |= (inL >>> (j + i)) & 1; - } - } - - out[off + 0] = outL >>> 0; - out[off + 1] = outR >>> 0; -}; - -exports.rip = function rip(inL, inR, out, off) { - var outL = 0; - var outR = 0; - - for (var i = 0; i < 4; i++) { - for (var j = 24; j >= 0; j -= 8) { - outL <<= 1; - outL |= (inR >>> (j + i)) & 1; - outL <<= 1; - outL |= (inL >>> (j + i)) & 1; - } - } - for (var i = 4; i < 8; i++) { - for (var j = 24; j >= 0; j -= 8) { - outR <<= 1; - outR |= (inR >>> (j + i)) & 1; - outR <<= 1; - outR |= (inL >>> (j + i)) & 1; - } - } - - out[off + 0] = outL >>> 0; - out[off + 1] = outR >>> 0; -}; - -exports.pc1 = function pc1(inL, inR, out, off) { - var outL = 0; - var outR = 0; - - // 7, 15, 23, 31, 39, 47, 55, 63 - // 6, 14, 22, 30, 39, 47, 55, 63 - // 5, 13, 21, 29, 39, 47, 55, 63 - // 4, 12, 20, 28 - for (var i = 7; i >= 5; i--) { - for (var j = 0; j <= 24; j += 8) { - outL <<= 1; - outL |= (inR >> (j + i)) & 1; - } - for (var j = 0; j <= 24; j += 8) { - outL <<= 1; - outL |= (inL >> (j + i)) & 1; - } - } - for (var j = 0; j <= 24; j += 8) { - outL <<= 1; - outL |= (inR >> (j + i)) & 1; - } - - // 1, 9, 17, 25, 33, 41, 49, 57 - // 2, 10, 18, 26, 34, 42, 50, 58 - // 3, 11, 19, 27, 35, 43, 51, 59 - // 36, 44, 52, 60 - for (var i = 1; i <= 3; i++) { - for (var j = 0; j <= 24; j += 8) { - outR <<= 1; - outR |= (inR >> (j + i)) & 1; - } - for (var j = 0; j <= 24; j += 8) { - outR <<= 1; - outR |= (inL >> (j + i)) & 1; - } - } - for (var j = 0; j <= 24; j += 8) { - outR <<= 1; - outR |= (inL >> (j + i)) & 1; - } - - out[off + 0] = outL >>> 0; - out[off + 1] = outR >>> 0; -}; - -exports.r28shl = function r28shl(num, shift) { - return ((num << shift) & 0xfffffff) | (num >>> (28 - shift)); -}; - -var pc2table = [ - // inL => outL - 14, 11, 17, 4, 27, 23, 25, 0, - 13, 22, 7, 18, 5, 9, 16, 24, - 2, 20, 12, 21, 1, 8, 15, 26, - - // inR => outR - 15, 4, 25, 19, 9, 1, 26, 16, - 5, 11, 23, 8, 12, 7, 17, 0, - 22, 3, 10, 14, 6, 20, 27, 24 -]; - -exports.pc2 = function pc2(inL, inR, out, off) { - var outL = 0; - var outR = 0; - - var len = pc2table.length >>> 1; - for (var i = 0; i < len; i++) { - outL <<= 1; - outL |= (inL >>> pc2table[i]) & 0x1; - } - for (var i = len; i < pc2table.length; i++) { - outR <<= 1; - outR |= (inR >>> pc2table[i]) & 0x1; - } - - out[off + 0] = outL >>> 0; - out[off + 1] = outR >>> 0; -}; - -exports.expand = function expand(r, out, off) { - var outL = 0; - var outR = 0; - - outL = ((r & 1) << 5) | (r >>> 27); - for (var i = 23; i >= 15; i -= 4) { - outL <<= 6; - outL |= (r >>> i) & 0x3f; - } - for (var i = 11; i >= 3; i -= 4) { - outR |= (r >>> i) & 0x3f; - outR <<= 6; - } - outR |= ((r & 0x1f) << 1) | (r >>> 31); - - out[off + 0] = outL >>> 0; - out[off + 1] = outR >>> 0; -}; - -var sTable = [ - 14, 0, 4, 15, 13, 7, 1, 4, 2, 14, 15, 2, 11, 13, 8, 1, - 3, 10, 10, 6, 6, 12, 12, 11, 5, 9, 9, 5, 0, 3, 7, 8, - 4, 15, 1, 12, 14, 8, 8, 2, 13, 4, 6, 9, 2, 1, 11, 7, - 15, 5, 12, 11, 9, 3, 7, 14, 3, 10, 10, 0, 5, 6, 0, 13, - - 15, 3, 1, 13, 8, 4, 14, 7, 6, 15, 11, 2, 3, 8, 4, 14, - 9, 12, 7, 0, 2, 1, 13, 10, 12, 6, 0, 9, 5, 11, 10, 5, - 0, 13, 14, 8, 7, 10, 11, 1, 10, 3, 4, 15, 13, 4, 1, 2, - 5, 11, 8, 6, 12, 7, 6, 12, 9, 0, 3, 5, 2, 14, 15, 9, - - 10, 13, 0, 7, 9, 0, 14, 9, 6, 3, 3, 4, 15, 6, 5, 10, - 1, 2, 13, 8, 12, 5, 7, 14, 11, 12, 4, 11, 2, 15, 8, 1, - 13, 1, 6, 10, 4, 13, 9, 0, 8, 6, 15, 9, 3, 8, 0, 7, - 11, 4, 1, 15, 2, 14, 12, 3, 5, 11, 10, 5, 14, 2, 7, 12, - - 7, 13, 13, 8, 14, 11, 3, 5, 0, 6, 6, 15, 9, 0, 10, 3, - 1, 4, 2, 7, 8, 2, 5, 12, 11, 1, 12, 10, 4, 14, 15, 9, - 10, 3, 6, 15, 9, 0, 0, 6, 12, 10, 11, 1, 7, 13, 13, 8, - 15, 9, 1, 4, 3, 5, 14, 11, 5, 12, 2, 7, 8, 2, 4, 14, - - 2, 14, 12, 11, 4, 2, 1, 12, 7, 4, 10, 7, 11, 13, 6, 1, - 8, 5, 5, 0, 3, 15, 15, 10, 13, 3, 0, 9, 14, 8, 9, 6, - 4, 11, 2, 8, 1, 12, 11, 7, 10, 1, 13, 14, 7, 2, 8, 13, - 15, 6, 9, 15, 12, 0, 5, 9, 6, 10, 3, 4, 0, 5, 14, 3, - - 12, 10, 1, 15, 10, 4, 15, 2, 9, 7, 2, 12, 6, 9, 8, 5, - 0, 6, 13, 1, 3, 13, 4, 14, 14, 0, 7, 11, 5, 3, 11, 8, - 9, 4, 14, 3, 15, 2, 5, 12, 2, 9, 8, 5, 12, 15, 3, 10, - 7, 11, 0, 14, 4, 1, 10, 7, 1, 6, 13, 0, 11, 8, 6, 13, - - 4, 13, 11, 0, 2, 11, 14, 7, 15, 4, 0, 9, 8, 1, 13, 10, - 3, 14, 12, 3, 9, 5, 7, 12, 5, 2, 10, 15, 6, 8, 1, 6, - 1, 6, 4, 11, 11, 13, 13, 8, 12, 1, 3, 4, 7, 10, 14, 7, - 10, 9, 15, 5, 6, 0, 8, 15, 0, 14, 5, 2, 9, 3, 2, 12, - - 13, 1, 2, 15, 8, 13, 4, 8, 6, 10, 15, 3, 11, 7, 1, 4, - 10, 12, 9, 5, 3, 6, 14, 11, 5, 0, 0, 14, 12, 9, 7, 2, - 7, 2, 11, 1, 4, 14, 1, 7, 9, 4, 12, 10, 14, 8, 2, 13, - 0, 15, 6, 12, 10, 9, 13, 0, 15, 3, 3, 5, 5, 6, 8, 11 -]; - -exports.substitute = function substitute(inL, inR) { - var out = 0; - for (var i = 0; i < 4; i++) { - var b = (inL >>> (18 - i * 6)) & 0x3f; - var sb = sTable[i * 0x40 + b]; - - out <<= 4; - out |= sb; - } - for (var i = 0; i < 4; i++) { - var b = (inR >>> (18 - i * 6)) & 0x3f; - var sb = sTable[4 * 0x40 + i * 0x40 + b]; - - out <<= 4; - out |= sb; - } - return out >>> 0; -}; - -var permuteTable = [ - 16, 25, 12, 11, 3, 20, 4, 15, 31, 17, 9, 6, 27, 14, 1, 22, - 30, 24, 8, 18, 0, 5, 29, 23, 13, 19, 2, 26, 10, 21, 28, 7 -]; - -exports.permute = function permute(num) { - var out = 0; - for (var i = 0; i < permuteTable.length; i++) { - out <<= 1; - out |= (num >>> permuteTable[i]) & 0x1; - } - return out >>> 0; -}; - -exports.padSplit = function padSplit(num, size, group) { - var str = num.toString(2); - while (str.length < size) - str = '0' + str; - - var out = []; - for (var i = 0; i < size; i += group) - out.push(str.slice(i, i + group)); - return out.join(' '); -}; - -},{}],180:[function(require,module,exports){ -(function (Buffer){(function (){ -var generatePrime = require('./lib/generatePrime') -var primes = require('./lib/primes.json') - -var DH = require('./lib/dh') - -function getDiffieHellman (mod) { - var prime = new Buffer(primes[mod].prime, 'hex') - var gen = new Buffer(primes[mod].gen, 'hex') - - return new DH(prime, gen) -} - -var ENCODINGS = { - 'binary': true, 'hex': true, 'base64': true -} - -function createDiffieHellman (prime, enc, generator, genc) { - if (Buffer.isBuffer(enc) || ENCODINGS[enc] === undefined) { - return createDiffieHellman(prime, 'binary', enc, generator) - } - - enc = enc || 'binary' - genc = genc || 'binary' - generator = generator || new Buffer([2]) - - if (!Buffer.isBuffer(generator)) { - generator = new Buffer(generator, genc) - } - - if (typeof prime === 'number') { - return new DH(generatePrime(prime, generator), generator, true) - } - - if (!Buffer.isBuffer(prime)) { - prime = new Buffer(prime, enc) - } - - return new DH(prime, generator, true) -} - -exports.DiffieHellmanGroup = exports.createDiffieHellmanGroup = exports.getDiffieHellman = getDiffieHellman -exports.createDiffieHellman = exports.DiffieHellman = createDiffieHellman - -}).call(this)}).call(this,require("buffer").Buffer) -},{"./lib/dh":181,"./lib/generatePrime":182,"./lib/primes.json":183,"buffer":137}],181:[function(require,module,exports){ -(function (Buffer){(function (){ -var BN = require('bn.js'); -var MillerRabin = require('miller-rabin'); -var millerRabin = new MillerRabin(); -var TWENTYFOUR = new BN(24); -var ELEVEN = new BN(11); -var TEN = new BN(10); -var THREE = new BN(3); -var SEVEN = new BN(7); -var primes = require('./generatePrime'); -var randomBytes = require('randombytes'); -module.exports = DH; - -function setPublicKey(pub, enc) { - enc = enc || 'utf8'; - if (!Buffer.isBuffer(pub)) { - pub = new Buffer(pub, enc); - } - this._pub = new BN(pub); - return this; -} - -function setPrivateKey(priv, enc) { - enc = enc || 'utf8'; - if (!Buffer.isBuffer(priv)) { - priv = new Buffer(priv, enc); - } - this._priv = new BN(priv); - return this; -} - -var primeCache = {}; -function checkPrime(prime, generator) { - var gen = generator.toString('hex'); - var hex = [gen, prime.toString(16)].join('_'); - if (hex in primeCache) { - return primeCache[hex]; - } - var error = 0; - - if (prime.isEven() || - !primes.simpleSieve || - !primes.fermatTest(prime) || - !millerRabin.test(prime)) { - //not a prime so +1 - error += 1; - - if (gen === '02' || gen === '05') { - // we'd be able to check the generator - // it would fail so +8 - error += 8; - } else { - //we wouldn't be able to test the generator - // so +4 - error += 4; - } - primeCache[hex] = error; - return error; - } - if (!millerRabin.test(prime.shrn(1))) { - //not a safe prime - error += 2; - } - var rem; - switch (gen) { - case '02': - if (prime.mod(TWENTYFOUR).cmp(ELEVEN)) { - // unsuidable generator - error += 8; - } - break; - case '05': - rem = prime.mod(TEN); - if (rem.cmp(THREE) && rem.cmp(SEVEN)) { - // prime mod 10 needs to equal 3 or 7 - error += 8; - } - break; - default: - error += 4; - } - primeCache[hex] = error; - return error; -} - -function DH(prime, generator, malleable) { - this.setGenerator(generator); - this.__prime = new BN(prime); - this._prime = BN.mont(this.__prime); - this._primeLen = prime.length; - this._pub = undefined; - this._priv = undefined; - this._primeCode = undefined; - if (malleable) { - this.setPublicKey = setPublicKey; - this.setPrivateKey = setPrivateKey; - } else { - this._primeCode = 8; - } -} -Object.defineProperty(DH.prototype, 'verifyError', { - enumerable: true, - get: function () { - if (typeof this._primeCode !== 'number') { - this._primeCode = checkPrime(this.__prime, this.__gen); - } - return this._primeCode; - } -}); -DH.prototype.generateKeys = function () { - if (!this._priv) { - this._priv = new BN(randomBytes(this._primeLen)); - } - this._pub = this._gen.toRed(this._prime).redPow(this._priv).fromRed(); - return this.getPublicKey(); -}; - -DH.prototype.computeSecret = function (other) { - other = new BN(other); - other = other.toRed(this._prime); - var secret = other.redPow(this._priv).fromRed(); - var out = new Buffer(secret.toArray()); - var prime = this.getPrime(); - if (out.length < prime.length) { - var front = new Buffer(prime.length - out.length); - front.fill(0); - out = Buffer.concat([front, out]); - } - return out; -}; - -DH.prototype.getPublicKey = function getPublicKey(enc) { - return formatReturnValue(this._pub, enc); -}; - -DH.prototype.getPrivateKey = function getPrivateKey(enc) { - return formatReturnValue(this._priv, enc); -}; - -DH.prototype.getPrime = function (enc) { - return formatReturnValue(this.__prime, enc); -}; - -DH.prototype.getGenerator = function (enc) { - return formatReturnValue(this._gen, enc); -}; - -DH.prototype.setGenerator = function (gen, enc) { - enc = enc || 'utf8'; - if (!Buffer.isBuffer(gen)) { - gen = new Buffer(gen, enc); - } - this.__gen = gen; - this._gen = new BN(gen); - return this; -}; - -function formatReturnValue(bn, enc) { - var buf = new Buffer(bn.toArray()); - if (!enc) { - return buf; - } else { - return buf.toString(enc); - } -} - -}).call(this)}).call(this,require("buffer").Buffer) -},{"./generatePrime":182,"bn.js":184,"buffer":137,"miller-rabin":299,"randombytes":400}],182:[function(require,module,exports){ -var randomBytes = require('randombytes'); -module.exports = findPrime; -findPrime.simpleSieve = simpleSieve; -findPrime.fermatTest = fermatTest; -var BN = require('bn.js'); -var TWENTYFOUR = new BN(24); -var MillerRabin = require('miller-rabin'); -var millerRabin = new MillerRabin(); -var ONE = new BN(1); -var TWO = new BN(2); -var FIVE = new BN(5); -var SIXTEEN = new BN(16); -var EIGHT = new BN(8); -var TEN = new BN(10); -var THREE = new BN(3); -var SEVEN = new BN(7); -var ELEVEN = new BN(11); -var FOUR = new BN(4); -var TWELVE = new BN(12); -var primes = null; - -function _getPrimes() { - if (primes !== null) - return primes; - - var limit = 0x100000; - var res = []; - res[0] = 2; - for (var i = 1, k = 3; k < limit; k += 2) { - var sqrt = Math.ceil(Math.sqrt(k)); - for (var j = 0; j < i && res[j] <= sqrt; j++) - if (k % res[j] === 0) - break; - - if (i !== j && res[j] <= sqrt) - continue; - - res[i++] = k; - } - primes = res; - return res; -} - -function simpleSieve(p) { - var primes = _getPrimes(); - - for (var i = 0; i < primes.length; i++) - if (p.modn(primes[i]) === 0) { - if (p.cmpn(primes[i]) === 0) { - return true; - } else { - return false; - } - } - - return true; -} - -function fermatTest(p) { - var red = BN.mont(p); - return TWO.toRed(red).redPow(p.subn(1)).fromRed().cmpn(1) === 0; -} - -function findPrime(bits, gen) { - if (bits < 16) { - // this is what openssl does - if (gen === 2 || gen === 5) { - return new BN([0x8c, 0x7b]); - } else { - return new BN([0x8c, 0x27]); - } - } - gen = new BN(gen); - - var num, n2; - - while (true) { - num = new BN(randomBytes(Math.ceil(bits / 8))); - while (num.bitLength() > bits) { - num.ishrn(1); - } - if (num.isEven()) { - num.iadd(ONE); - } - if (!num.testn(1)) { - num.iadd(TWO); - } - if (!gen.cmp(TWO)) { - while (num.mod(TWENTYFOUR).cmp(ELEVEN)) { - num.iadd(FOUR); - } - } else if (!gen.cmp(FIVE)) { - while (num.mod(TEN).cmp(THREE)) { - num.iadd(FOUR); - } - } - n2 = num.shrn(1); - if (simpleSieve(n2) && simpleSieve(num) && - fermatTest(n2) && fermatTest(num) && - millerRabin.test(n2) && millerRabin.test(num)) { - return num; - } - } - -} - -},{"bn.js":184,"miller-rabin":299,"randombytes":400}],183:[function(require,module,exports){ -module.exports={ - "modp1": { - "gen": "02", - "prime": "ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a63a3620ffffffffffffffff" - }, - "modp2": { - "gen": "02", - "prime": "ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece65381ffffffffffffffff" - }, - "modp5": { - "gen": "02", - "prime": "ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca237327ffffffffffffffff" - }, - "modp14": { - "gen": "02", - "prime": "ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca18217c32905e462e36ce3be39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9de2bcbf6955817183995497cea956ae515d2261898fa051015728e5a8aacaa68ffffffffffffffff" - }, - "modp15": { - "gen": "02", - "prime": "ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca18217c32905e462e36ce3be39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9de2bcbf6955817183995497cea956ae515d2261898fa051015728e5a8aaac42dad33170d04507a33a85521abdf1cba64ecfb850458dbef0a8aea71575d060c7db3970f85a6e1e4c7abf5ae8cdb0933d71e8c94e04a25619dcee3d2261ad2ee6bf12ffa06d98a0864d87602733ec86a64521f2b18177b200cbbe117577a615d6c770988c0bad946e208e24fa074e5ab3143db5bfce0fd108e4b82d120a93ad2caffffffffffffffff" - }, - "modp16": { - "gen": "02", - "prime": "ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca18217c32905e462e36ce3be39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9de2bcbf6955817183995497cea956ae515d2261898fa051015728e5a8aaac42dad33170d04507a33a85521abdf1cba64ecfb850458dbef0a8aea71575d060c7db3970f85a6e1e4c7abf5ae8cdb0933d71e8c94e04a25619dcee3d2261ad2ee6bf12ffa06d98a0864d87602733ec86a64521f2b18177b200cbbe117577a615d6c770988c0bad946e208e24fa074e5ab3143db5bfce0fd108e4b82d120a92108011a723c12a787e6d788719a10bdba5b2699c327186af4e23c1a946834b6150bda2583e9ca2ad44ce8dbbbc2db04de8ef92e8efc141fbecaa6287c59474e6bc05d99b2964fa090c3a2233ba186515be7ed1f612970cee2d7afb81bdd762170481cd0069127d5b05aa993b4ea988d8fddc186ffb7dc90a6c08f4df435c934063199ffffffffffffffff" - }, - "modp17": { - "gen": "02", - "prime": "ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca18217c32905e462e36ce3be39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9de2bcbf6955817183995497cea956ae515d2261898fa051015728e5a8aaac42dad33170d04507a33a85521abdf1cba64ecfb850458dbef0a8aea71575d060c7db3970f85a6e1e4c7abf5ae8cdb0933d71e8c94e04a25619dcee3d2261ad2ee6bf12ffa06d98a0864d87602733ec86a64521f2b18177b200cbbe117577a615d6c770988c0bad946e208e24fa074e5ab3143db5bfce0fd108e4b82d120a92108011a723c12a787e6d788719a10bdba5b2699c327186af4e23c1a946834b6150bda2583e9ca2ad44ce8dbbbc2db04de8ef92e8efc141fbecaa6287c59474e6bc05d99b2964fa090c3a2233ba186515be7ed1f612970cee2d7afb81bdd762170481cd0069127d5b05aa993b4ea988d8fddc186ffb7dc90a6c08f4df435c93402849236c3fab4d27c7026c1d4dcb2602646dec9751e763dba37bdf8ff9406ad9e530ee5db382f413001aeb06a53ed9027d831179727b0865a8918da3edbebcf9b14ed44ce6cbaced4bb1bdb7f1447e6cc254b332051512bd7af426fb8f401378cd2bf5983ca01c64b92ecf032ea15d1721d03f482d7ce6e74fef6d55e702f46980c82b5a84031900b1c9e59e7c97fbec7e8f323a97a7e36cc88be0f1d45b7ff585ac54bd407b22b4154aacc8f6d7ebf48e1d814cc5ed20f8037e0a79715eef29be32806a1d58bb7c5da76f550aa3d8a1fbff0eb19ccb1a313d55cda56c9ec2ef29632387fe8d76e3c0468043e8f663f4860ee12bf2d5b0b7474d6e694f91e6dcc4024ffffffffffffffff" - }, - "modp18": { - "gen": "02", - "prime": "ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca18217c32905e462e36ce3be39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9de2bcbf6955817183995497cea956ae515d2261898fa051015728e5a8aaac42dad33170d04507a33a85521abdf1cba64ecfb850458dbef0a8aea71575d060c7db3970f85a6e1e4c7abf5ae8cdb0933d71e8c94e04a25619dcee3d2261ad2ee6bf12ffa06d98a0864d87602733ec86a64521f2b18177b200cbbe117577a615d6c770988c0bad946e208e24fa074e5ab3143db5bfce0fd108e4b82d120a92108011a723c12a787e6d788719a10bdba5b2699c327186af4e23c1a946834b6150bda2583e9ca2ad44ce8dbbbc2db04de8ef92e8efc141fbecaa6287c59474e6bc05d99b2964fa090c3a2233ba186515be7ed1f612970cee2d7afb81bdd762170481cd0069127d5b05aa993b4ea988d8fddc186ffb7dc90a6c08f4df435c93402849236c3fab4d27c7026c1d4dcb2602646dec9751e763dba37bdf8ff9406ad9e530ee5db382f413001aeb06a53ed9027d831179727b0865a8918da3edbebcf9b14ed44ce6cbaced4bb1bdb7f1447e6cc254b332051512bd7af426fb8f401378cd2bf5983ca01c64b92ecf032ea15d1721d03f482d7ce6e74fef6d55e702f46980c82b5a84031900b1c9e59e7c97fbec7e8f323a97a7e36cc88be0f1d45b7ff585ac54bd407b22b4154aacc8f6d7ebf48e1d814cc5ed20f8037e0a79715eef29be32806a1d58bb7c5da76f550aa3d8a1fbff0eb19ccb1a313d55cda56c9ec2ef29632387fe8d76e3c0468043e8f663f4860ee12bf2d5b0b7474d6e694f91e6dbe115974a3926f12fee5e438777cb6a932df8cd8bec4d073b931ba3bc832b68d9dd300741fa7bf8afc47ed2576f6936ba424663aab639c5ae4f5683423b4742bf1c978238f16cbe39d652de3fdb8befc848ad922222e04a4037c0713eb57a81a23f0c73473fc646cea306b4bcbc8862f8385ddfa9d4b7fa2c087e879683303ed5bdd3a062b3cf5b3a278a66d2a13f83f44f82ddf310ee074ab6a364597e899a0255dc164f31cc50846851df9ab48195ded7ea1b1d510bd7ee74d73faf36bc31ecfa268359046f4eb879f924009438b481c6cd7889a002ed5ee382bc9190da6fc026e479558e4475677e9aa9e3050e2765694dfc81f56e880b96e7160c980dd98edd3dfffffffffffffffff" - } -} -},{}],184:[function(require,module,exports){ -arguments[4][47][0].apply(exports,arguments) -},{"buffer":93,"dup":47}],185:[function(require,module,exports){ -'use strict'; - -var elliptic = exports; - -elliptic.version = require('../package.json').version; -elliptic.utils = require('./elliptic/utils'); -elliptic.rand = require('brorand'); -elliptic.curve = require('./elliptic/curve'); -elliptic.curves = require('./elliptic/curves'); - -// Protocols -elliptic.ec = require('./elliptic/ec'); -elliptic.eddsa = require('./elliptic/eddsa'); - -},{"../package.json":201,"./elliptic/curve":188,"./elliptic/curves":191,"./elliptic/ec":192,"./elliptic/eddsa":195,"./elliptic/utils":199,"brorand":92}],186:[function(require,module,exports){ -'use strict'; - -var BN = require('bn.js'); -var utils = require('../utils'); -var getNAF = utils.getNAF; -var getJSF = utils.getJSF; -var assert = utils.assert; - -function BaseCurve(type, conf) { - this.type = type; - this.p = new BN(conf.p, 16); - - // Use Montgomery, when there is no fast reduction for the prime - this.red = conf.prime ? BN.red(conf.prime) : BN.mont(this.p); - - // Useful for many curves - this.zero = new BN(0).toRed(this.red); - this.one = new BN(1).toRed(this.red); - this.two = new BN(2).toRed(this.red); - - // Curve configuration, optional - this.n = conf.n && new BN(conf.n, 16); - this.g = conf.g && this.pointFromJSON(conf.g, conf.gRed); - - // Temporary arrays - this._wnafT1 = new Array(4); - this._wnafT2 = new Array(4); - this._wnafT3 = new Array(4); - this._wnafT4 = new Array(4); - - this._bitLength = this.n ? this.n.bitLength() : 0; - - // Generalized Greg Maxwell's trick - var adjustCount = this.n && this.p.div(this.n); - if (!adjustCount || adjustCount.cmpn(100) > 0) { - this.redN = null; - } else { - this._maxwellTrick = true; - this.redN = this.n.toRed(this.red); - } -} -module.exports = BaseCurve; - -BaseCurve.prototype.point = function point() { - throw new Error('Not implemented'); -}; - -BaseCurve.prototype.validate = function validate() { - throw new Error('Not implemented'); -}; - -BaseCurve.prototype._fixedNafMul = function _fixedNafMul(p, k) { - assert(p.precomputed); - var doubles = p._getDoubles(); - - var naf = getNAF(k, 1, this._bitLength); - var I = (1 << (doubles.step + 1)) - (doubles.step % 2 === 0 ? 2 : 1); - I /= 3; - - // Translate into more windowed form - var repr = []; - var j; - var nafW; - for (j = 0; j < naf.length; j += doubles.step) { - nafW = 0; - for (var l = j + doubles.step - 1; l >= j; l--) - nafW = (nafW << 1) + naf[l]; - repr.push(nafW); - } - - var a = this.jpoint(null, null, null); - var b = this.jpoint(null, null, null); - for (var i = I; i > 0; i--) { - for (j = 0; j < repr.length; j++) { - nafW = repr[j]; - if (nafW === i) - b = b.mixedAdd(doubles.points[j]); - else if (nafW === -i) - b = b.mixedAdd(doubles.points[j].neg()); - } - a = a.add(b); - } - return a.toP(); -}; - -BaseCurve.prototype._wnafMul = function _wnafMul(p, k) { - var w = 4; - - // Precompute window - var nafPoints = p._getNAFPoints(w); - w = nafPoints.wnd; - var wnd = nafPoints.points; - - // Get NAF form - var naf = getNAF(k, w, this._bitLength); - - // Add `this`*(N+1) for every w-NAF index - var acc = this.jpoint(null, null, null); - for (var i = naf.length - 1; i >= 0; i--) { - // Count zeroes - for (var l = 0; i >= 0 && naf[i] === 0; i--) - l++; - if (i >= 0) - l++; - acc = acc.dblp(l); - - if (i < 0) - break; - var z = naf[i]; - assert(z !== 0); - if (p.type === 'affine') { - // J +- P - if (z > 0) - acc = acc.mixedAdd(wnd[(z - 1) >> 1]); - else - acc = acc.mixedAdd(wnd[(-z - 1) >> 1].neg()); - } else { - // J +- J - if (z > 0) - acc = acc.add(wnd[(z - 1) >> 1]); - else - acc = acc.add(wnd[(-z - 1) >> 1].neg()); - } - } - return p.type === 'affine' ? acc.toP() : acc; -}; - -BaseCurve.prototype._wnafMulAdd = function _wnafMulAdd(defW, - points, - coeffs, - len, - jacobianResult) { - var wndWidth = this._wnafT1; - var wnd = this._wnafT2; - var naf = this._wnafT3; - - // Fill all arrays - var max = 0; - var i; - var j; - var p; - for (i = 0; i < len; i++) { - p = points[i]; - var nafPoints = p._getNAFPoints(defW); - wndWidth[i] = nafPoints.wnd; - wnd[i] = nafPoints.points; - } - - // Comb small window NAFs - for (i = len - 1; i >= 1; i -= 2) { - var a = i - 1; - var b = i; - if (wndWidth[a] !== 1 || wndWidth[b] !== 1) { - naf[a] = getNAF(coeffs[a], wndWidth[a], this._bitLength); - naf[b] = getNAF(coeffs[b], wndWidth[b], this._bitLength); - max = Math.max(naf[a].length, max); - max = Math.max(naf[b].length, max); - continue; - } - - var comb = [ - points[a], /* 1 */ - null, /* 3 */ - null, /* 5 */ - points[b], /* 7 */ - ]; - - // Try to avoid Projective points, if possible - if (points[a].y.cmp(points[b].y) === 0) { - comb[1] = points[a].add(points[b]); - comb[2] = points[a].toJ().mixedAdd(points[b].neg()); - } else if (points[a].y.cmp(points[b].y.redNeg()) === 0) { - comb[1] = points[a].toJ().mixedAdd(points[b]); - comb[2] = points[a].add(points[b].neg()); - } else { - comb[1] = points[a].toJ().mixedAdd(points[b]); - comb[2] = points[a].toJ().mixedAdd(points[b].neg()); - } - - var index = [ - -3, /* -1 -1 */ - -1, /* -1 0 */ - -5, /* -1 1 */ - -7, /* 0 -1 */ - 0, /* 0 0 */ - 7, /* 0 1 */ - 5, /* 1 -1 */ - 1, /* 1 0 */ - 3, /* 1 1 */ - ]; - - var jsf = getJSF(coeffs[a], coeffs[b]); - max = Math.max(jsf[0].length, max); - naf[a] = new Array(max); - naf[b] = new Array(max); - for (j = 0; j < max; j++) { - var ja = jsf[0][j] | 0; - var jb = jsf[1][j] | 0; - - naf[a][j] = index[(ja + 1) * 3 + (jb + 1)]; - naf[b][j] = 0; - wnd[a] = comb; - } - } - - var acc = this.jpoint(null, null, null); - var tmp = this._wnafT4; - for (i = max; i >= 0; i--) { - var k = 0; - - while (i >= 0) { - var zero = true; - for (j = 0; j < len; j++) { - tmp[j] = naf[j][i] | 0; - if (tmp[j] !== 0) - zero = false; - } - if (!zero) - break; - k++; - i--; - } - if (i >= 0) - k++; - acc = acc.dblp(k); - if (i < 0) - break; - - for (j = 0; j < len; j++) { - var z = tmp[j]; - p; - if (z === 0) - continue; - else if (z > 0) - p = wnd[j][(z - 1) >> 1]; - else if (z < 0) - p = wnd[j][(-z - 1) >> 1].neg(); - - if (p.type === 'affine') - acc = acc.mixedAdd(p); - else - acc = acc.add(p); - } - } - // Zeroify references - for (i = 0; i < len; i++) - wnd[i] = null; - - if (jacobianResult) - return acc; - else - return acc.toP(); -}; - -function BasePoint(curve, type) { - this.curve = curve; - this.type = type; - this.precomputed = null; -} -BaseCurve.BasePoint = BasePoint; - -BasePoint.prototype.eq = function eq(/*other*/) { - throw new Error('Not implemented'); -}; - -BasePoint.prototype.validate = function validate() { - return this.curve.validate(this); -}; - -BaseCurve.prototype.decodePoint = function decodePoint(bytes, enc) { - bytes = utils.toArray(bytes, enc); - - var len = this.p.byteLength(); - - // uncompressed, hybrid-odd, hybrid-even - if ((bytes[0] === 0x04 || bytes[0] === 0x06 || bytes[0] === 0x07) && - bytes.length - 1 === 2 * len) { - if (bytes[0] === 0x06) - assert(bytes[bytes.length - 1] % 2 === 0); - else if (bytes[0] === 0x07) - assert(bytes[bytes.length - 1] % 2 === 1); - - var res = this.point(bytes.slice(1, 1 + len), - bytes.slice(1 + len, 1 + 2 * len)); - - return res; - } else if ((bytes[0] === 0x02 || bytes[0] === 0x03) && - bytes.length - 1 === len) { - return this.pointFromX(bytes.slice(1, 1 + len), bytes[0] === 0x03); - } - throw new Error('Unknown point format'); -}; - -BasePoint.prototype.encodeCompressed = function encodeCompressed(enc) { - return this.encode(enc, true); -}; - -BasePoint.prototype._encode = function _encode(compact) { - var len = this.curve.p.byteLength(); - var x = this.getX().toArray('be', len); - - if (compact) - return [ this.getY().isEven() ? 0x02 : 0x03 ].concat(x); - - return [ 0x04 ].concat(x, this.getY().toArray('be', len)); -}; - -BasePoint.prototype.encode = function encode(enc, compact) { - return utils.encode(this._encode(compact), enc); -}; - -BasePoint.prototype.precompute = function precompute(power) { - if (this.precomputed) - return this; - - var precomputed = { - doubles: null, - naf: null, - beta: null, - }; - precomputed.naf = this._getNAFPoints(8); - precomputed.doubles = this._getDoubles(4, power); - precomputed.beta = this._getBeta(); - this.precomputed = precomputed; - - return this; -}; - -BasePoint.prototype._hasDoubles = function _hasDoubles(k) { - if (!this.precomputed) - return false; - - var doubles = this.precomputed.doubles; - if (!doubles) - return false; - - return doubles.points.length >= Math.ceil((k.bitLength() + 1) / doubles.step); -}; - -BasePoint.prototype._getDoubles = function _getDoubles(step, power) { - if (this.precomputed && this.precomputed.doubles) - return this.precomputed.doubles; - - var doubles = [ this ]; - var acc = this; - for (var i = 0; i < power; i += step) { - for (var j = 0; j < step; j++) - acc = acc.dbl(); - doubles.push(acc); - } - return { - step: step, - points: doubles, - }; -}; - -BasePoint.prototype._getNAFPoints = function _getNAFPoints(wnd) { - if (this.precomputed && this.precomputed.naf) - return this.precomputed.naf; - - var res = [ this ]; - var max = (1 << wnd) - 1; - var dbl = max === 1 ? null : this.dbl(); - for (var i = 1; i < max; i++) - res[i] = res[i - 1].add(dbl); - return { - wnd: wnd, - points: res, - }; -}; - -BasePoint.prototype._getBeta = function _getBeta() { - return null; -}; - -BasePoint.prototype.dblp = function dblp(k) { - var r = this; - for (var i = 0; i < k; i++) - r = r.dbl(); - return r; -}; - -},{"../utils":199,"bn.js":200}],187:[function(require,module,exports){ -'use strict'; - -var utils = require('../utils'); -var BN = require('bn.js'); -var inherits = require('inherits'); -var Base = require('./base'); - -var assert = utils.assert; - -function EdwardsCurve(conf) { - // NOTE: Important as we are creating point in Base.call() - this.twisted = (conf.a | 0) !== 1; - this.mOneA = this.twisted && (conf.a | 0) === -1; - this.extended = this.mOneA; - - Base.call(this, 'edwards', conf); - - this.a = new BN(conf.a, 16).umod(this.red.m); - this.a = this.a.toRed(this.red); - this.c = new BN(conf.c, 16).toRed(this.red); - this.c2 = this.c.redSqr(); - this.d = new BN(conf.d, 16).toRed(this.red); - this.dd = this.d.redAdd(this.d); - - assert(!this.twisted || this.c.fromRed().cmpn(1) === 0); - this.oneC = (conf.c | 0) === 1; -} -inherits(EdwardsCurve, Base); -module.exports = EdwardsCurve; - -EdwardsCurve.prototype._mulA = function _mulA(num) { - if (this.mOneA) - return num.redNeg(); - else - return this.a.redMul(num); -}; - -EdwardsCurve.prototype._mulC = function _mulC(num) { - if (this.oneC) - return num; - else - return this.c.redMul(num); -}; - -// Just for compatibility with Short curve -EdwardsCurve.prototype.jpoint = function jpoint(x, y, z, t) { - return this.point(x, y, z, t); -}; - -EdwardsCurve.prototype.pointFromX = function pointFromX(x, odd) { - x = new BN(x, 16); - if (!x.red) - x = x.toRed(this.red); - - var x2 = x.redSqr(); - var rhs = this.c2.redSub(this.a.redMul(x2)); - var lhs = this.one.redSub(this.c2.redMul(this.d).redMul(x2)); - - var y2 = rhs.redMul(lhs.redInvm()); - var y = y2.redSqrt(); - if (y.redSqr().redSub(y2).cmp(this.zero) !== 0) - throw new Error('invalid point'); - - var isOdd = y.fromRed().isOdd(); - if (odd && !isOdd || !odd && isOdd) - y = y.redNeg(); - - return this.point(x, y); -}; - -EdwardsCurve.prototype.pointFromY = function pointFromY(y, odd) { - y = new BN(y, 16); - if (!y.red) - y = y.toRed(this.red); - - // x^2 = (y^2 - c^2) / (c^2 d y^2 - a) - var y2 = y.redSqr(); - var lhs = y2.redSub(this.c2); - var rhs = y2.redMul(this.d).redMul(this.c2).redSub(this.a); - var x2 = lhs.redMul(rhs.redInvm()); - - if (x2.cmp(this.zero) === 0) { - if (odd) - throw new Error('invalid point'); - else - return this.point(this.zero, y); - } - - var x = x2.redSqrt(); - if (x.redSqr().redSub(x2).cmp(this.zero) !== 0) - throw new Error('invalid point'); - - if (x.fromRed().isOdd() !== odd) - x = x.redNeg(); - - return this.point(x, y); -}; - -EdwardsCurve.prototype.validate = function validate(point) { - if (point.isInfinity()) - return true; - - // Curve: A * X^2 + Y^2 = C^2 * (1 + D * X^2 * Y^2) - point.normalize(); - - var x2 = point.x.redSqr(); - var y2 = point.y.redSqr(); - var lhs = x2.redMul(this.a).redAdd(y2); - var rhs = this.c2.redMul(this.one.redAdd(this.d.redMul(x2).redMul(y2))); - - return lhs.cmp(rhs) === 0; -}; - -function Point(curve, x, y, z, t) { - Base.BasePoint.call(this, curve, 'projective'); - if (x === null && y === null && z === null) { - this.x = this.curve.zero; - this.y = this.curve.one; - this.z = this.curve.one; - this.t = this.curve.zero; - this.zOne = true; - } else { - this.x = new BN(x, 16); - this.y = new BN(y, 16); - this.z = z ? new BN(z, 16) : this.curve.one; - this.t = t && new BN(t, 16); - if (!this.x.red) - this.x = this.x.toRed(this.curve.red); - if (!this.y.red) - this.y = this.y.toRed(this.curve.red); - if (!this.z.red) - this.z = this.z.toRed(this.curve.red); - if (this.t && !this.t.red) - this.t = this.t.toRed(this.curve.red); - this.zOne = this.z === this.curve.one; - - // Use extended coordinates - if (this.curve.extended && !this.t) { - this.t = this.x.redMul(this.y); - if (!this.zOne) - this.t = this.t.redMul(this.z.redInvm()); - } - } -} -inherits(Point, Base.BasePoint); - -EdwardsCurve.prototype.pointFromJSON = function pointFromJSON(obj) { - return Point.fromJSON(this, obj); -}; - -EdwardsCurve.prototype.point = function point(x, y, z, t) { - return new Point(this, x, y, z, t); -}; - -Point.fromJSON = function fromJSON(curve, obj) { - return new Point(curve, obj[0], obj[1], obj[2]); -}; - -Point.prototype.inspect = function inspect() { - if (this.isInfinity()) - return ''; - return ''; -}; - -Point.prototype.isInfinity = function isInfinity() { - // XXX This code assumes that zero is always zero in red - return this.x.cmpn(0) === 0 && - (this.y.cmp(this.z) === 0 || - (this.zOne && this.y.cmp(this.curve.c) === 0)); -}; - -Point.prototype._extDbl = function _extDbl() { - // hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html - // #doubling-dbl-2008-hwcd - // 4M + 4S - - // A = X1^2 - var a = this.x.redSqr(); - // B = Y1^2 - var b = this.y.redSqr(); - // C = 2 * Z1^2 - var c = this.z.redSqr(); - c = c.redIAdd(c); - // D = a * A - var d = this.curve._mulA(a); - // E = (X1 + Y1)^2 - A - B - var e = this.x.redAdd(this.y).redSqr().redISub(a).redISub(b); - // G = D + B - var g = d.redAdd(b); - // F = G - C - var f = g.redSub(c); - // H = D - B - var h = d.redSub(b); - // X3 = E * F - var nx = e.redMul(f); - // Y3 = G * H - var ny = g.redMul(h); - // T3 = E * H - var nt = e.redMul(h); - // Z3 = F * G - var nz = f.redMul(g); - return this.curve.point(nx, ny, nz, nt); -}; - -Point.prototype._projDbl = function _projDbl() { - // hyperelliptic.org/EFD/g1p/auto-twisted-projective.html - // #doubling-dbl-2008-bbjlp - // #doubling-dbl-2007-bl - // and others - // Generally 3M + 4S or 2M + 4S - - // B = (X1 + Y1)^2 - var b = this.x.redAdd(this.y).redSqr(); - // C = X1^2 - var c = this.x.redSqr(); - // D = Y1^2 - var d = this.y.redSqr(); - - var nx; - var ny; - var nz; - var e; - var h; - var j; - if (this.curve.twisted) { - // E = a * C - e = this.curve._mulA(c); - // F = E + D - var f = e.redAdd(d); - if (this.zOne) { - // X3 = (B - C - D) * (F - 2) - nx = b.redSub(c).redSub(d).redMul(f.redSub(this.curve.two)); - // Y3 = F * (E - D) - ny = f.redMul(e.redSub(d)); - // Z3 = F^2 - 2 * F - nz = f.redSqr().redSub(f).redSub(f); - } else { - // H = Z1^2 - h = this.z.redSqr(); - // J = F - 2 * H - j = f.redSub(h).redISub(h); - // X3 = (B-C-D)*J - nx = b.redSub(c).redISub(d).redMul(j); - // Y3 = F * (E - D) - ny = f.redMul(e.redSub(d)); - // Z3 = F * J - nz = f.redMul(j); - } - } else { - // E = C + D - e = c.redAdd(d); - // H = (c * Z1)^2 - h = this.curve._mulC(this.z).redSqr(); - // J = E - 2 * H - j = e.redSub(h).redSub(h); - // X3 = c * (B - E) * J - nx = this.curve._mulC(b.redISub(e)).redMul(j); - // Y3 = c * E * (C - D) - ny = this.curve._mulC(e).redMul(c.redISub(d)); - // Z3 = E * J - nz = e.redMul(j); - } - return this.curve.point(nx, ny, nz); -}; - -Point.prototype.dbl = function dbl() { - if (this.isInfinity()) - return this; - - // Double in extended coordinates - if (this.curve.extended) - return this._extDbl(); - else - return this._projDbl(); -}; - -Point.prototype._extAdd = function _extAdd(p) { - // hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html - // #addition-add-2008-hwcd-3 - // 8M - - // A = (Y1 - X1) * (Y2 - X2) - var a = this.y.redSub(this.x).redMul(p.y.redSub(p.x)); - // B = (Y1 + X1) * (Y2 + X2) - var b = this.y.redAdd(this.x).redMul(p.y.redAdd(p.x)); - // C = T1 * k * T2 - var c = this.t.redMul(this.curve.dd).redMul(p.t); - // D = Z1 * 2 * Z2 - var d = this.z.redMul(p.z.redAdd(p.z)); - // E = B - A - var e = b.redSub(a); - // F = D - C - var f = d.redSub(c); - // G = D + C - var g = d.redAdd(c); - // H = B + A - var h = b.redAdd(a); - // X3 = E * F - var nx = e.redMul(f); - // Y3 = G * H - var ny = g.redMul(h); - // T3 = E * H - var nt = e.redMul(h); - // Z3 = F * G - var nz = f.redMul(g); - return this.curve.point(nx, ny, nz, nt); -}; - -Point.prototype._projAdd = function _projAdd(p) { - // hyperelliptic.org/EFD/g1p/auto-twisted-projective.html - // #addition-add-2008-bbjlp - // #addition-add-2007-bl - // 10M + 1S - - // A = Z1 * Z2 - var a = this.z.redMul(p.z); - // B = A^2 - var b = a.redSqr(); - // C = X1 * X2 - var c = this.x.redMul(p.x); - // D = Y1 * Y2 - var d = this.y.redMul(p.y); - // E = d * C * D - var e = this.curve.d.redMul(c).redMul(d); - // F = B - E - var f = b.redSub(e); - // G = B + E - var g = b.redAdd(e); - // X3 = A * F * ((X1 + Y1) * (X2 + Y2) - C - D) - var tmp = this.x.redAdd(this.y).redMul(p.x.redAdd(p.y)).redISub(c).redISub(d); - var nx = a.redMul(f).redMul(tmp); - var ny; - var nz; - if (this.curve.twisted) { - // Y3 = A * G * (D - a * C) - ny = a.redMul(g).redMul(d.redSub(this.curve._mulA(c))); - // Z3 = F * G - nz = f.redMul(g); - } else { - // Y3 = A * G * (D - C) - ny = a.redMul(g).redMul(d.redSub(c)); - // Z3 = c * F * G - nz = this.curve._mulC(f).redMul(g); - } - return this.curve.point(nx, ny, nz); -}; - -Point.prototype.add = function add(p) { - if (this.isInfinity()) - return p; - if (p.isInfinity()) - return this; - - if (this.curve.extended) - return this._extAdd(p); - else - return this._projAdd(p); -}; - -Point.prototype.mul = function mul(k) { - if (this._hasDoubles(k)) - return this.curve._fixedNafMul(this, k); - else - return this.curve._wnafMul(this, k); -}; - -Point.prototype.mulAdd = function mulAdd(k1, p, k2) { - return this.curve._wnafMulAdd(1, [ this, p ], [ k1, k2 ], 2, false); -}; - -Point.prototype.jmulAdd = function jmulAdd(k1, p, k2) { - return this.curve._wnafMulAdd(1, [ this, p ], [ k1, k2 ], 2, true); -}; - -Point.prototype.normalize = function normalize() { - if (this.zOne) - return this; - - // Normalize coordinates - var zi = this.z.redInvm(); - this.x = this.x.redMul(zi); - this.y = this.y.redMul(zi); - if (this.t) - this.t = this.t.redMul(zi); - this.z = this.curve.one; - this.zOne = true; - return this; -}; - -Point.prototype.neg = function neg() { - return this.curve.point(this.x.redNeg(), - this.y, - this.z, - this.t && this.t.redNeg()); -}; - -Point.prototype.getX = function getX() { - this.normalize(); - return this.x.fromRed(); -}; - -Point.prototype.getY = function getY() { - this.normalize(); - return this.y.fromRed(); -}; - -Point.prototype.eq = function eq(other) { - return this === other || - this.getX().cmp(other.getX()) === 0 && - this.getY().cmp(other.getY()) === 0; -}; - -Point.prototype.eqXToP = function eqXToP(x) { - var rx = x.toRed(this.curve.red).redMul(this.z); - if (this.x.cmp(rx) === 0) - return true; - - var xc = x.clone(); - var t = this.curve.redN.redMul(this.z); - for (;;) { - xc.iadd(this.curve.n); - if (xc.cmp(this.curve.p) >= 0) - return false; - - rx.redIAdd(t); - if (this.x.cmp(rx) === 0) - return true; - } -}; - -// Compatibility with BaseCurve -Point.prototype.toP = Point.prototype.normalize; -Point.prototype.mixedAdd = Point.prototype.add; - -},{"../utils":199,"./base":186,"bn.js":200,"inherits":256}],188:[function(require,module,exports){ -'use strict'; - -var curve = exports; - -curve.base = require('./base'); -curve.short = require('./short'); -curve.mont = require('./mont'); -curve.edwards = require('./edwards'); - -},{"./base":186,"./edwards":187,"./mont":189,"./short":190}],189:[function(require,module,exports){ -'use strict'; - -var BN = require('bn.js'); -var inherits = require('inherits'); -var Base = require('./base'); - -var utils = require('../utils'); - -function MontCurve(conf) { - Base.call(this, 'mont', conf); - - this.a = new BN(conf.a, 16).toRed(this.red); - this.b = new BN(conf.b, 16).toRed(this.red); - this.i4 = new BN(4).toRed(this.red).redInvm(); - this.two = new BN(2).toRed(this.red); - this.a24 = this.i4.redMul(this.a.redAdd(this.two)); -} -inherits(MontCurve, Base); -module.exports = MontCurve; - -MontCurve.prototype.validate = function validate(point) { - var x = point.normalize().x; - var x2 = x.redSqr(); - var rhs = x2.redMul(x).redAdd(x2.redMul(this.a)).redAdd(x); - var y = rhs.redSqrt(); - - return y.redSqr().cmp(rhs) === 0; -}; - -function Point(curve, x, z) { - Base.BasePoint.call(this, curve, 'projective'); - if (x === null && z === null) { - this.x = this.curve.one; - this.z = this.curve.zero; - } else { - this.x = new BN(x, 16); - this.z = new BN(z, 16); - if (!this.x.red) - this.x = this.x.toRed(this.curve.red); - if (!this.z.red) - this.z = this.z.toRed(this.curve.red); - } -} -inherits(Point, Base.BasePoint); - -MontCurve.prototype.decodePoint = function decodePoint(bytes, enc) { - return this.point(utils.toArray(bytes, enc), 1); -}; - -MontCurve.prototype.point = function point(x, z) { - return new Point(this, x, z); -}; - -MontCurve.prototype.pointFromJSON = function pointFromJSON(obj) { - return Point.fromJSON(this, obj); -}; - -Point.prototype.precompute = function precompute() { - // No-op -}; - -Point.prototype._encode = function _encode() { - return this.getX().toArray('be', this.curve.p.byteLength()); -}; - -Point.fromJSON = function fromJSON(curve, obj) { - return new Point(curve, obj[0], obj[1] || curve.one); -}; - -Point.prototype.inspect = function inspect() { - if (this.isInfinity()) - return ''; - return ''; -}; - -Point.prototype.isInfinity = function isInfinity() { - // XXX This code assumes that zero is always zero in red - return this.z.cmpn(0) === 0; -}; - -Point.prototype.dbl = function dbl() { - // http://hyperelliptic.org/EFD/g1p/auto-montgom-xz.html#doubling-dbl-1987-m-3 - // 2M + 2S + 4A - - // A = X1 + Z1 - var a = this.x.redAdd(this.z); - // AA = A^2 - var aa = a.redSqr(); - // B = X1 - Z1 - var b = this.x.redSub(this.z); - // BB = B^2 - var bb = b.redSqr(); - // C = AA - BB - var c = aa.redSub(bb); - // X3 = AA * BB - var nx = aa.redMul(bb); - // Z3 = C * (BB + A24 * C) - var nz = c.redMul(bb.redAdd(this.curve.a24.redMul(c))); - return this.curve.point(nx, nz); -}; - -Point.prototype.add = function add() { - throw new Error('Not supported on Montgomery curve'); -}; - -Point.prototype.diffAdd = function diffAdd(p, diff) { - // http://hyperelliptic.org/EFD/g1p/auto-montgom-xz.html#diffadd-dadd-1987-m-3 - // 4M + 2S + 6A - - // A = X2 + Z2 - var a = this.x.redAdd(this.z); - // B = X2 - Z2 - var b = this.x.redSub(this.z); - // C = X3 + Z3 - var c = p.x.redAdd(p.z); - // D = X3 - Z3 - var d = p.x.redSub(p.z); - // DA = D * A - var da = d.redMul(a); - // CB = C * B - var cb = c.redMul(b); - // X5 = Z1 * (DA + CB)^2 - var nx = diff.z.redMul(da.redAdd(cb).redSqr()); - // Z5 = X1 * (DA - CB)^2 - var nz = diff.x.redMul(da.redISub(cb).redSqr()); - return this.curve.point(nx, nz); -}; - -Point.prototype.mul = function mul(k) { - var t = k.clone(); - var a = this; // (N / 2) * Q + Q - var b = this.curve.point(null, null); // (N / 2) * Q - var c = this; // Q - - for (var bits = []; t.cmpn(0) !== 0; t.iushrn(1)) - bits.push(t.andln(1)); - - for (var i = bits.length - 1; i >= 0; i--) { - if (bits[i] === 0) { - // N * Q + Q = ((N / 2) * Q + Q)) + (N / 2) * Q - a = a.diffAdd(b, c); - // N * Q = 2 * ((N / 2) * Q + Q)) - b = b.dbl(); - } else { - // N * Q = ((N / 2) * Q + Q) + ((N / 2) * Q) - b = a.diffAdd(b, c); - // N * Q + Q = 2 * ((N / 2) * Q + Q) - a = a.dbl(); - } - } - return b; -}; - -Point.prototype.mulAdd = function mulAdd() { - throw new Error('Not supported on Montgomery curve'); -}; - -Point.prototype.jumlAdd = function jumlAdd() { - throw new Error('Not supported on Montgomery curve'); -}; - -Point.prototype.eq = function eq(other) { - return this.getX().cmp(other.getX()) === 0; -}; - -Point.prototype.normalize = function normalize() { - this.x = this.x.redMul(this.z.redInvm()); - this.z = this.curve.one; - return this; -}; - -Point.prototype.getX = function getX() { - // Normalize coordinates - this.normalize(); - - return this.x.fromRed(); -}; - -},{"../utils":199,"./base":186,"bn.js":200,"inherits":256}],190:[function(require,module,exports){ -'use strict'; - -var utils = require('../utils'); -var BN = require('bn.js'); -var inherits = require('inherits'); -var Base = require('./base'); - -var assert = utils.assert; - -function ShortCurve(conf) { - Base.call(this, 'short', conf); - - this.a = new BN(conf.a, 16).toRed(this.red); - this.b = new BN(conf.b, 16).toRed(this.red); - this.tinv = this.two.redInvm(); - - this.zeroA = this.a.fromRed().cmpn(0) === 0; - this.threeA = this.a.fromRed().sub(this.p).cmpn(-3) === 0; - - // If the curve is endomorphic, precalculate beta and lambda - this.endo = this._getEndomorphism(conf); - this._endoWnafT1 = new Array(4); - this._endoWnafT2 = new Array(4); -} -inherits(ShortCurve, Base); -module.exports = ShortCurve; - -ShortCurve.prototype._getEndomorphism = function _getEndomorphism(conf) { - // No efficient endomorphism - if (!this.zeroA || !this.g || !this.n || this.p.modn(3) !== 1) - return; - - // Compute beta and lambda, that lambda * P = (beta * Px; Py) - var beta; - var lambda; - if (conf.beta) { - beta = new BN(conf.beta, 16).toRed(this.red); - } else { - var betas = this._getEndoRoots(this.p); - // Choose the smallest beta - beta = betas[0].cmp(betas[1]) < 0 ? betas[0] : betas[1]; - beta = beta.toRed(this.red); - } - if (conf.lambda) { - lambda = new BN(conf.lambda, 16); - } else { - // Choose the lambda that is matching selected beta - var lambdas = this._getEndoRoots(this.n); - if (this.g.mul(lambdas[0]).x.cmp(this.g.x.redMul(beta)) === 0) { - lambda = lambdas[0]; - } else { - lambda = lambdas[1]; - assert(this.g.mul(lambda).x.cmp(this.g.x.redMul(beta)) === 0); - } - } - - // Get basis vectors, used for balanced length-two representation - var basis; - if (conf.basis) { - basis = conf.basis.map(function(vec) { - return { - a: new BN(vec.a, 16), - b: new BN(vec.b, 16), - }; - }); - } else { - basis = this._getEndoBasis(lambda); - } - - return { - beta: beta, - lambda: lambda, - basis: basis, - }; -}; - -ShortCurve.prototype._getEndoRoots = function _getEndoRoots(num) { - // Find roots of for x^2 + x + 1 in F - // Root = (-1 +- Sqrt(-3)) / 2 - // - var red = num === this.p ? this.red : BN.mont(num); - var tinv = new BN(2).toRed(red).redInvm(); - var ntinv = tinv.redNeg(); - - var s = new BN(3).toRed(red).redNeg().redSqrt().redMul(tinv); - - var l1 = ntinv.redAdd(s).fromRed(); - var l2 = ntinv.redSub(s).fromRed(); - return [ l1, l2 ]; -}; - -ShortCurve.prototype._getEndoBasis = function _getEndoBasis(lambda) { - // aprxSqrt >= sqrt(this.n) - var aprxSqrt = this.n.ushrn(Math.floor(this.n.bitLength() / 2)); - - // 3.74 - // Run EGCD, until r(L + 1) < aprxSqrt - var u = lambda; - var v = this.n.clone(); - var x1 = new BN(1); - var y1 = new BN(0); - var x2 = new BN(0); - var y2 = new BN(1); - - // NOTE: all vectors are roots of: a + b * lambda = 0 (mod n) - var a0; - var b0; - // First vector - var a1; - var b1; - // Second vector - var a2; - var b2; - - var prevR; - var i = 0; - var r; - var x; - while (u.cmpn(0) !== 0) { - var q = v.div(u); - r = v.sub(q.mul(u)); - x = x2.sub(q.mul(x1)); - var y = y2.sub(q.mul(y1)); - - if (!a1 && r.cmp(aprxSqrt) < 0) { - a0 = prevR.neg(); - b0 = x1; - a1 = r.neg(); - b1 = x; - } else if (a1 && ++i === 2) { - break; - } - prevR = r; - - v = u; - u = r; - x2 = x1; - x1 = x; - y2 = y1; - y1 = y; - } - a2 = r.neg(); - b2 = x; - - var len1 = a1.sqr().add(b1.sqr()); - var len2 = a2.sqr().add(b2.sqr()); - if (len2.cmp(len1) >= 0) { - a2 = a0; - b2 = b0; - } - - // Normalize signs - if (a1.negative) { - a1 = a1.neg(); - b1 = b1.neg(); - } - if (a2.negative) { - a2 = a2.neg(); - b2 = b2.neg(); - } - - return [ - { a: a1, b: b1 }, - { a: a2, b: b2 }, - ]; -}; - -ShortCurve.prototype._endoSplit = function _endoSplit(k) { - var basis = this.endo.basis; - var v1 = basis[0]; - var v2 = basis[1]; - - var c1 = v2.b.mul(k).divRound(this.n); - var c2 = v1.b.neg().mul(k).divRound(this.n); - - var p1 = c1.mul(v1.a); - var p2 = c2.mul(v2.a); - var q1 = c1.mul(v1.b); - var q2 = c2.mul(v2.b); - - // Calculate answer - var k1 = k.sub(p1).sub(p2); - var k2 = q1.add(q2).neg(); - return { k1: k1, k2: k2 }; -}; - -ShortCurve.prototype.pointFromX = function pointFromX(x, odd) { - x = new BN(x, 16); - if (!x.red) - x = x.toRed(this.red); - - var y2 = x.redSqr().redMul(x).redIAdd(x.redMul(this.a)).redIAdd(this.b); - var y = y2.redSqrt(); - if (y.redSqr().redSub(y2).cmp(this.zero) !== 0) - throw new Error('invalid point'); - - // XXX Is there any way to tell if the number is odd without converting it - // to non-red form? - var isOdd = y.fromRed().isOdd(); - if (odd && !isOdd || !odd && isOdd) - y = y.redNeg(); - - return this.point(x, y); -}; - -ShortCurve.prototype.validate = function validate(point) { - if (point.inf) - return true; - - var x = point.x; - var y = point.y; - - var ax = this.a.redMul(x); - var rhs = x.redSqr().redMul(x).redIAdd(ax).redIAdd(this.b); - return y.redSqr().redISub(rhs).cmpn(0) === 0; -}; - -ShortCurve.prototype._endoWnafMulAdd = - function _endoWnafMulAdd(points, coeffs, jacobianResult) { - var npoints = this._endoWnafT1; - var ncoeffs = this._endoWnafT2; - for (var i = 0; i < points.length; i++) { - var split = this._endoSplit(coeffs[i]); - var p = points[i]; - var beta = p._getBeta(); - - if (split.k1.negative) { - split.k1.ineg(); - p = p.neg(true); - } - if (split.k2.negative) { - split.k2.ineg(); - beta = beta.neg(true); - } - - npoints[i * 2] = p; - npoints[i * 2 + 1] = beta; - ncoeffs[i * 2] = split.k1; - ncoeffs[i * 2 + 1] = split.k2; - } - var res = this._wnafMulAdd(1, npoints, ncoeffs, i * 2, jacobianResult); - - // Clean-up references to points and coefficients - for (var j = 0; j < i * 2; j++) { - npoints[j] = null; - ncoeffs[j] = null; - } - return res; - }; - -function Point(curve, x, y, isRed) { - Base.BasePoint.call(this, curve, 'affine'); - if (x === null && y === null) { - this.x = null; - this.y = null; - this.inf = true; - } else { - this.x = new BN(x, 16); - this.y = new BN(y, 16); - // Force redgomery representation when loading from JSON - if (isRed) { - this.x.forceRed(this.curve.red); - this.y.forceRed(this.curve.red); - } - if (!this.x.red) - this.x = this.x.toRed(this.curve.red); - if (!this.y.red) - this.y = this.y.toRed(this.curve.red); - this.inf = false; - } -} -inherits(Point, Base.BasePoint); - -ShortCurve.prototype.point = function point(x, y, isRed) { - return new Point(this, x, y, isRed); -}; - -ShortCurve.prototype.pointFromJSON = function pointFromJSON(obj, red) { - return Point.fromJSON(this, obj, red); -}; - -Point.prototype._getBeta = function _getBeta() { - if (!this.curve.endo) - return; - - var pre = this.precomputed; - if (pre && pre.beta) - return pre.beta; - - var beta = this.curve.point(this.x.redMul(this.curve.endo.beta), this.y); - if (pre) { - var curve = this.curve; - var endoMul = function(p) { - return curve.point(p.x.redMul(curve.endo.beta), p.y); - }; - pre.beta = beta; - beta.precomputed = { - beta: null, - naf: pre.naf && { - wnd: pre.naf.wnd, - points: pre.naf.points.map(endoMul), - }, - doubles: pre.doubles && { - step: pre.doubles.step, - points: pre.doubles.points.map(endoMul), - }, - }; - } - return beta; -}; - -Point.prototype.toJSON = function toJSON() { - if (!this.precomputed) - return [ this.x, this.y ]; - - return [ this.x, this.y, this.precomputed && { - doubles: this.precomputed.doubles && { - step: this.precomputed.doubles.step, - points: this.precomputed.doubles.points.slice(1), - }, - naf: this.precomputed.naf && { - wnd: this.precomputed.naf.wnd, - points: this.precomputed.naf.points.slice(1), - }, - } ]; -}; - -Point.fromJSON = function fromJSON(curve, obj, red) { - if (typeof obj === 'string') - obj = JSON.parse(obj); - var res = curve.point(obj[0], obj[1], red); - if (!obj[2]) - return res; - - function obj2point(obj) { - return curve.point(obj[0], obj[1], red); - } - - var pre = obj[2]; - res.precomputed = { - beta: null, - doubles: pre.doubles && { - step: pre.doubles.step, - points: [ res ].concat(pre.doubles.points.map(obj2point)), - }, - naf: pre.naf && { - wnd: pre.naf.wnd, - points: [ res ].concat(pre.naf.points.map(obj2point)), - }, - }; - return res; -}; - -Point.prototype.inspect = function inspect() { - if (this.isInfinity()) - return ''; - return ''; -}; - -Point.prototype.isInfinity = function isInfinity() { - return this.inf; -}; - -Point.prototype.add = function add(p) { - // O + P = P - if (this.inf) - return p; - - // P + O = P - if (p.inf) - return this; - - // P + P = 2P - if (this.eq(p)) - return this.dbl(); - - // P + (-P) = O - if (this.neg().eq(p)) - return this.curve.point(null, null); - - // P + Q = O - if (this.x.cmp(p.x) === 0) - return this.curve.point(null, null); - - var c = this.y.redSub(p.y); - if (c.cmpn(0) !== 0) - c = c.redMul(this.x.redSub(p.x).redInvm()); - var nx = c.redSqr().redISub(this.x).redISub(p.x); - var ny = c.redMul(this.x.redSub(nx)).redISub(this.y); - return this.curve.point(nx, ny); -}; - -Point.prototype.dbl = function dbl() { - if (this.inf) - return this; - - // 2P = O - var ys1 = this.y.redAdd(this.y); - if (ys1.cmpn(0) === 0) - return this.curve.point(null, null); - - var a = this.curve.a; - - var x2 = this.x.redSqr(); - var dyinv = ys1.redInvm(); - var c = x2.redAdd(x2).redIAdd(x2).redIAdd(a).redMul(dyinv); - - var nx = c.redSqr().redISub(this.x.redAdd(this.x)); - var ny = c.redMul(this.x.redSub(nx)).redISub(this.y); - return this.curve.point(nx, ny); -}; - -Point.prototype.getX = function getX() { - return this.x.fromRed(); -}; - -Point.prototype.getY = function getY() { - return this.y.fromRed(); -}; - -Point.prototype.mul = function mul(k) { - k = new BN(k, 16); - if (this.isInfinity()) - return this; - else if (this._hasDoubles(k)) - return this.curve._fixedNafMul(this, k); - else if (this.curve.endo) - return this.curve._endoWnafMulAdd([ this ], [ k ]); - else - return this.curve._wnafMul(this, k); -}; - -Point.prototype.mulAdd = function mulAdd(k1, p2, k2) { - var points = [ this, p2 ]; - var coeffs = [ k1, k2 ]; - if (this.curve.endo) - return this.curve._endoWnafMulAdd(points, coeffs); - else - return this.curve._wnafMulAdd(1, points, coeffs, 2); -}; - -Point.prototype.jmulAdd = function jmulAdd(k1, p2, k2) { - var points = [ this, p2 ]; - var coeffs = [ k1, k2 ]; - if (this.curve.endo) - return this.curve._endoWnafMulAdd(points, coeffs, true); - else - return this.curve._wnafMulAdd(1, points, coeffs, 2, true); -}; - -Point.prototype.eq = function eq(p) { - return this === p || - this.inf === p.inf && - (this.inf || this.x.cmp(p.x) === 0 && this.y.cmp(p.y) === 0); -}; - -Point.prototype.neg = function neg(_precompute) { - if (this.inf) - return this; - - var res = this.curve.point(this.x, this.y.redNeg()); - if (_precompute && this.precomputed) { - var pre = this.precomputed; - var negate = function(p) { - return p.neg(); - }; - res.precomputed = { - naf: pre.naf && { - wnd: pre.naf.wnd, - points: pre.naf.points.map(negate), - }, - doubles: pre.doubles && { - step: pre.doubles.step, - points: pre.doubles.points.map(negate), - }, - }; - } - return res; -}; - -Point.prototype.toJ = function toJ() { - if (this.inf) - return this.curve.jpoint(null, null, null); - - var res = this.curve.jpoint(this.x, this.y, this.curve.one); - return res; -}; - -function JPoint(curve, x, y, z) { - Base.BasePoint.call(this, curve, 'jacobian'); - if (x === null && y === null && z === null) { - this.x = this.curve.one; - this.y = this.curve.one; - this.z = new BN(0); - } else { - this.x = new BN(x, 16); - this.y = new BN(y, 16); - this.z = new BN(z, 16); - } - if (!this.x.red) - this.x = this.x.toRed(this.curve.red); - if (!this.y.red) - this.y = this.y.toRed(this.curve.red); - if (!this.z.red) - this.z = this.z.toRed(this.curve.red); - - this.zOne = this.z === this.curve.one; -} -inherits(JPoint, Base.BasePoint); - -ShortCurve.prototype.jpoint = function jpoint(x, y, z) { - return new JPoint(this, x, y, z); -}; - -JPoint.prototype.toP = function toP() { - if (this.isInfinity()) - return this.curve.point(null, null); - - var zinv = this.z.redInvm(); - var zinv2 = zinv.redSqr(); - var ax = this.x.redMul(zinv2); - var ay = this.y.redMul(zinv2).redMul(zinv); - - return this.curve.point(ax, ay); -}; - -JPoint.prototype.neg = function neg() { - return this.curve.jpoint(this.x, this.y.redNeg(), this.z); -}; - -JPoint.prototype.add = function add(p) { - // O + P = P - if (this.isInfinity()) - return p; - - // P + O = P - if (p.isInfinity()) - return this; - - // 12M + 4S + 7A - var pz2 = p.z.redSqr(); - var z2 = this.z.redSqr(); - var u1 = this.x.redMul(pz2); - var u2 = p.x.redMul(z2); - var s1 = this.y.redMul(pz2.redMul(p.z)); - var s2 = p.y.redMul(z2.redMul(this.z)); - - var h = u1.redSub(u2); - var r = s1.redSub(s2); - if (h.cmpn(0) === 0) { - if (r.cmpn(0) !== 0) - return this.curve.jpoint(null, null, null); - else - return this.dbl(); - } - - var h2 = h.redSqr(); - var h3 = h2.redMul(h); - var v = u1.redMul(h2); - - var nx = r.redSqr().redIAdd(h3).redISub(v).redISub(v); - var ny = r.redMul(v.redISub(nx)).redISub(s1.redMul(h3)); - var nz = this.z.redMul(p.z).redMul(h); - - return this.curve.jpoint(nx, ny, nz); -}; - -JPoint.prototype.mixedAdd = function mixedAdd(p) { - // O + P = P - if (this.isInfinity()) - return p.toJ(); - - // P + O = P - if (p.isInfinity()) - return this; - - // 8M + 3S + 7A - var z2 = this.z.redSqr(); - var u1 = this.x; - var u2 = p.x.redMul(z2); - var s1 = this.y; - var s2 = p.y.redMul(z2).redMul(this.z); - - var h = u1.redSub(u2); - var r = s1.redSub(s2); - if (h.cmpn(0) === 0) { - if (r.cmpn(0) !== 0) - return this.curve.jpoint(null, null, null); - else - return this.dbl(); - } - - var h2 = h.redSqr(); - var h3 = h2.redMul(h); - var v = u1.redMul(h2); - - var nx = r.redSqr().redIAdd(h3).redISub(v).redISub(v); - var ny = r.redMul(v.redISub(nx)).redISub(s1.redMul(h3)); - var nz = this.z.redMul(h); - - return this.curve.jpoint(nx, ny, nz); -}; - -JPoint.prototype.dblp = function dblp(pow) { - if (pow === 0) - return this; - if (this.isInfinity()) - return this; - if (!pow) - return this.dbl(); - - var i; - if (this.curve.zeroA || this.curve.threeA) { - var r = this; - for (i = 0; i < pow; i++) - r = r.dbl(); - return r; - } - - // 1M + 2S + 1A + N * (4S + 5M + 8A) - // N = 1 => 6M + 6S + 9A - var a = this.curve.a; - var tinv = this.curve.tinv; - - var jx = this.x; - var jy = this.y; - var jz = this.z; - var jz4 = jz.redSqr().redSqr(); - - // Reuse results - var jyd = jy.redAdd(jy); - for (i = 0; i < pow; i++) { - var jx2 = jx.redSqr(); - var jyd2 = jyd.redSqr(); - var jyd4 = jyd2.redSqr(); - var c = jx2.redAdd(jx2).redIAdd(jx2).redIAdd(a.redMul(jz4)); - - var t1 = jx.redMul(jyd2); - var nx = c.redSqr().redISub(t1.redAdd(t1)); - var t2 = t1.redISub(nx); - var dny = c.redMul(t2); - dny = dny.redIAdd(dny).redISub(jyd4); - var nz = jyd.redMul(jz); - if (i + 1 < pow) - jz4 = jz4.redMul(jyd4); - - jx = nx; - jz = nz; - jyd = dny; - } - - return this.curve.jpoint(jx, jyd.redMul(tinv), jz); -}; - -JPoint.prototype.dbl = function dbl() { - if (this.isInfinity()) - return this; - - if (this.curve.zeroA) - return this._zeroDbl(); - else if (this.curve.threeA) - return this._threeDbl(); - else - return this._dbl(); -}; - -JPoint.prototype._zeroDbl = function _zeroDbl() { - var nx; - var ny; - var nz; - // Z = 1 - if (this.zOne) { - // hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html - // #doubling-mdbl-2007-bl - // 1M + 5S + 14A - - // XX = X1^2 - var xx = this.x.redSqr(); - // YY = Y1^2 - var yy = this.y.redSqr(); - // YYYY = YY^2 - var yyyy = yy.redSqr(); - // S = 2 * ((X1 + YY)^2 - XX - YYYY) - var s = this.x.redAdd(yy).redSqr().redISub(xx).redISub(yyyy); - s = s.redIAdd(s); - // M = 3 * XX + a; a = 0 - var m = xx.redAdd(xx).redIAdd(xx); - // T = M ^ 2 - 2*S - var t = m.redSqr().redISub(s).redISub(s); - - // 8 * YYYY - var yyyy8 = yyyy.redIAdd(yyyy); - yyyy8 = yyyy8.redIAdd(yyyy8); - yyyy8 = yyyy8.redIAdd(yyyy8); - - // X3 = T - nx = t; - // Y3 = M * (S - T) - 8 * YYYY - ny = m.redMul(s.redISub(t)).redISub(yyyy8); - // Z3 = 2*Y1 - nz = this.y.redAdd(this.y); - } else { - // hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html - // #doubling-dbl-2009-l - // 2M + 5S + 13A - - // A = X1^2 - var a = this.x.redSqr(); - // B = Y1^2 - var b = this.y.redSqr(); - // C = B^2 - var c = b.redSqr(); - // D = 2 * ((X1 + B)^2 - A - C) - var d = this.x.redAdd(b).redSqr().redISub(a).redISub(c); - d = d.redIAdd(d); - // E = 3 * A - var e = a.redAdd(a).redIAdd(a); - // F = E^2 - var f = e.redSqr(); - - // 8 * C - var c8 = c.redIAdd(c); - c8 = c8.redIAdd(c8); - c8 = c8.redIAdd(c8); - - // X3 = F - 2 * D - nx = f.redISub(d).redISub(d); - // Y3 = E * (D - X3) - 8 * C - ny = e.redMul(d.redISub(nx)).redISub(c8); - // Z3 = 2 * Y1 * Z1 - nz = this.y.redMul(this.z); - nz = nz.redIAdd(nz); - } - - return this.curve.jpoint(nx, ny, nz); -}; - -JPoint.prototype._threeDbl = function _threeDbl() { - var nx; - var ny; - var nz; - // Z = 1 - if (this.zOne) { - // hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html - // #doubling-mdbl-2007-bl - // 1M + 5S + 15A - - // XX = X1^2 - var xx = this.x.redSqr(); - // YY = Y1^2 - var yy = this.y.redSqr(); - // YYYY = YY^2 - var yyyy = yy.redSqr(); - // S = 2 * ((X1 + YY)^2 - XX - YYYY) - var s = this.x.redAdd(yy).redSqr().redISub(xx).redISub(yyyy); - s = s.redIAdd(s); - // M = 3 * XX + a - var m = xx.redAdd(xx).redIAdd(xx).redIAdd(this.curve.a); - // T = M^2 - 2 * S - var t = m.redSqr().redISub(s).redISub(s); - // X3 = T - nx = t; - // Y3 = M * (S - T) - 8 * YYYY - var yyyy8 = yyyy.redIAdd(yyyy); - yyyy8 = yyyy8.redIAdd(yyyy8); - yyyy8 = yyyy8.redIAdd(yyyy8); - ny = m.redMul(s.redISub(t)).redISub(yyyy8); - // Z3 = 2 * Y1 - nz = this.y.redAdd(this.y); - } else { - // hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2001-b - // 3M + 5S - - // delta = Z1^2 - var delta = this.z.redSqr(); - // gamma = Y1^2 - var gamma = this.y.redSqr(); - // beta = X1 * gamma - var beta = this.x.redMul(gamma); - // alpha = 3 * (X1 - delta) * (X1 + delta) - var alpha = this.x.redSub(delta).redMul(this.x.redAdd(delta)); - alpha = alpha.redAdd(alpha).redIAdd(alpha); - // X3 = alpha^2 - 8 * beta - var beta4 = beta.redIAdd(beta); - beta4 = beta4.redIAdd(beta4); - var beta8 = beta4.redAdd(beta4); - nx = alpha.redSqr().redISub(beta8); - // Z3 = (Y1 + Z1)^2 - gamma - delta - nz = this.y.redAdd(this.z).redSqr().redISub(gamma).redISub(delta); - // Y3 = alpha * (4 * beta - X3) - 8 * gamma^2 - var ggamma8 = gamma.redSqr(); - ggamma8 = ggamma8.redIAdd(ggamma8); - ggamma8 = ggamma8.redIAdd(ggamma8); - ggamma8 = ggamma8.redIAdd(ggamma8); - ny = alpha.redMul(beta4.redISub(nx)).redISub(ggamma8); - } - - return this.curve.jpoint(nx, ny, nz); -}; - -JPoint.prototype._dbl = function _dbl() { - var a = this.curve.a; - - // 4M + 6S + 10A - var jx = this.x; - var jy = this.y; - var jz = this.z; - var jz4 = jz.redSqr().redSqr(); - - var jx2 = jx.redSqr(); - var jy2 = jy.redSqr(); - - var c = jx2.redAdd(jx2).redIAdd(jx2).redIAdd(a.redMul(jz4)); - - var jxd4 = jx.redAdd(jx); - jxd4 = jxd4.redIAdd(jxd4); - var t1 = jxd4.redMul(jy2); - var nx = c.redSqr().redISub(t1.redAdd(t1)); - var t2 = t1.redISub(nx); - - var jyd8 = jy2.redSqr(); - jyd8 = jyd8.redIAdd(jyd8); - jyd8 = jyd8.redIAdd(jyd8); - jyd8 = jyd8.redIAdd(jyd8); - var ny = c.redMul(t2).redISub(jyd8); - var nz = jy.redAdd(jy).redMul(jz); - - return this.curve.jpoint(nx, ny, nz); -}; - -JPoint.prototype.trpl = function trpl() { - if (!this.curve.zeroA) - return this.dbl().add(this); - - // hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#tripling-tpl-2007-bl - // 5M + 10S + ... - - // XX = X1^2 - var xx = this.x.redSqr(); - // YY = Y1^2 - var yy = this.y.redSqr(); - // ZZ = Z1^2 - var zz = this.z.redSqr(); - // YYYY = YY^2 - var yyyy = yy.redSqr(); - // M = 3 * XX + a * ZZ2; a = 0 - var m = xx.redAdd(xx).redIAdd(xx); - // MM = M^2 - var mm = m.redSqr(); - // E = 6 * ((X1 + YY)^2 - XX - YYYY) - MM - var e = this.x.redAdd(yy).redSqr().redISub(xx).redISub(yyyy); - e = e.redIAdd(e); - e = e.redAdd(e).redIAdd(e); - e = e.redISub(mm); - // EE = E^2 - var ee = e.redSqr(); - // T = 16*YYYY - var t = yyyy.redIAdd(yyyy); - t = t.redIAdd(t); - t = t.redIAdd(t); - t = t.redIAdd(t); - // U = (M + E)^2 - MM - EE - T - var u = m.redIAdd(e).redSqr().redISub(mm).redISub(ee).redISub(t); - // X3 = 4 * (X1 * EE - 4 * YY * U) - var yyu4 = yy.redMul(u); - yyu4 = yyu4.redIAdd(yyu4); - yyu4 = yyu4.redIAdd(yyu4); - var nx = this.x.redMul(ee).redISub(yyu4); - nx = nx.redIAdd(nx); - nx = nx.redIAdd(nx); - // Y3 = 8 * Y1 * (U * (T - U) - E * EE) - var ny = this.y.redMul(u.redMul(t.redISub(u)).redISub(e.redMul(ee))); - ny = ny.redIAdd(ny); - ny = ny.redIAdd(ny); - ny = ny.redIAdd(ny); - // Z3 = (Z1 + E)^2 - ZZ - EE - var nz = this.z.redAdd(e).redSqr().redISub(zz).redISub(ee); - - return this.curve.jpoint(nx, ny, nz); -}; - -JPoint.prototype.mul = function mul(k, kbase) { - k = new BN(k, kbase); - - return this.curve._wnafMul(this, k); -}; - -JPoint.prototype.eq = function eq(p) { - if (p.type === 'affine') - return this.eq(p.toJ()); - - if (this === p) - return true; - - // x1 * z2^2 == x2 * z1^2 - var z2 = this.z.redSqr(); - var pz2 = p.z.redSqr(); - if (this.x.redMul(pz2).redISub(p.x.redMul(z2)).cmpn(0) !== 0) - return false; - - // y1 * z2^3 == y2 * z1^3 - var z3 = z2.redMul(this.z); - var pz3 = pz2.redMul(p.z); - return this.y.redMul(pz3).redISub(p.y.redMul(z3)).cmpn(0) === 0; -}; - -JPoint.prototype.eqXToP = function eqXToP(x) { - var zs = this.z.redSqr(); - var rx = x.toRed(this.curve.red).redMul(zs); - if (this.x.cmp(rx) === 0) - return true; - - var xc = x.clone(); - var t = this.curve.redN.redMul(zs); - for (;;) { - xc.iadd(this.curve.n); - if (xc.cmp(this.curve.p) >= 0) - return false; - - rx.redIAdd(t); - if (this.x.cmp(rx) === 0) - return true; - } -}; - -JPoint.prototype.inspect = function inspect() { - if (this.isInfinity()) - return ''; - return ''; -}; - -JPoint.prototype.isInfinity = function isInfinity() { - // XXX This code assumes that zero is always zero in red - return this.z.cmpn(0) === 0; -}; - -},{"../utils":199,"./base":186,"bn.js":200,"inherits":256}],191:[function(require,module,exports){ -'use strict'; - -var curves = exports; - -var hash = require('hash.js'); -var curve = require('./curve'); -var utils = require('./utils'); - -var assert = utils.assert; - -function PresetCurve(options) { - if (options.type === 'short') - this.curve = new curve.short(options); - else if (options.type === 'edwards') - this.curve = new curve.edwards(options); - else - this.curve = new curve.mont(options); - this.g = this.curve.g; - this.n = this.curve.n; - this.hash = options.hash; - - assert(this.g.validate(), 'Invalid curve'); - assert(this.g.mul(this.n).isInfinity(), 'Invalid curve, G*N != O'); -} -curves.PresetCurve = PresetCurve; - -function defineCurve(name, options) { - Object.defineProperty(curves, name, { - configurable: true, - enumerable: true, - get: function() { - var curve = new PresetCurve(options); - Object.defineProperty(curves, name, { - configurable: true, - enumerable: true, - value: curve, - }); - return curve; - }, - }); -} - -defineCurve('p192', { - type: 'short', - prime: 'p192', - p: 'ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff', - a: 'ffffffff ffffffff ffffffff fffffffe ffffffff fffffffc', - b: '64210519 e59c80e7 0fa7e9ab 72243049 feb8deec c146b9b1', - n: 'ffffffff ffffffff ffffffff 99def836 146bc9b1 b4d22831', - hash: hash.sha256, - gRed: false, - g: [ - '188da80e b03090f6 7cbf20eb 43a18800 f4ff0afd 82ff1012', - '07192b95 ffc8da78 631011ed 6b24cdd5 73f977a1 1e794811', - ], -}); - -defineCurve('p224', { - type: 'short', - prime: 'p224', - p: 'ffffffff ffffffff ffffffff ffffffff 00000000 00000000 00000001', - a: 'ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff fffffffe', - b: 'b4050a85 0c04b3ab f5413256 5044b0b7 d7bfd8ba 270b3943 2355ffb4', - n: 'ffffffff ffffffff ffffffff ffff16a2 e0b8f03e 13dd2945 5c5c2a3d', - hash: hash.sha256, - gRed: false, - g: [ - 'b70e0cbd 6bb4bf7f 321390b9 4a03c1d3 56c21122 343280d6 115c1d21', - 'bd376388 b5f723fb 4c22dfe6 cd4375a0 5a074764 44d58199 85007e34', - ], -}); - -defineCurve('p256', { - type: 'short', - prime: null, - p: 'ffffffff 00000001 00000000 00000000 00000000 ffffffff ffffffff ffffffff', - a: 'ffffffff 00000001 00000000 00000000 00000000 ffffffff ffffffff fffffffc', - b: '5ac635d8 aa3a93e7 b3ebbd55 769886bc 651d06b0 cc53b0f6 3bce3c3e 27d2604b', - n: 'ffffffff 00000000 ffffffff ffffffff bce6faad a7179e84 f3b9cac2 fc632551', - hash: hash.sha256, - gRed: false, - g: [ - '6b17d1f2 e12c4247 f8bce6e5 63a440f2 77037d81 2deb33a0 f4a13945 d898c296', - '4fe342e2 fe1a7f9b 8ee7eb4a 7c0f9e16 2bce3357 6b315ece cbb64068 37bf51f5', - ], -}); - -defineCurve('p384', { - type: 'short', - prime: null, - p: 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ' + - 'fffffffe ffffffff 00000000 00000000 ffffffff', - a: 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ' + - 'fffffffe ffffffff 00000000 00000000 fffffffc', - b: 'b3312fa7 e23ee7e4 988e056b e3f82d19 181d9c6e fe814112 0314088f ' + - '5013875a c656398d 8a2ed19d 2a85c8ed d3ec2aef', - n: 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff c7634d81 ' + - 'f4372ddf 581a0db2 48b0a77a ecec196a ccc52973', - hash: hash.sha384, - gRed: false, - g: [ - 'aa87ca22 be8b0537 8eb1c71e f320ad74 6e1d3b62 8ba79b98 59f741e0 82542a38 ' + - '5502f25d bf55296c 3a545e38 72760ab7', - '3617de4a 96262c6f 5d9e98bf 9292dc29 f8f41dbd 289a147c e9da3113 b5f0b8c0 ' + - '0a60b1ce 1d7e819d 7a431d7c 90ea0e5f', - ], -}); - -defineCurve('p521', { - type: 'short', - prime: null, - p: '000001ff ffffffff ffffffff ffffffff ffffffff ffffffff ' + - 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ' + - 'ffffffff ffffffff ffffffff ffffffff ffffffff', - a: '000001ff ffffffff ffffffff ffffffff ffffffff ffffffff ' + - 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ' + - 'ffffffff ffffffff ffffffff ffffffff fffffffc', - b: '00000051 953eb961 8e1c9a1f 929a21a0 b68540ee a2da725b ' + - '99b315f3 b8b48991 8ef109e1 56193951 ec7e937b 1652c0bd ' + - '3bb1bf07 3573df88 3d2c34f1 ef451fd4 6b503f00', - n: '000001ff ffffffff ffffffff ffffffff ffffffff ffffffff ' + - 'ffffffff ffffffff fffffffa 51868783 bf2f966b 7fcc0148 ' + - 'f709a5d0 3bb5c9b8 899c47ae bb6fb71e 91386409', - hash: hash.sha512, - gRed: false, - g: [ - '000000c6 858e06b7 0404e9cd 9e3ecb66 2395b442 9c648139 ' + - '053fb521 f828af60 6b4d3dba a14b5e77 efe75928 fe1dc127 ' + - 'a2ffa8de 3348b3c1 856a429b f97e7e31 c2e5bd66', - '00000118 39296a78 9a3bc004 5c8a5fb4 2c7d1bd9 98f54449 ' + - '579b4468 17afbd17 273e662c 97ee7299 5ef42640 c550b901 ' + - '3fad0761 353c7086 a272c240 88be9476 9fd16650', - ], -}); - -defineCurve('curve25519', { - type: 'mont', - prime: 'p25519', - p: '7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed', - a: '76d06', - b: '1', - n: '1000000000000000 0000000000000000 14def9dea2f79cd6 5812631a5cf5d3ed', - hash: hash.sha256, - gRed: false, - g: [ - '9', - ], -}); - -defineCurve('ed25519', { - type: 'edwards', - prime: 'p25519', - p: '7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed', - a: '-1', - c: '1', - // -121665 * (121666^(-1)) (mod P) - d: '52036cee2b6ffe73 8cc740797779e898 00700a4d4141d8ab 75eb4dca135978a3', - n: '1000000000000000 0000000000000000 14def9dea2f79cd6 5812631a5cf5d3ed', - hash: hash.sha256, - gRed: false, - g: [ - '216936d3cd6e53fec0a4e231fdd6dc5c692cc7609525a7b2c9562d608f25d51a', - - // 4/5 - '6666666666666666666666666666666666666666666666666666666666666658', - ], -}); - -var pre; -try { - pre = require('./precomputed/secp256k1'); -} catch (e) { - pre = undefined; -} - -defineCurve('secp256k1', { - type: 'short', - prime: 'k256', - p: 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe fffffc2f', - a: '0', - b: '7', - n: 'ffffffff ffffffff ffffffff fffffffe baaedce6 af48a03b bfd25e8c d0364141', - h: '1', - hash: hash.sha256, - - // Precomputed endomorphism - beta: '7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee', - lambda: '5363ad4cc05c30e0a5261c028812645a122e22ea20816678df02967c1b23bd72', - basis: [ - { - a: '3086d221a7d46bcde86c90e49284eb15', - b: '-e4437ed6010e88286f547fa90abfe4c3', - }, - { - a: '114ca50f7a8e2f3f657c1108d9d44cfd8', - b: '3086d221a7d46bcde86c90e49284eb15', - }, - ], - - gRed: false, - g: [ - '79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798', - '483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8', - pre, - ], -}); - -},{"./curve":188,"./precomputed/secp256k1":198,"./utils":199,"hash.js":241}],192:[function(require,module,exports){ -'use strict'; - -var BN = require('bn.js'); -var HmacDRBG = require('hmac-drbg'); -var utils = require('../utils'); -var curves = require('../curves'); -var rand = require('brorand'); -var assert = utils.assert; - -var KeyPair = require('./key'); -var Signature = require('./signature'); - -function EC(options) { - if (!(this instanceof EC)) - return new EC(options); - - // Shortcut `elliptic.ec(curve-name)` - if (typeof options === 'string') { - assert(Object.prototype.hasOwnProperty.call(curves, options), - 'Unknown curve ' + options); - - options = curves[options]; - } - - // Shortcut for `elliptic.ec(elliptic.curves.curveName)` - if (options instanceof curves.PresetCurve) - options = { curve: options }; - - this.curve = options.curve.curve; - this.n = this.curve.n; - this.nh = this.n.ushrn(1); - this.g = this.curve.g; - - // Point on curve - this.g = options.curve.g; - this.g.precompute(options.curve.n.bitLength() + 1); - - // Hash for function for DRBG - this.hash = options.hash || options.curve.hash; -} -module.exports = EC; - -EC.prototype.keyPair = function keyPair(options) { - return new KeyPair(this, options); -}; - -EC.prototype.keyFromPrivate = function keyFromPrivate(priv, enc) { - return KeyPair.fromPrivate(this, priv, enc); -}; - -EC.prototype.keyFromPublic = function keyFromPublic(pub, enc) { - return KeyPair.fromPublic(this, pub, enc); -}; - -EC.prototype.genKeyPair = function genKeyPair(options) { - if (!options) - options = {}; - - // Instantiate Hmac_DRBG - var drbg = new HmacDRBG({ - hash: this.hash, - pers: options.pers, - persEnc: options.persEnc || 'utf8', - entropy: options.entropy || rand(this.hash.hmacStrength), - entropyEnc: options.entropy && options.entropyEnc || 'utf8', - nonce: this.n.toArray(), - }); - - var bytes = this.n.byteLength(); - var ns2 = this.n.sub(new BN(2)); - for (;;) { - var priv = new BN(drbg.generate(bytes)); - if (priv.cmp(ns2) > 0) - continue; - - priv.iaddn(1); - return this.keyFromPrivate(priv); - } -}; - -EC.prototype._truncateToN = function _truncateToN(msg, truncOnly) { - var delta = msg.byteLength() * 8 - this.n.bitLength(); - if (delta > 0) - msg = msg.ushrn(delta); - if (!truncOnly && msg.cmp(this.n) >= 0) - return msg.sub(this.n); - else - return msg; -}; - -EC.prototype.sign = function sign(msg, key, enc, options) { - if (typeof enc === 'object') { - options = enc; - enc = null; - } - if (!options) - options = {}; - - key = this.keyFromPrivate(key, enc); - msg = this._truncateToN(new BN(msg, 16)); - - // Zero-extend key to provide enough entropy - var bytes = this.n.byteLength(); - var bkey = key.getPrivate().toArray('be', bytes); - - // Zero-extend nonce to have the same byte size as N - var nonce = msg.toArray('be', bytes); - - // Instantiate Hmac_DRBG - var drbg = new HmacDRBG({ - hash: this.hash, - entropy: bkey, - nonce: nonce, - pers: options.pers, - persEnc: options.persEnc || 'utf8', - }); - - // Number of bytes to generate - var ns1 = this.n.sub(new BN(1)); - - for (var iter = 0; ; iter++) { - var k = options.k ? - options.k(iter) : - new BN(drbg.generate(this.n.byteLength())); - k = this._truncateToN(k, true); - if (k.cmpn(1) <= 0 || k.cmp(ns1) >= 0) - continue; - - var kp = this.g.mul(k); - if (kp.isInfinity()) - continue; - - var kpX = kp.getX(); - var r = kpX.umod(this.n); - if (r.cmpn(0) === 0) - continue; - - var s = k.invm(this.n).mul(r.mul(key.getPrivate()).iadd(msg)); - s = s.umod(this.n); - if (s.cmpn(0) === 0) - continue; - - var recoveryParam = (kp.getY().isOdd() ? 1 : 0) | - (kpX.cmp(r) !== 0 ? 2 : 0); - - // Use complement of `s`, if it is > `n / 2` - if (options.canonical && s.cmp(this.nh) > 0) { - s = this.n.sub(s); - recoveryParam ^= 1; - } - - return new Signature({ r: r, s: s, recoveryParam: recoveryParam }); - } -}; - -EC.prototype.verify = function verify(msg, signature, key, enc) { - msg = this._truncateToN(new BN(msg, 16)); - key = this.keyFromPublic(key, enc); - signature = new Signature(signature, 'hex'); - - // Perform primitive values validation - var r = signature.r; - var s = signature.s; - if (r.cmpn(1) < 0 || r.cmp(this.n) >= 0) - return false; - if (s.cmpn(1) < 0 || s.cmp(this.n) >= 0) - return false; - - // Validate signature - var sinv = s.invm(this.n); - var u1 = sinv.mul(msg).umod(this.n); - var u2 = sinv.mul(r).umod(this.n); - var p; - - if (!this.curve._maxwellTrick) { - p = this.g.mulAdd(u1, key.getPublic(), u2); - if (p.isInfinity()) - return false; - - return p.getX().umod(this.n).cmp(r) === 0; - } - - // NOTE: Greg Maxwell's trick, inspired by: - // https://git.io/vad3K - - p = this.g.jmulAdd(u1, key.getPublic(), u2); - if (p.isInfinity()) - return false; - - // Compare `p.x` of Jacobian point with `r`, - // this will do `p.x == r * p.z^2` instead of multiplying `p.x` by the - // inverse of `p.z^2` - return p.eqXToP(r); -}; - -EC.prototype.recoverPubKey = function(msg, signature, j, enc) { - assert((3 & j) === j, 'The recovery param is more than two bits'); - signature = new Signature(signature, enc); - - var n = this.n; - var e = new BN(msg); - var r = signature.r; - var s = signature.s; - - // A set LSB signifies that the y-coordinate is odd - var isYOdd = j & 1; - var isSecondKey = j >> 1; - if (r.cmp(this.curve.p.umod(this.curve.n)) >= 0 && isSecondKey) - throw new Error('Unable to find sencond key candinate'); - - // 1.1. Let x = r + jn. - if (isSecondKey) - r = this.curve.pointFromX(r.add(this.curve.n), isYOdd); - else - r = this.curve.pointFromX(r, isYOdd); - - var rInv = signature.r.invm(n); - var s1 = n.sub(e).mul(rInv).umod(n); - var s2 = s.mul(rInv).umod(n); - - // 1.6.1 Compute Q = r^-1 (sR - eG) - // Q = r^-1 (sR + -eG) - return this.g.mulAdd(s1, r, s2); -}; - -EC.prototype.getKeyRecoveryParam = function(e, signature, Q, enc) { - signature = new Signature(signature, enc); - if (signature.recoveryParam !== null) - return signature.recoveryParam; - - for (var i = 0; i < 4; i++) { - var Qprime; - try { - Qprime = this.recoverPubKey(e, signature, i); - } catch (e) { - continue; - } - - if (Qprime.eq(Q)) - return i; - } - throw new Error('Unable to find valid recovery factor'); -}; - -},{"../curves":191,"../utils":199,"./key":193,"./signature":194,"bn.js":200,"brorand":92,"hmac-drbg":254}],193:[function(require,module,exports){ -'use strict'; - -var BN = require('bn.js'); -var utils = require('../utils'); -var assert = utils.assert; - -function KeyPair(ec, options) { - this.ec = ec; - this.priv = null; - this.pub = null; - - // KeyPair(ec, { priv: ..., pub: ... }) - if (options.priv) - this._importPrivate(options.priv, options.privEnc); - if (options.pub) - this._importPublic(options.pub, options.pubEnc); -} -module.exports = KeyPair; - -KeyPair.fromPublic = function fromPublic(ec, pub, enc) { - if (pub instanceof KeyPair) - return pub; - - return new KeyPair(ec, { - pub: pub, - pubEnc: enc, - }); -}; - -KeyPair.fromPrivate = function fromPrivate(ec, priv, enc) { - if (priv instanceof KeyPair) - return priv; - - return new KeyPair(ec, { - priv: priv, - privEnc: enc, - }); -}; - -KeyPair.prototype.validate = function validate() { - var pub = this.getPublic(); - - if (pub.isInfinity()) - return { result: false, reason: 'Invalid public key' }; - if (!pub.validate()) - return { result: false, reason: 'Public key is not a point' }; - if (!pub.mul(this.ec.curve.n).isInfinity()) - return { result: false, reason: 'Public key * N != O' }; - - return { result: true, reason: null }; -}; - -KeyPair.prototype.getPublic = function getPublic(compact, enc) { - // compact is optional argument - if (typeof compact === 'string') { - enc = compact; - compact = null; - } - - if (!this.pub) - this.pub = this.ec.g.mul(this.priv); - - if (!enc) - return this.pub; - - return this.pub.encode(enc, compact); -}; - -KeyPair.prototype.getPrivate = function getPrivate(enc) { - if (enc === 'hex') - return this.priv.toString(16, 2); - else - return this.priv; -}; - -KeyPair.prototype._importPrivate = function _importPrivate(key, enc) { - this.priv = new BN(key, enc || 16); - - // Ensure that the priv won't be bigger than n, otherwise we may fail - // in fixed multiplication method - this.priv = this.priv.umod(this.ec.curve.n); -}; - -KeyPair.prototype._importPublic = function _importPublic(key, enc) { - if (key.x || key.y) { - // Montgomery points only have an `x` coordinate. - // Weierstrass/Edwards points on the other hand have both `x` and - // `y` coordinates. - if (this.ec.curve.type === 'mont') { - assert(key.x, 'Need x coordinate'); - } else if (this.ec.curve.type === 'short' || - this.ec.curve.type === 'edwards') { - assert(key.x && key.y, 'Need both x and y coordinate'); - } - this.pub = this.ec.curve.point(key.x, key.y); - return; - } - this.pub = this.ec.curve.decodePoint(key, enc); -}; - -// ECDH -KeyPair.prototype.derive = function derive(pub) { - if(!pub.validate()) { - assert(pub.validate(), 'public point not validated'); - } - return pub.mul(this.priv).getX(); -}; - -// ECDSA -KeyPair.prototype.sign = function sign(msg, enc, options) { - return this.ec.sign(msg, this, enc, options); -}; - -KeyPair.prototype.verify = function verify(msg, signature) { - return this.ec.verify(msg, signature, this); -}; - -KeyPair.prototype.inspect = function inspect() { - return ''; -}; - -},{"../utils":199,"bn.js":200}],194:[function(require,module,exports){ -'use strict'; - -var BN = require('bn.js'); - -var utils = require('../utils'); -var assert = utils.assert; - -function Signature(options, enc) { - if (options instanceof Signature) - return options; - - if (this._importDER(options, enc)) - return; - - assert(options.r && options.s, 'Signature without r or s'); - this.r = new BN(options.r, 16); - this.s = new BN(options.s, 16); - if (options.recoveryParam === undefined) - this.recoveryParam = null; - else - this.recoveryParam = options.recoveryParam; -} -module.exports = Signature; - -function Position() { - this.place = 0; -} - -function getLength(buf, p) { - var initial = buf[p.place++]; - if (!(initial & 0x80)) { - return initial; - } - var octetLen = initial & 0xf; - - // Indefinite length or overflow - if (octetLen === 0 || octetLen > 4) { - return false; - } - - var val = 0; - for (var i = 0, off = p.place; i < octetLen; i++, off++) { - val <<= 8; - val |= buf[off]; - val >>>= 0; - } - - // Leading zeroes - if (val <= 0x7f) { - return false; - } - - p.place = off; - return val; -} - -function rmPadding(buf) { - var i = 0; - var len = buf.length - 1; - while (!buf[i] && !(buf[i + 1] & 0x80) && i < len) { - i++; - } - if (i === 0) { - return buf; - } - return buf.slice(i); -} - -Signature.prototype._importDER = function _importDER(data, enc) { - data = utils.toArray(data, enc); - var p = new Position(); - if (data[p.place++] !== 0x30) { - return false; - } - var len = getLength(data, p); - if (len === false) { - return false; - } - if ((len + p.place) !== data.length) { - return false; - } - if (data[p.place++] !== 0x02) { - return false; - } - var rlen = getLength(data, p); - if (rlen === false) { - return false; - } - var r = data.slice(p.place, rlen + p.place); - p.place += rlen; - if (data[p.place++] !== 0x02) { - return false; - } - var slen = getLength(data, p); - if (slen === false) { - return false; - } - if (data.length !== slen + p.place) { - return false; - } - var s = data.slice(p.place, slen + p.place); - if (r[0] === 0) { - if (r[1] & 0x80) { - r = r.slice(1); - } else { - // Leading zeroes - return false; - } - } - if (s[0] === 0) { - if (s[1] & 0x80) { - s = s.slice(1); - } else { - // Leading zeroes - return false; - } - } - - this.r = new BN(r); - this.s = new BN(s); - this.recoveryParam = null; - - return true; -}; - -function constructLength(arr, len) { - if (len < 0x80) { - arr.push(len); - return; - } - var octets = 1 + (Math.log(len) / Math.LN2 >>> 3); - arr.push(octets | 0x80); - while (--octets) { - arr.push((len >>> (octets << 3)) & 0xff); - } - arr.push(len); -} - -Signature.prototype.toDER = function toDER(enc) { - var r = this.r.toArray(); - var s = this.s.toArray(); - - // Pad values - if (r[0] & 0x80) - r = [ 0 ].concat(r); - // Pad values - if (s[0] & 0x80) - s = [ 0 ].concat(s); - - r = rmPadding(r); - s = rmPadding(s); - - while (!s[0] && !(s[1] & 0x80)) { - s = s.slice(1); - } - var arr = [ 0x02 ]; - constructLength(arr, r.length); - arr = arr.concat(r); - arr.push(0x02); - constructLength(arr, s.length); - var backHalf = arr.concat(s); - var res = [ 0x30 ]; - constructLength(res, backHalf.length); - res = res.concat(backHalf); - return utils.encode(res, enc); -}; - -},{"../utils":199,"bn.js":200}],195:[function(require,module,exports){ -'use strict'; - -var hash = require('hash.js'); -var curves = require('../curves'); -var utils = require('../utils'); -var assert = utils.assert; -var parseBytes = utils.parseBytes; -var KeyPair = require('./key'); -var Signature = require('./signature'); - -function EDDSA(curve) { - assert(curve === 'ed25519', 'only tested with ed25519 so far'); - - if (!(this instanceof EDDSA)) - return new EDDSA(curve); - - curve = curves[curve].curve; - this.curve = curve; - this.g = curve.g; - this.g.precompute(curve.n.bitLength() + 1); - - this.pointClass = curve.point().constructor; - this.encodingLength = Math.ceil(curve.n.bitLength() / 8); - this.hash = hash.sha512; -} - -module.exports = EDDSA; - -/** -* @param {Array|String} message - message bytes -* @param {Array|String|KeyPair} secret - secret bytes or a keypair -* @returns {Signature} - signature -*/ -EDDSA.prototype.sign = function sign(message, secret) { - message = parseBytes(message); - var key = this.keyFromSecret(secret); - var r = this.hashInt(key.messagePrefix(), message); - var R = this.g.mul(r); - var Rencoded = this.encodePoint(R); - var s_ = this.hashInt(Rencoded, key.pubBytes(), message) - .mul(key.priv()); - var S = r.add(s_).umod(this.curve.n); - return this.makeSignature({ R: R, S: S, Rencoded: Rencoded }); -}; - -/** -* @param {Array} message - message bytes -* @param {Array|String|Signature} sig - sig bytes -* @param {Array|String|Point|KeyPair} pub - public key -* @returns {Boolean} - true if public key matches sig of message -*/ -EDDSA.prototype.verify = function verify(message, sig, pub) { - message = parseBytes(message); - sig = this.makeSignature(sig); - var key = this.keyFromPublic(pub); - var h = this.hashInt(sig.Rencoded(), key.pubBytes(), message); - var SG = this.g.mul(sig.S()); - var RplusAh = sig.R().add(key.pub().mul(h)); - return RplusAh.eq(SG); -}; - -EDDSA.prototype.hashInt = function hashInt() { - var hash = this.hash(); - for (var i = 0; i < arguments.length; i++) - hash.update(arguments[i]); - return utils.intFromLE(hash.digest()).umod(this.curve.n); -}; - -EDDSA.prototype.keyFromPublic = function keyFromPublic(pub) { - return KeyPair.fromPublic(this, pub); -}; - -EDDSA.prototype.keyFromSecret = function keyFromSecret(secret) { - return KeyPair.fromSecret(this, secret); -}; - -EDDSA.prototype.makeSignature = function makeSignature(sig) { - if (sig instanceof Signature) - return sig; - return new Signature(this, sig); -}; - -/** -* * https://tools.ietf.org/html/draft-josefsson-eddsa-ed25519-03#section-5.2 -* -* EDDSA defines methods for encoding and decoding points and integers. These are -* helper convenience methods, that pass along to utility functions implied -* parameters. -* -*/ -EDDSA.prototype.encodePoint = function encodePoint(point) { - var enc = point.getY().toArray('le', this.encodingLength); - enc[this.encodingLength - 1] |= point.getX().isOdd() ? 0x80 : 0; - return enc; -}; - -EDDSA.prototype.decodePoint = function decodePoint(bytes) { - bytes = utils.parseBytes(bytes); - - var lastIx = bytes.length - 1; - var normed = bytes.slice(0, lastIx).concat(bytes[lastIx] & ~0x80); - var xIsOdd = (bytes[lastIx] & 0x80) !== 0; - - var y = utils.intFromLE(normed); - return this.curve.pointFromY(y, xIsOdd); -}; - -EDDSA.prototype.encodeInt = function encodeInt(num) { - return num.toArray('le', this.encodingLength); -}; - -EDDSA.prototype.decodeInt = function decodeInt(bytes) { - return utils.intFromLE(bytes); -}; - -EDDSA.prototype.isPoint = function isPoint(val) { - return val instanceof this.pointClass; -}; - -},{"../curves":191,"../utils":199,"./key":196,"./signature":197,"hash.js":241}],196:[function(require,module,exports){ -'use strict'; - -var utils = require('../utils'); -var assert = utils.assert; -var parseBytes = utils.parseBytes; -var cachedProperty = utils.cachedProperty; - -/** -* @param {EDDSA} eddsa - instance -* @param {Object} params - public/private key parameters -* -* @param {Array} [params.secret] - secret seed bytes -* @param {Point} [params.pub] - public key point (aka `A` in eddsa terms) -* @param {Array} [params.pub] - public key point encoded as bytes -* -*/ -function KeyPair(eddsa, params) { - this.eddsa = eddsa; - this._secret = parseBytes(params.secret); - if (eddsa.isPoint(params.pub)) - this._pub = params.pub; - else - this._pubBytes = parseBytes(params.pub); -} - -KeyPair.fromPublic = function fromPublic(eddsa, pub) { - if (pub instanceof KeyPair) - return pub; - return new KeyPair(eddsa, { pub: pub }); -}; - -KeyPair.fromSecret = function fromSecret(eddsa, secret) { - if (secret instanceof KeyPair) - return secret; - return new KeyPair(eddsa, { secret: secret }); -}; - -KeyPair.prototype.secret = function secret() { - return this._secret; -}; - -cachedProperty(KeyPair, 'pubBytes', function pubBytes() { - return this.eddsa.encodePoint(this.pub()); -}); - -cachedProperty(KeyPair, 'pub', function pub() { - if (this._pubBytes) - return this.eddsa.decodePoint(this._pubBytes); - return this.eddsa.g.mul(this.priv()); -}); - -cachedProperty(KeyPair, 'privBytes', function privBytes() { - var eddsa = this.eddsa; - var hash = this.hash(); - var lastIx = eddsa.encodingLength - 1; - - var a = hash.slice(0, eddsa.encodingLength); - a[0] &= 248; - a[lastIx] &= 127; - a[lastIx] |= 64; - - return a; -}); - -cachedProperty(KeyPair, 'priv', function priv() { - return this.eddsa.decodeInt(this.privBytes()); -}); - -cachedProperty(KeyPair, 'hash', function hash() { - return this.eddsa.hash().update(this.secret()).digest(); -}); - -cachedProperty(KeyPair, 'messagePrefix', function messagePrefix() { - return this.hash().slice(this.eddsa.encodingLength); -}); - -KeyPair.prototype.sign = function sign(message) { - assert(this._secret, 'KeyPair can only verify'); - return this.eddsa.sign(message, this); -}; - -KeyPair.prototype.verify = function verify(message, sig) { - return this.eddsa.verify(message, sig, this); -}; - -KeyPair.prototype.getSecret = function getSecret(enc) { - assert(this._secret, 'KeyPair is public only'); - return utils.encode(this.secret(), enc); -}; - -KeyPair.prototype.getPublic = function getPublic(enc) { - return utils.encode(this.pubBytes(), enc); -}; - -module.exports = KeyPair; - -},{"../utils":199}],197:[function(require,module,exports){ -'use strict'; - -var BN = require('bn.js'); -var utils = require('../utils'); -var assert = utils.assert; -var cachedProperty = utils.cachedProperty; -var parseBytes = utils.parseBytes; - -/** -* @param {EDDSA} eddsa - eddsa instance -* @param {Array|Object} sig - -* @param {Array|Point} [sig.R] - R point as Point or bytes -* @param {Array|bn} [sig.S] - S scalar as bn or bytes -* @param {Array} [sig.Rencoded] - R point encoded -* @param {Array} [sig.Sencoded] - S scalar encoded -*/ -function Signature(eddsa, sig) { - this.eddsa = eddsa; - - if (typeof sig !== 'object') - sig = parseBytes(sig); - - if (Array.isArray(sig)) { - sig = { - R: sig.slice(0, eddsa.encodingLength), - S: sig.slice(eddsa.encodingLength), - }; - } - - assert(sig.R && sig.S, 'Signature without R or S'); - - if (eddsa.isPoint(sig.R)) - this._R = sig.R; - if (sig.S instanceof BN) - this._S = sig.S; - - this._Rencoded = Array.isArray(sig.R) ? sig.R : sig.Rencoded; - this._Sencoded = Array.isArray(sig.S) ? sig.S : sig.Sencoded; -} - -cachedProperty(Signature, 'S', function S() { - return this.eddsa.decodeInt(this.Sencoded()); -}); - -cachedProperty(Signature, 'R', function R() { - return this.eddsa.decodePoint(this.Rencoded()); -}); - -cachedProperty(Signature, 'Rencoded', function Rencoded() { - return this.eddsa.encodePoint(this.R()); -}); - -cachedProperty(Signature, 'Sencoded', function Sencoded() { - return this.eddsa.encodeInt(this.S()); -}); - -Signature.prototype.toBytes = function toBytes() { - return this.Rencoded().concat(this.Sencoded()); -}; - -Signature.prototype.toHex = function toHex() { - return utils.encode(this.toBytes(), 'hex').toUpperCase(); -}; - -module.exports = Signature; - -},{"../utils":199,"bn.js":200}],198:[function(require,module,exports){ +},{"../utils":161,"bn.js":86}],160:[function(require,module,exports){ module.exports = { doubles: { step: 4, @@ -38988,7 +34654,7 @@ module.exports = { }, }; -},{}],199:[function(require,module,exports){ +},{}],161:[function(require,module,exports){ 'use strict'; var utils = exports; @@ -39005,12 +34671,15 @@ utils.encode = minUtils.encode; // Represent num in a w-NAF form function getNAF(num, w, bits) { var naf = new Array(Math.max(num.bitLength(), bits) + 1); - naf.fill(0); + var i; + for (i = 0; i < naf.length; i += 1) { + naf[i] = 0; + } var ws = 1 << (w + 1); var k = num.clone(); - for (var i = 0; i < naf.length; i++) { + for (i = 0; i < naf.length; i++) { var z; var mod = k.andln(ws - 1); if (k.isOdd()) { @@ -39109,12 +34778,10 @@ function intFromLE(bytes) { utils.intFromLE = intFromLE; -},{"bn.js":200,"minimalistic-assert":301,"minimalistic-crypto-utils":302}],200:[function(require,module,exports){ -arguments[4][47][0].apply(exports,arguments) -},{"buffer":93,"dup":47}],201:[function(require,module,exports){ +},{"bn.js":86,"minimalistic-assert":259,"minimalistic-crypto-utils":260}],162:[function(require,module,exports){ module.exports={ "name": "elliptic", - "version": "6.5.4", + "version": "6.5.7", "description": "EC cryptography", "main": "lib/elliptic.js", "files": [ @@ -39169,7 +34836,7 @@ module.exports={ } } -},{}],202:[function(require,module,exports){ +},{}],163:[function(require,module,exports){ 'use strict' const AbstractLevelDOWN = require('abstract-leveldown').AbstractLevelDOWN @@ -39378,7 +35045,7 @@ Batch.prototype._write = function (opts, cb) { this.batch.write(opts, cb) } -},{"abstract-leveldown":30,"inherits":256,"level-codec":263,"level-errors":265}],203:[function(require,module,exports){ +},{"abstract-leveldown":30,"inherits":200,"level-codec":206,"level-errors":208}],164:[function(require,module,exports){ 'use strict'; var GetIntrinsic = require('get-intrinsic'); @@ -39396,49 +35063,49 @@ if ($defineProperty) { module.exports = $defineProperty; -},{"get-intrinsic":217}],204:[function(require,module,exports){ +},{"get-intrinsic":178}],165:[function(require,module,exports){ 'use strict'; /** @type {import('./eval')} */ module.exports = EvalError; -},{}],205:[function(require,module,exports){ +},{}],166:[function(require,module,exports){ 'use strict'; /** @type {import('.')} */ module.exports = Error; -},{}],206:[function(require,module,exports){ +},{}],167:[function(require,module,exports){ 'use strict'; /** @type {import('./range')} */ module.exports = RangeError; -},{}],207:[function(require,module,exports){ +},{}],168:[function(require,module,exports){ 'use strict'; /** @type {import('./ref')} */ module.exports = ReferenceError; -},{}],208:[function(require,module,exports){ +},{}],169:[function(require,module,exports){ 'use strict'; /** @type {import('./syntax')} */ module.exports = SyntaxError; -},{}],209:[function(require,module,exports){ +},{}],170:[function(require,module,exports){ 'use strict'; /** @type {import('./type')} */ module.exports = TypeError; -},{}],210:[function(require,module,exports){ +},{}],171:[function(require,module,exports){ 'use strict'; /** @type {import('./uri')} */ module.exports = URIError; -},{}],211:[function(require,module,exports){ +},{}],172:[function(require,module,exports){ // Copyright Joyent, Inc. and other Node contributors. // // Permission is hereby granted, free of charge, to any person obtaining a @@ -39937,7 +35604,7 @@ function eventTargetAgnosticAddListener(emitter, name, listener, flags) { } } -},{}],212:[function(require,module,exports){ +},{}],173:[function(require,module,exports){ var Buffer = require('safe-buffer').Buffer var MD5 = require('md5.js') @@ -39984,7 +35651,7 @@ function EVP_BytesToKey (password, salt, keyBits, ivLen) { module.exports = EVP_BytesToKey -},{"md5.js":298,"safe-buffer":404}],213:[function(require,module,exports){ +},{"md5.js":241,"safe-buffer":390}],174:[function(require,module,exports){ (function (root, factory) { // Hack to make all exports of this module sha256 function object properties. var exports = {}; @@ -40413,7 +36080,7 @@ function pbkdf2(password, salt, iterations, dkLen) { exports.pbkdf2 = pbkdf2; }); -},{}],214:[function(require,module,exports){ +},{}],175:[function(require,module,exports){ 'use strict'; var isCallable = require('is-callable'); @@ -40477,7 +36144,7 @@ var forEach = function forEach(list, iterator, thisArg) { module.exports = forEach; -},{"is-callable":260}],215:[function(require,module,exports){ +},{"is-callable":203}],176:[function(require,module,exports){ 'use strict'; /* eslint no-invalid-this: 1 */ @@ -40563,14 +36230,14 @@ module.exports = function bind(that) { return bound; }; -},{}],216:[function(require,module,exports){ +},{}],177:[function(require,module,exports){ 'use strict'; var implementation = require('./implementation'); module.exports = Function.prototype.bind || implementation; -},{"./implementation":215}],217:[function(require,module,exports){ +},{"./implementation":176}],178:[function(require,module,exports){ 'use strict'; var undefined; @@ -40931,7 +36598,7 @@ module.exports = function GetIntrinsic(name, allowMissing) { return value; }; -},{"es-errors":205,"es-errors/eval":204,"es-errors/range":206,"es-errors/ref":207,"es-errors/syntax":208,"es-errors/type":209,"es-errors/uri":210,"function-bind":216,"has-proto":220,"has-symbols":221,"hasown":253}],218:[function(require,module,exports){ +},{"es-errors":166,"es-errors/eval":165,"es-errors/range":167,"es-errors/ref":168,"es-errors/syntax":169,"es-errors/type":170,"es-errors/uri":171,"function-bind":177,"has-proto":181,"has-symbols":182,"hasown":197}],179:[function(require,module,exports){ 'use strict'; var GetIntrinsic = require('get-intrinsic'); @@ -40949,7 +36616,7 @@ if ($gOPD) { module.exports = $gOPD; -},{"get-intrinsic":217}],219:[function(require,module,exports){ +},{"get-intrinsic":178}],180:[function(require,module,exports){ 'use strict'; var $defineProperty = require('es-define-property'); @@ -40973,7 +36640,7 @@ hasPropertyDescriptors.hasArrayLengthDefineBug = function hasArrayLengthDefineBu module.exports = hasPropertyDescriptors; -},{"es-define-property":203}],220:[function(require,module,exports){ +},{"es-define-property":164}],181:[function(require,module,exports){ 'use strict'; var test = { @@ -40990,7 +36657,7 @@ module.exports = function hasProto() { && !(test instanceof $Object); }; -},{}],221:[function(require,module,exports){ +},{}],182:[function(require,module,exports){ 'use strict'; var origSymbol = typeof Symbol !== 'undefined' && Symbol; @@ -41005,7 +36672,7 @@ module.exports = function hasNativeSymbols() { return hasSymbolSham(); }; -},{"./shams":222}],222:[function(require,module,exports){ +},{"./shams":183}],183:[function(require,module,exports){ 'use strict'; /* eslint complexity: [2, 18], max-statements: [2, 33] */ @@ -41049,7 +36716,7 @@ module.exports = function hasSymbols() { return true; }; -},{}],223:[function(require,module,exports){ +},{}],184:[function(require,module,exports){ 'use strict'; var hasSymbols = require('has-symbols/shams'); @@ -41059,136 +36726,7 @@ module.exports = function hasToStringTagShams() { return hasSymbols() && !!Symbol.toStringTag; }; -},{"has-symbols/shams":222}],224:[function(require,module,exports){ -'use strict' -var Buffer = require('safe-buffer').Buffer -var Transform = require('readable-stream').Transform -var inherits = require('inherits') - -function throwIfNotStringOrBuffer (val, prefix) { - if (!Buffer.isBuffer(val) && typeof val !== 'string') { - throw new TypeError(prefix + ' must be a string or a buffer') - } -} - -function HashBase (blockSize) { - Transform.call(this) - - this._block = Buffer.allocUnsafe(blockSize) - this._blockSize = blockSize - this._blockOffset = 0 - this._length = [0, 0, 0, 0] - - this._finalized = false -} - -inherits(HashBase, Transform) - -HashBase.prototype._transform = function (chunk, encoding, callback) { - var error = null - try { - this.update(chunk, encoding) - } catch (err) { - error = err - } - - callback(error) -} - -HashBase.prototype._flush = function (callback) { - var error = null - try { - this.push(this.digest()) - } catch (err) { - error = err - } - - callback(error) -} - -HashBase.prototype.update = function (data, encoding) { - throwIfNotStringOrBuffer(data, 'Data') - if (this._finalized) throw new Error('Digest already called') - if (!Buffer.isBuffer(data)) data = Buffer.from(data, encoding) - - // consume data - var block = this._block - var offset = 0 - while (this._blockOffset + data.length - offset >= this._blockSize) { - for (var i = this._blockOffset; i < this._blockSize;) block[i++] = data[offset++] - this._update() - this._blockOffset = 0 - } - while (offset < data.length) block[this._blockOffset++] = data[offset++] - - // update length - for (var j = 0, carry = data.length * 8; carry > 0; ++j) { - this._length[j] += carry - carry = (this._length[j] / 0x0100000000) | 0 - if (carry > 0) this._length[j] -= 0x0100000000 * carry - } - - return this -} - -HashBase.prototype._update = function () { - throw new Error('_update is not implemented') -} - -HashBase.prototype.digest = function (encoding) { - if (this._finalized) throw new Error('Digest already called') - this._finalized = true - - var digest = this._digest() - if (encoding !== undefined) digest = digest.toString(encoding) - - // reset state - this._block.fill(0) - this._blockOffset = 0 - for (var i = 0; i < 4; ++i) this._length[i] = 0 - - return digest -} - -HashBase.prototype._digest = function () { - throw new Error('_digest is not implemented') -} - -module.exports = HashBase - -},{"inherits":256,"readable-stream":239,"safe-buffer":240}],225:[function(require,module,exports){ -arguments[4][121][0].apply(exports,arguments) -},{"dup":121}],226:[function(require,module,exports){ -arguments[4][122][0].apply(exports,arguments) -},{"./_stream_readable":228,"./_stream_writable":230,"_process":391,"dup":122,"inherits":256}],227:[function(require,module,exports){ -arguments[4][123][0].apply(exports,arguments) -},{"./_stream_transform":229,"dup":123,"inherits":256}],228:[function(require,module,exports){ -arguments[4][124][0].apply(exports,arguments) -},{"../errors":225,"./_stream_duplex":226,"./internal/streams/async_iterator":231,"./internal/streams/buffer_list":232,"./internal/streams/destroy":233,"./internal/streams/from":235,"./internal/streams/state":237,"./internal/streams/stream":238,"_process":391,"buffer":137,"dup":124,"events":211,"inherits":256,"string_decoder/":415,"util":93}],229:[function(require,module,exports){ -arguments[4][125][0].apply(exports,arguments) -},{"../errors":225,"./_stream_duplex":226,"dup":125,"inherits":256}],230:[function(require,module,exports){ -arguments[4][126][0].apply(exports,arguments) -},{"../errors":225,"./_stream_duplex":226,"./internal/streams/destroy":233,"./internal/streams/state":237,"./internal/streams/stream":238,"_process":391,"buffer":137,"dup":126,"inherits":256,"util-deprecate":416}],231:[function(require,module,exports){ -arguments[4][127][0].apply(exports,arguments) -},{"./end-of-stream":234,"_process":391,"dup":127}],232:[function(require,module,exports){ -arguments[4][128][0].apply(exports,arguments) -},{"buffer":137,"dup":128,"util":93}],233:[function(require,module,exports){ -arguments[4][129][0].apply(exports,arguments) -},{"_process":391,"dup":129}],234:[function(require,module,exports){ -arguments[4][130][0].apply(exports,arguments) -},{"../../../errors":225,"dup":130}],235:[function(require,module,exports){ -arguments[4][131][0].apply(exports,arguments) -},{"dup":131}],236:[function(require,module,exports){ -arguments[4][132][0].apply(exports,arguments) -},{"../../../errors":225,"./end-of-stream":234,"dup":132}],237:[function(require,module,exports){ -arguments[4][133][0].apply(exports,arguments) -},{"../../../errors":225,"dup":133}],238:[function(require,module,exports){ -arguments[4][134][0].apply(exports,arguments) -},{"dup":134,"events":211}],239:[function(require,module,exports){ -arguments[4][135][0].apply(exports,arguments) -},{"./lib/_stream_duplex.js":226,"./lib/_stream_passthrough.js":227,"./lib/_stream_readable.js":228,"./lib/_stream_transform.js":229,"./lib/_stream_writable.js":230,"./lib/internal/streams/end-of-stream.js":234,"./lib/internal/streams/pipeline.js":236,"dup":135}],240:[function(require,module,exports){ -arguments[4][136][0].apply(exports,arguments) -},{"buffer":137,"dup":136}],241:[function(require,module,exports){ +},{"has-symbols/shams":183}],185:[function(require,module,exports){ var hash = exports; hash.utils = require('./hash/utils'); @@ -41205,7 +36743,7 @@ hash.sha384 = hash.sha.sha384; hash.sha512 = hash.sha.sha512; hash.ripemd160 = hash.ripemd.ripemd160; -},{"./hash/common":242,"./hash/hmac":243,"./hash/ripemd":244,"./hash/sha":245,"./hash/utils":252}],242:[function(require,module,exports){ +},{"./hash/common":186,"./hash/hmac":187,"./hash/ripemd":188,"./hash/sha":189,"./hash/utils":196}],186:[function(require,module,exports){ 'use strict'; var utils = require('./utils'); @@ -41299,7 +36837,7 @@ BlockHash.prototype._pad = function pad() { return res; }; -},{"./utils":252,"minimalistic-assert":301}],243:[function(require,module,exports){ +},{"./utils":196,"minimalistic-assert":259}],187:[function(require,module,exports){ 'use strict'; var utils = require('./utils'); @@ -41348,7 +36886,7 @@ Hmac.prototype.digest = function digest(enc) { return this.outer.digest(enc); }; -},{"./utils":252,"minimalistic-assert":301}],244:[function(require,module,exports){ +},{"./utils":196,"minimalistic-assert":259}],188:[function(require,module,exports){ 'use strict'; var utils = require('./utils'); @@ -41496,7 +37034,7 @@ var sh = [ 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11 ]; -},{"./common":242,"./utils":252}],245:[function(require,module,exports){ +},{"./common":186,"./utils":196}],189:[function(require,module,exports){ 'use strict'; exports.sha1 = require('./sha/1'); @@ -41505,7 +37043,7 @@ exports.sha256 = require('./sha/256'); exports.sha384 = require('./sha/384'); exports.sha512 = require('./sha/512'); -},{"./sha/1":246,"./sha/224":247,"./sha/256":248,"./sha/384":249,"./sha/512":250}],246:[function(require,module,exports){ +},{"./sha/1":190,"./sha/224":191,"./sha/256":192,"./sha/384":193,"./sha/512":194}],190:[function(require,module,exports){ 'use strict'; var utils = require('../utils'); @@ -41581,7 +37119,7 @@ SHA1.prototype._digest = function digest(enc) { return utils.split32(this.h, 'big'); }; -},{"../common":242,"../utils":252,"./common":251}],247:[function(require,module,exports){ +},{"../common":186,"../utils":196,"./common":195}],191:[function(require,module,exports){ 'use strict'; var utils = require('../utils'); @@ -41613,7 +37151,7 @@ SHA224.prototype._digest = function digest(enc) { }; -},{"../utils":252,"./256":248}],248:[function(require,module,exports){ +},{"../utils":196,"./256":192}],192:[function(require,module,exports){ 'use strict'; var utils = require('../utils'); @@ -41720,7 +37258,7 @@ SHA256.prototype._digest = function digest(enc) { return utils.split32(this.h, 'big'); }; -},{"../common":242,"../utils":252,"./common":251,"minimalistic-assert":301}],249:[function(require,module,exports){ +},{"../common":186,"../utils":196,"./common":195,"minimalistic-assert":259}],193:[function(require,module,exports){ 'use strict'; var utils = require('../utils'); @@ -41757,7 +37295,7 @@ SHA384.prototype._digest = function digest(enc) { return utils.split32(this.h.slice(0, 12), 'big'); }; -},{"../utils":252,"./512":250}],250:[function(require,module,exports){ +},{"../utils":196,"./512":194}],194:[function(require,module,exports){ 'use strict'; var utils = require('../utils'); @@ -42089,7 +37627,7 @@ function g1_512_lo(xh, xl) { return r; } -},{"../common":242,"../utils":252,"minimalistic-assert":301}],251:[function(require,module,exports){ +},{"../common":186,"../utils":196,"minimalistic-assert":259}],195:[function(require,module,exports){ 'use strict'; var utils = require('../utils'); @@ -42140,7 +37678,7 @@ function g1_256(x) { } exports.g1_256 = g1_256; -},{"../utils":252}],252:[function(require,module,exports){ +},{"../utils":196}],196:[function(require,module,exports){ 'use strict'; var assert = require('minimalistic-assert'); @@ -42420,7 +37958,7 @@ function shr64_lo(ah, al, num) { } exports.shr64_lo = shr64_lo; -},{"inherits":256,"minimalistic-assert":301}],253:[function(require,module,exports){ +},{"inherits":200,"minimalistic-assert":259}],197:[function(require,module,exports){ 'use strict'; var call = Function.prototype.call; @@ -42430,7 +37968,7 @@ var bind = require('function-bind'); /** @type {import('.')} */ module.exports = bind.call(call, $hasOwn); -},{"function-bind":216}],254:[function(require,module,exports){ +},{"function-bind":177}],198:[function(require,module,exports){ 'use strict'; var hash = require('hash.js'); @@ -42545,7 +38083,7 @@ HmacDRBG.prototype.generate = function generate(len, enc, add, addEnc) { return utils.encode(res, enc); }; -},{"hash.js":241,"minimalistic-assert":301,"minimalistic-crypto-utils":302}],255:[function(require,module,exports){ +},{"hash.js":185,"minimalistic-assert":259,"minimalistic-crypto-utils":260}],199:[function(require,module,exports){ /*! ieee754. BSD-3-Clause License. Feross Aboukhadijeh */ exports.read = function (buffer, offset, isLE, mLen, nBytes) { var e, m @@ -42632,7 +38170,7 @@ exports.write = function (buffer, value, offset, isLE, mLen, nBytes) { buffer[offset + i - d] |= s * 128 } -},{}],256:[function(require,module,exports){ +},{}],200:[function(require,module,exports){ if (typeof Object.create === 'function') { // implementation from standard node.js 'util' module module.exports = function inherits(ctor, superCtor) { @@ -42661,30 +38199,7 @@ if (typeof Object.create === 'function') { } } -},{}],257:[function(require,module,exports){ -/*! - * Determine if an object is a Buffer - * - * @author Feross Aboukhadijeh - * @license MIT - */ - -// The _isBuffer check is for Safari 5-7 support, because it's missing -// Object.prototype.constructor. Remove this eventually -module.exports = function (obj) { - return obj != null && (isBuffer(obj) || isSlowBuffer(obj) || !!obj._isBuffer) -} - -function isBuffer (obj) { - return !!obj.constructor && typeof obj.constructor.isBuffer === 'function' && obj.constructor.isBuffer(obj) -} - -// For Node v0.10 support. Remove this eventually. -function isSlowBuffer (obj) { - return typeof obj.readFloatLE === 'function' && typeof obj.slice === 'function' && isBuffer(obj.slice(0, 0)) -} - -},{}],258:[function(require,module,exports){ +},{}],201:[function(require,module,exports){ 'use strict'; var hasToStringTag = require('has-tostringtag/shams')(); @@ -42719,7 +38234,7 @@ isStandardArguments.isLegacyArguments = isLegacyArguments; // for tests module.exports = supportsStandardArguments ? isStandardArguments : isLegacyArguments; -},{"call-bind/callBound":157,"has-tostringtag/shams":223}],259:[function(require,module,exports){ +},{"call-bind/callBound":120,"has-tostringtag/shams":184}],202:[function(require,module,exports){ /*! * Determine if an object is a Buffer * @@ -42727,12 +38242,22 @@ module.exports = supportsStandardArguments ? isStandardArguments : isLegacyArgum * @license MIT */ -module.exports = function isBuffer (obj) { - return obj != null && obj.constructor != null && - typeof obj.constructor.isBuffer === 'function' && obj.constructor.isBuffer(obj) +// The _isBuffer check is for Safari 5-7 support, because it's missing +// Object.prototype.constructor. Remove this eventually +module.exports = function (obj) { + return obj != null && (isBuffer(obj) || isSlowBuffer(obj) || !!obj._isBuffer) } -},{}],260:[function(require,module,exports){ +function isBuffer (obj) { + return !!obj.constructor && typeof obj.constructor.isBuffer === 'function' && obj.constructor.isBuffer(obj) +} + +// For Node v0.10 support. Remove this eventually. +function isSlowBuffer (obj) { + return typeof obj.readFloatLE === 'function' && typeof obj.slice === 'function' && isBuffer(obj.slice(0, 0)) +} + +},{}],203:[function(require,module,exports){ 'use strict'; var fnToStr = Function.prototype.toString; @@ -42835,7 +38360,7 @@ module.exports = reflectApply return tryFunctionObject(value); }; -},{}],261:[function(require,module,exports){ +},{}],204:[function(require,module,exports){ 'use strict'; var toStr = Object.prototype.toString; @@ -42875,7 +38400,7 @@ module.exports = function isGeneratorFunction(fn) { return getProto(fn) === GeneratorFunction; }; -},{"has-tostringtag/shams":223}],262:[function(require,module,exports){ +},{"has-tostringtag/shams":184}],205:[function(require,module,exports){ 'use strict'; var whichTypedArray = require('which-typed-array'); @@ -42885,7 +38410,7 @@ module.exports = function isTypedArray(value) { return !!whichTypedArray(value); }; -},{"which-typed-array":417}],263:[function(require,module,exports){ +},{"which-typed-array":427}],206:[function(require,module,exports){ 'use strict' const encodings = require('./lib/encodings') @@ -42996,7 +38521,7 @@ Codec.prototype.valueAsBuffer = function (opts) { return this._valueEncoding(opts).buffer } -},{"./lib/encodings":264}],264:[function(require,module,exports){ +},{"./lib/encodings":207}],207:[function(require,module,exports){ 'use strict' const { Buffer } = require('buffer') @@ -43066,7 +38591,7 @@ function isBinary (data) { return data === undefined || data === null || Buffer.isBuffer(data) } -},{"buffer":137}],265:[function(require,module,exports){ +},{"buffer":118}],208:[function(require,module,exports){ 'use strict' function createError (type, Proto) { @@ -43117,7 +38642,7 @@ module.exports = { module.exports.NotFoundError.prototype.notFound = true module.exports.NotFoundError.prototype.status = 404 -},{}],266:[function(require,module,exports){ +},{}],209:[function(require,module,exports){ 'use strict' const inherits = require('inherits') @@ -43162,9 +38687,136 @@ ReadStream.prototype._destroy = function (err, callback) { }) } -},{"inherits":256,"readable-stream":281}],267:[function(require,module,exports){ -arguments[4][121][0].apply(exports,arguments) -},{"dup":121}],268:[function(require,module,exports){ +},{"inherits":200,"readable-stream":224}],210:[function(require,module,exports){ +'use strict'; + +function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; subClass.__proto__ = superClass; } + +var codes = {}; + +function createErrorType(code, message, Base) { + if (!Base) { + Base = Error; + } + + function getMessage(arg1, arg2, arg3) { + if (typeof message === 'string') { + return message; + } else { + return message(arg1, arg2, arg3); + } + } + + var NodeError = + /*#__PURE__*/ + function (_Base) { + _inheritsLoose(NodeError, _Base); + + function NodeError(arg1, arg2, arg3) { + return _Base.call(this, getMessage(arg1, arg2, arg3)) || this; + } + + return NodeError; + }(Base); + + NodeError.prototype.name = Base.name; + NodeError.prototype.code = code; + codes[code] = NodeError; +} // https://github.com/nodejs/node/blob/v10.8.0/lib/internal/errors.js + + +function oneOf(expected, thing) { + if (Array.isArray(expected)) { + var len = expected.length; + expected = expected.map(function (i) { + return String(i); + }); + + if (len > 2) { + return "one of ".concat(thing, " ").concat(expected.slice(0, len - 1).join(', '), ", or ") + expected[len - 1]; + } else if (len === 2) { + return "one of ".concat(thing, " ").concat(expected[0], " or ").concat(expected[1]); + } else { + return "of ".concat(thing, " ").concat(expected[0]); + } + } else { + return "of ".concat(thing, " ").concat(String(expected)); + } +} // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/startsWith + + +function startsWith(str, search, pos) { + return str.substr(!pos || pos < 0 ? 0 : +pos, search.length) === search; +} // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/endsWith + + +function endsWith(str, search, this_len) { + if (this_len === undefined || this_len > str.length) { + this_len = str.length; + } + + return str.substring(this_len - search.length, this_len) === search; +} // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/includes + + +function includes(str, search, start) { + if (typeof start !== 'number') { + start = 0; + } + + if (start + search.length > str.length) { + return false; + } else { + return str.indexOf(search, start) !== -1; + } +} + +createErrorType('ERR_INVALID_OPT_VALUE', function (name, value) { + return 'The value "' + value + '" is invalid for option "' + name + '"'; +}, TypeError); +createErrorType('ERR_INVALID_ARG_TYPE', function (name, expected, actual) { + // determiner: 'must be' or 'must not be' + var determiner; + + if (typeof expected === 'string' && startsWith(expected, 'not ')) { + determiner = 'must not be'; + expected = expected.replace(/^not /, ''); + } else { + determiner = 'must be'; + } + + var msg; + + if (endsWith(name, ' argument')) { + // For cases like 'first argument' + msg = "The ".concat(name, " ").concat(determiner, " ").concat(oneOf(expected, 'type')); + } else { + var type = includes(name, '.') ? 'property' : 'argument'; + msg = "The \"".concat(name, "\" ").concat(type, " ").concat(determiner, " ").concat(oneOf(expected, 'type')); + } + + msg += ". Received type ".concat(typeof actual); + return msg; +}, TypeError); +createErrorType('ERR_STREAM_PUSH_AFTER_EOF', 'stream.push() after EOF'); +createErrorType('ERR_METHOD_NOT_IMPLEMENTED', function (name) { + return 'The ' + name + ' method is not implemented'; +}); +createErrorType('ERR_STREAM_PREMATURE_CLOSE', 'Premature close'); +createErrorType('ERR_STREAM_DESTROYED', function (name) { + return 'Cannot call ' + name + ' after a stream was destroyed'; +}); +createErrorType('ERR_MULTIPLE_CALLBACK', 'Callback called multiple times'); +createErrorType('ERR_STREAM_CANNOT_PIPE', 'Cannot pipe, not readable'); +createErrorType('ERR_STREAM_WRITE_AFTER_END', 'write after end'); +createErrorType('ERR_STREAM_NULL_VALUES', 'May not write null values to stream', TypeError); +createErrorType('ERR_UNKNOWN_ENCODING', function (arg) { + return 'Unknown encoding: ' + arg; +}, TypeError); +createErrorType('ERR_STREAM_UNSHIFT_AFTER_END_EVENT', 'stream.unshift() after end event'); +module.exports.codes = codes; + +},{}],211:[function(require,module,exports){ (function (process){(function (){ // Copyright Joyent, Inc. and other Node contributors. // @@ -43293,7 +38945,7 @@ Object.defineProperty(Duplex.prototype, 'destroyed', { } }); }).call(this)}).call(this,require('_process')) -},{"./_stream_readable":270,"./_stream_writable":272,"_process":391,"inherits":256}],269:[function(require,module,exports){ +},{"./_stream_readable":213,"./_stream_writable":215,"_process":350,"inherits":200}],212:[function(require,module,exports){ // Copyright Joyent, Inc. and other Node contributors. // // Permission is hereby granted, free of charge, to any person obtaining a @@ -43331,7 +38983,7 @@ function PassThrough(options) { PassThrough.prototype._transform = function (chunk, encoding, cb) { cb(null, chunk); }; -},{"./_stream_transform":271,"inherits":256}],270:[function(require,module,exports){ +},{"./_stream_transform":214,"inherits":200}],213:[function(require,module,exports){ (function (process,global){(function (){ // Copyright Joyent, Inc. and other Node contributors. // @@ -44361,7 +40013,7 @@ function indexOf(xs, x) { return -1; } }).call(this)}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"../errors":267,"./_stream_duplex":268,"./internal/streams/async_iterator":273,"./internal/streams/buffer_list":274,"./internal/streams/destroy":275,"./internal/streams/from":277,"./internal/streams/state":279,"./internal/streams/stream":280,"_process":391,"buffer":137,"events":211,"inherits":256,"string_decoder/":415,"util":93}],271:[function(require,module,exports){ +},{"../errors":210,"./_stream_duplex":211,"./internal/streams/async_iterator":216,"./internal/streams/buffer_list":217,"./internal/streams/destroy":218,"./internal/streams/from":220,"./internal/streams/state":222,"./internal/streams/stream":223,"_process":350,"buffer":118,"events":172,"inherits":200,"string_decoder/":415,"util":88}],214:[function(require,module,exports){ // Copyright Joyent, Inc. and other Node contributors. // // Permission is hereby granted, free of charge, to any person obtaining a @@ -44552,7 +40204,7 @@ function done(stream, er, data) { if (stream._transformState.transforming) throw new ERR_TRANSFORM_ALREADY_TRANSFORMING(); return stream.push(null); } -},{"../errors":267,"./_stream_duplex":268,"inherits":256}],272:[function(require,module,exports){ +},{"../errors":210,"./_stream_duplex":211,"inherits":200}],215:[function(require,module,exports){ (function (process,global){(function (){ // Copyright Joyent, Inc. and other Node contributors. // @@ -45196,7 +40848,7 @@ Writable.prototype._destroy = function (err, cb) { cb(err); }; }).call(this)}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"../errors":267,"./_stream_duplex":268,"./internal/streams/destroy":275,"./internal/streams/state":279,"./internal/streams/stream":280,"_process":391,"buffer":137,"inherits":256,"util-deprecate":416}],273:[function(require,module,exports){ +},{"../errors":210,"./_stream_duplex":211,"./internal/streams/destroy":218,"./internal/streams/state":222,"./internal/streams/stream":223,"_process":350,"buffer":118,"inherits":200,"util-deprecate":417}],216:[function(require,module,exports){ (function (process){(function (){ 'use strict'; @@ -45379,7 +41031,7 @@ var createReadableStreamAsyncIterator = function createReadableStreamAsyncIterat }; module.exports = createReadableStreamAsyncIterator; }).call(this)}).call(this,require('_process')) -},{"./end-of-stream":276,"_process":391}],274:[function(require,module,exports){ +},{"./end-of-stream":219,"_process":350}],217:[function(require,module,exports){ 'use strict'; function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; } @@ -45563,7 +41215,7 @@ module.exports = /*#__PURE__*/function () { }]); return BufferList; }(); -},{"buffer":137,"util":93}],275:[function(require,module,exports){ +},{"buffer":118,"util":88}],218:[function(require,module,exports){ (function (process){(function (){ 'use strict'; @@ -45662,7 +41314,7 @@ module.exports = { errorOrDestroy: errorOrDestroy }; }).call(this)}).call(this,require('_process')) -},{"_process":391}],276:[function(require,module,exports){ +},{"_process":350}],219:[function(require,module,exports){ // Ported from https://github.com/mafintosh/end-of-stream with // permission from the author, Mathias Buus (@mafintosh). @@ -45749,9 +41401,12 @@ function eos(stream, opts, callback) { }; } module.exports = eos; -},{"../../../errors":267}],277:[function(require,module,exports){ -arguments[4][131][0].apply(exports,arguments) -},{"dup":131}],278:[function(require,module,exports){ +},{"../../../errors":210}],220:[function(require,module,exports){ +module.exports = function () { + throw new Error('Readable.from is not available in the browser') +}; + +},{}],221:[function(require,module,exports){ // Ported from https://github.com/mafintosh/pump with // permission from the author, Mathias Buus (@mafintosh). @@ -45838,7 +41493,7 @@ function pipeline() { return streams.reduce(pipe); } module.exports = pipeline; -},{"../../../errors":267,"./end-of-stream":276}],279:[function(require,module,exports){ +},{"../../../errors":210,"./end-of-stream":219}],222:[function(require,module,exports){ 'use strict'; var ERR_INVALID_OPT_VALUE = require('../../../errors').codes.ERR_INVALID_OPT_VALUE; @@ -45861,11 +41516,21 @@ function getHighWaterMark(state, options, duplexKey, isDuplex) { module.exports = { getHighWaterMark: getHighWaterMark }; -},{"../../../errors":267}],280:[function(require,module,exports){ -arguments[4][134][0].apply(exports,arguments) -},{"dup":134,"events":211}],281:[function(require,module,exports){ -arguments[4][135][0].apply(exports,arguments) -},{"./lib/_stream_duplex.js":268,"./lib/_stream_passthrough.js":269,"./lib/_stream_readable.js":270,"./lib/_stream_transform.js":271,"./lib/_stream_writable.js":272,"./lib/internal/streams/end-of-stream.js":276,"./lib/internal/streams/pipeline.js":278,"dup":135}],282:[function(require,module,exports){ +},{"../../../errors":210}],223:[function(require,module,exports){ +module.exports = require('events').EventEmitter; + +},{"events":172}],224:[function(require,module,exports){ +exports = module.exports = require('./lib/_stream_readable.js'); +exports.Stream = exports; +exports.Readable = exports; +exports.Writable = require('./lib/_stream_writable.js'); +exports.Duplex = require('./lib/_stream_duplex.js'); +exports.Transform = require('./lib/_stream_transform.js'); +exports.PassThrough = require('./lib/_stream_passthrough.js'); +exports.finished = require('./lib/internal/streams/end-of-stream.js'); +exports.pipeline = require('./lib/internal/streams/pipeline.js'); + +},{"./lib/_stream_duplex.js":211,"./lib/_stream_passthrough.js":212,"./lib/_stream_readable.js":213,"./lib/_stream_transform.js":214,"./lib/_stream_writable.js":215,"./lib/internal/streams/end-of-stream.js":219,"./lib/internal/streams/pipeline.js":221}],225:[function(require,module,exports){ /* global indexedDB */ 'use strict' @@ -46171,7 +41836,7 @@ Level.destroy = function (location, prefix, callback) { } } -},{"./iterator":283,"./util/clear":284,"./util/deserialize":285,"./util/key-range":286,"./util/serialize":287,"./util/support":288,"abstract-leveldown":30,"inherits":256,"run-parallel-limit":403}],283:[function(require,module,exports){ +},{"./iterator":226,"./util/clear":227,"./util/deserialize":228,"./util/key-range":229,"./util/serialize":230,"./util/support":231,"abstract-leveldown":30,"inherits":200,"run-parallel-limit":389}],226:[function(require,module,exports){ 'use strict' const inherits = require('inherits') @@ -46317,7 +41982,7 @@ Iterator.prototype._end = function (callback) { this.onComplete = callback } -},{"./util/deserialize":285,"./util/key-range":286,"abstract-leveldown":30,"inherits":256}],284:[function(require,module,exports){ +},{"./util/deserialize":228,"./util/key-range":229,"abstract-leveldown":30,"inherits":200}],227:[function(require,module,exports){ 'use strict' module.exports = function clear (db, location, keyRange, options, callback) { @@ -46353,7 +42018,7 @@ module.exports = function clear (db, location, keyRange, options, callback) { } } -},{}],285:[function(require,module,exports){ +},{}],228:[function(require,module,exports){ (function (global){(function (){ 'use strict' @@ -46401,7 +42066,7 @@ module.exports = function (data, asBuffer) { } }).call(this)}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"buffer":137}],286:[function(require,module,exports){ +},{"buffer":118}],229:[function(require,module,exports){ /* global IDBKeyRange */ 'use strict' @@ -46426,7 +42091,7 @@ module.exports = function createKeyRange (options) { } } -},{"ltgt":297}],287:[function(require,module,exports){ +},{"ltgt":240}],230:[function(require,module,exports){ (function (global){(function (){ 'use strict' @@ -46451,7 +42116,7 @@ module.exports = function (data, asBuffer) { } }).call(this)}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"buffer":137}],288:[function(require,module,exports){ +},{"buffer":118}],231:[function(require,module,exports){ 'use strict' const Buffer = require('buffer').Buffer @@ -46470,7 +42135,7 @@ exports.test = function (key) { // Detect binary key support (IndexedDB Second Edition) exports.bufferKeys = exports.test(Buffer.alloc(0)) -},{"buffer":137}],289:[function(require,module,exports){ +},{"buffer":118}],232:[function(require,module,exports){ 'use strict' const levelup = require('levelup') @@ -46510,7 +42175,7 @@ function packager (leveldown) { module.exports = packager -},{"encoding-down":202,"levelup":294}],290:[function(require,module,exports){ +},{"encoding-down":163,"levelup":237}],233:[function(require,module,exports){ 'use strict' module.exports = function supports (...manifests) { @@ -46556,10 +42221,10 @@ function maybeObject (value) { return !value ? false : Object.assign({}, value) } -},{}],291:[function(require,module,exports){ +},{}],234:[function(require,module,exports){ module.exports = require('level-packager')(require('level-js')) -},{"level-js":282,"level-packager":289}],292:[function(require,module,exports){ +},{"level-js":225,"level-packager":232}],235:[function(require,module,exports){ 'use strict' const WriteError = require('level-errors').WriteError @@ -46636,9 +42301,9 @@ Batch.prototype.write = function (options, callback) { module.exports = Batch -},{"./common":293,"catering":159,"level-errors":265}],293:[function(require,module,exports){ +},{"./common":236,"catering":122,"level-errors":208}],236:[function(require,module,exports){ arguments[4][31][0].apply(exports,arguments) -},{"dup":31}],294:[function(require,module,exports){ +},{"dup":31}],237:[function(require,module,exports){ 'use strict' const EventEmitter = require('events').EventEmitter @@ -46973,9 +42638,9 @@ function maybeError (db, callback) { LevelUP.errors = errors module.exports = LevelUP -},{"./batch":292,"./common":293,"./next-tick":295,"catering":159,"deferred-leveldown":171,"events":211,"level-errors":265,"level-iterator-stream":266,"level-supports":290,"util":155}],295:[function(require,module,exports){ +},{"./batch":235,"./common":236,"./next-tick":238,"catering":122,"deferred-leveldown":134,"events":172,"level-errors":208,"level-iterator-stream":209,"level-supports":233,"util":420}],238:[function(require,module,exports){ arguments[4][32][0].apply(exports,arguments) -},{"dup":32,"queue-microtask":399}],296:[function(require,module,exports){ +},{"dup":32,"queue-microtask":357}],239:[function(require,module,exports){ (function (global){(function (){ /** * @license @@ -64188,7 +59853,7 @@ arguments[4][32][0].apply(exports,arguments) }.call(this)); }).call(this)}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{}],297:[function(require,module,exports){ +},{}],240:[function(require,module,exports){ (function (Buffer){(function (){ exports.compare = function (a, b) { @@ -64356,8 +60021,8 @@ exports.filter = function (range, compare) { -}).call(this)}).call(this,{"isBuffer":require("../insert-module-globals/node_modules/is-buffer/index.js")}) -},{"../insert-module-globals/node_modules/is-buffer/index.js":257}],298:[function(require,module,exports){ +}).call(this)}).call(this,{"isBuffer":require("../is-buffer/index.js")}) +},{"../is-buffer/index.js":202}],241:[function(require,module,exports){ 'use strict' var inherits = require('inherits') var HashBase = require('hash-base') @@ -64505,7 +60170,134 @@ function fnI (a, b, c, d, m, k, s) { module.exports = MD5 -},{"hash-base":224,"inherits":256,"safe-buffer":404}],299:[function(require,module,exports){ +},{"hash-base":242,"inherits":200,"safe-buffer":390}],242:[function(require,module,exports){ +'use strict' +var Buffer = require('safe-buffer').Buffer +var Transform = require('readable-stream').Transform +var inherits = require('inherits') + +function throwIfNotStringOrBuffer (val, prefix) { + if (!Buffer.isBuffer(val) && typeof val !== 'string') { + throw new TypeError(prefix + ' must be a string or a buffer') + } +} + +function HashBase (blockSize) { + Transform.call(this) + + this._block = Buffer.allocUnsafe(blockSize) + this._blockSize = blockSize + this._blockOffset = 0 + this._length = [0, 0, 0, 0] + + this._finalized = false +} + +inherits(HashBase, Transform) + +HashBase.prototype._transform = function (chunk, encoding, callback) { + var error = null + try { + this.update(chunk, encoding) + } catch (err) { + error = err + } + + callback(error) +} + +HashBase.prototype._flush = function (callback) { + var error = null + try { + this.push(this.digest()) + } catch (err) { + error = err + } + + callback(error) +} + +HashBase.prototype.update = function (data, encoding) { + throwIfNotStringOrBuffer(data, 'Data') + if (this._finalized) throw new Error('Digest already called') + if (!Buffer.isBuffer(data)) data = Buffer.from(data, encoding) + + // consume data + var block = this._block + var offset = 0 + while (this._blockOffset + data.length - offset >= this._blockSize) { + for (var i = this._blockOffset; i < this._blockSize;) block[i++] = data[offset++] + this._update() + this._blockOffset = 0 + } + while (offset < data.length) block[this._blockOffset++] = data[offset++] + + // update length + for (var j = 0, carry = data.length * 8; carry > 0; ++j) { + this._length[j] += carry + carry = (this._length[j] / 0x0100000000) | 0 + if (carry > 0) this._length[j] -= 0x0100000000 * carry + } + + return this +} + +HashBase.prototype._update = function () { + throw new Error('_update is not implemented') +} + +HashBase.prototype.digest = function (encoding) { + if (this._finalized) throw new Error('Digest already called') + this._finalized = true + + var digest = this._digest() + if (encoding !== undefined) digest = digest.toString(encoding) + + // reset state + this._block.fill(0) + this._blockOffset = 0 + for (var i = 0; i < 4; ++i) this._length[i] = 0 + + return digest +} + +HashBase.prototype._digest = function () { + throw new Error('_digest is not implemented') +} + +module.exports = HashBase + +},{"inherits":200,"readable-stream":257,"safe-buffer":390}],243:[function(require,module,exports){ +arguments[4][210][0].apply(exports,arguments) +},{"dup":210}],244:[function(require,module,exports){ +arguments[4][211][0].apply(exports,arguments) +},{"./_stream_readable":246,"./_stream_writable":248,"_process":350,"dup":211,"inherits":200}],245:[function(require,module,exports){ +arguments[4][212][0].apply(exports,arguments) +},{"./_stream_transform":247,"dup":212,"inherits":200}],246:[function(require,module,exports){ +arguments[4][213][0].apply(exports,arguments) +},{"../errors":243,"./_stream_duplex":244,"./internal/streams/async_iterator":249,"./internal/streams/buffer_list":250,"./internal/streams/destroy":251,"./internal/streams/from":253,"./internal/streams/state":255,"./internal/streams/stream":256,"_process":350,"buffer":118,"dup":213,"events":172,"inherits":200,"string_decoder/":415,"util":88}],247:[function(require,module,exports){ +arguments[4][214][0].apply(exports,arguments) +},{"../errors":243,"./_stream_duplex":244,"dup":214,"inherits":200}],248:[function(require,module,exports){ +arguments[4][215][0].apply(exports,arguments) +},{"../errors":243,"./_stream_duplex":244,"./internal/streams/destroy":251,"./internal/streams/state":255,"./internal/streams/stream":256,"_process":350,"buffer":118,"dup":215,"inherits":200,"util-deprecate":417}],249:[function(require,module,exports){ +arguments[4][216][0].apply(exports,arguments) +},{"./end-of-stream":252,"_process":350,"dup":216}],250:[function(require,module,exports){ +arguments[4][217][0].apply(exports,arguments) +},{"buffer":118,"dup":217,"util":88}],251:[function(require,module,exports){ +arguments[4][218][0].apply(exports,arguments) +},{"_process":350,"dup":218}],252:[function(require,module,exports){ +arguments[4][219][0].apply(exports,arguments) +},{"../../../errors":243,"dup":219}],253:[function(require,module,exports){ +arguments[4][220][0].apply(exports,arguments) +},{"dup":220}],254:[function(require,module,exports){ +arguments[4][221][0].apply(exports,arguments) +},{"../../../errors":243,"./end-of-stream":252,"dup":221}],255:[function(require,module,exports){ +arguments[4][222][0].apply(exports,arguments) +},{"../../../errors":243,"dup":222}],256:[function(require,module,exports){ +arguments[4][223][0].apply(exports,arguments) +},{"dup":223,"events":172}],257:[function(require,module,exports){ +arguments[4][224][0].apply(exports,arguments) +},{"./lib/_stream_duplex.js":244,"./lib/_stream_passthrough.js":245,"./lib/_stream_readable.js":246,"./lib/_stream_transform.js":247,"./lib/_stream_writable.js":248,"./lib/internal/streams/end-of-stream.js":252,"./lib/internal/streams/pipeline.js":254,"dup":224}],258:[function(require,module,exports){ var bn = require('bn.js'); var brorand = require('brorand'); @@ -64558,1219 +60350,3691 @@ MillerRabin.prototype.test = function test(n, k, cb) { if (cb) cb(a); - var x = a.toRed(red).redPow(d); - if (x.cmp(rone) === 0 || x.cmp(rn1) === 0) - continue; + var x = a.toRed(red).redPow(d); + if (x.cmp(rone) === 0 || x.cmp(rn1) === 0) + continue; + + for (var i = 1; i < s; i++) { + x = x.redSqr(); + + if (x.cmp(rone) === 0) + return false; + if (x.cmp(rn1) === 0) + break; + } + + if (i === s) + return false; + } + + return prime; +}; + +MillerRabin.prototype.getDivisor = function getDivisor(n, k) { + var len = n.bitLength(); + var red = bn.mont(n); + var rone = new bn(1).toRed(red); + + if (!k) + k = Math.max(1, (len / 48) | 0); + + // Find d and s, (n - 1) = (2 ^ s) * d; + var n1 = n.subn(1); + for (var s = 0; !n1.testn(s); s++) {} + var d = n.shrn(s); + + var rn1 = n1.toRed(red); + + for (; k > 0; k--) { + var a = this._randrange(new bn(2), n1); + + var g = n.gcd(a); + if (g.cmpn(1) !== 0) + return g; + + var x = a.toRed(red).redPow(d); + if (x.cmp(rone) === 0 || x.cmp(rn1) === 0) + continue; + + for (var i = 1; i < s; i++) { + x = x.redSqr(); + + if (x.cmp(rone) === 0) + return x.fromRed().subn(1).gcd(n); + if (x.cmp(rn1) === 0) + break; + } + + if (i === s) { + x = x.redSqr(); + return x.fromRed().subn(1).gcd(n); + } + } + + return false; +}; + +},{"bn.js":86,"brorand":87}],259:[function(require,module,exports){ +module.exports = assert; + +function assert(val, msg) { + if (!val) + throw new Error(msg || 'Assertion failed'); +} + +assert.equal = function assertEqual(l, r, msg) { + if (l != r) + throw new Error(msg || ('Assertion failed: ' + l + ' != ' + r)); +}; + +},{}],260:[function(require,module,exports){ +'use strict'; + +var utils = exports; + +function toArray(msg, enc) { + if (Array.isArray(msg)) + return msg.slice(); + if (!msg) + return []; + var res = []; + if (typeof msg !== 'string') { + for (var i = 0; i < msg.length; i++) + res[i] = msg[i] | 0; + return res; + } + if (enc === 'hex') { + msg = msg.replace(/[^a-z0-9]+/ig, ''); + if (msg.length % 2 !== 0) + msg = '0' + msg; + for (var i = 0; i < msg.length; i += 2) + res.push(parseInt(msg[i] + msg[i + 1], 16)); + } else { + for (var i = 0; i < msg.length; i++) { + var c = msg.charCodeAt(i); + var hi = c >> 8; + var lo = c & 0xff; + if (hi) + res.push(hi, lo); + else + res.push(lo); + } + } + return res; +} +utils.toArray = toArray; + +function zero2(word) { + if (word.length === 1) + return '0' + word; + else + return word; +} +utils.zero2 = zero2; + +function toHex(msg) { + var res = ''; + for (var i = 0; i < msg.length; i++) + res += zero2(msg[i].toString(16)); + return res; +} +utils.toHex = toHex; + +utils.encode = function encode(arr, enc) { + if (enc === 'hex') + return toHex(arr); + else + return arr; +}; + +},{}],261:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +function getCrypto() { + if (typeof window === "undefined") { + if (typeof self !== "undefined" && self.document === undefined) { + // inside a web worker + return crypto; + } + else { + // inside node + return require("crypto").webcrypto; + } + } + // browsers + return window.crypto; +} +exports.default = getCrypto; + +},{"crypto":131}],262:[function(require,module,exports){ +(function (global,Buffer){(function (){ +"use strict"; +/* eslint-disable no-undef */ +/* eslint-disable global-require */ +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.ToolDb = exports.handleSubscribe = exports.handleQuery = exports.handlePut = exports.handlePong = exports.handlePing = exports.handleGet = exports.handleCrdtPut = exports.handleCrdtGet = exports.handleCrdt = exports.ToolDbNetwork = exports.ToolDbNetworkAdapter = exports.verifyData = exports.saveKeysComb = exports.loadKeysComb = exports.importKey = exports.generateKeysComb = exports.generateKeyPair = exports.generateKeyFromPassword = exports.exportKey = exports.encryptWithPass = exports.encryptData = exports.encodeKeyString = exports.deriveSecret = exports.decryptWithPass = exports.decryptData = exports.decodeKeyString = exports.verifyMessage = exports.uint8ToBase64 = exports.toBase64 = exports.textRandom = exports.stringToArrayBuffer = exports.randomAnimal = exports.generateIv = exports.fromBase64 = exports.base64ToUint8 = exports.base64ToBinaryDocument = exports.base64ToBinaryChange = exports.base64ToArrayBuffer = exports.arrayBufferToString = exports.arrayBufferToBase64 = exports.signData = exports.sha256 = exports.sha1 = exports.uniq = exports.proofOfWork = void 0; +var elliptic_1 = __importDefault(require("elliptic")); +__exportStar(require("./types/tooldb"), exports); +__exportStar(require("./types/message"), exports); +global.Buffer = global.Buffer || require("buffer").Buffer; +if (typeof btoa === "undefined") { + global.btoa = function (str) { + return Buffer.from(str, "binary").toString("base64"); + }; +} +if (typeof atob === "undefined") { + global.atob = function (b64Encoded) { + return Buffer.from(b64Encoded, "base64").toString("binary"); + }; +} +if (typeof window === "undefined") { + // Only set global crypto if we are in node, not for web workers + if (typeof self !== "undefined" && self.document !== undefined) { + global.crypto = require("crypto").webcrypto; + } + global.ecp256 = new elliptic_1.default.ec("p256"); +} +else { + window.ecp256 = new elliptic_1.default.ec("p256"); +} +var proofOfWork_1 = require("./utils/proofOfWork"); +Object.defineProperty(exports, "proofOfWork", { enumerable: true, get: function () { return __importDefault(proofOfWork_1).default; } }); +var uniq_1 = require("./utils/uniq"); +Object.defineProperty(exports, "uniq", { enumerable: true, get: function () { return __importDefault(uniq_1).default; } }); +var sha1_1 = require("./utils/sha1"); +Object.defineProperty(exports, "sha1", { enumerable: true, get: function () { return __importDefault(sha1_1).default; } }); +var sha256_1 = require("./utils/sha256"); +Object.defineProperty(exports, "sha256", { enumerable: true, get: function () { return __importDefault(sha256_1).default; } }); +var signData_1 = require("./utils/signData"); +Object.defineProperty(exports, "signData", { enumerable: true, get: function () { return __importDefault(signData_1).default; } }); +var arrayBufferToBase64_1 = require("./utils/arrayBufferToBase64"); +Object.defineProperty(exports, "arrayBufferToBase64", { enumerable: true, get: function () { return __importDefault(arrayBufferToBase64_1).default; } }); +var arrayBufferToString_1 = require("./utils/arrayBufferToString"); +Object.defineProperty(exports, "arrayBufferToString", { enumerable: true, get: function () { return __importDefault(arrayBufferToString_1).default; } }); +var base64ToArrayBuffer_1 = require("./utils/base64ToArrayBuffer"); +Object.defineProperty(exports, "base64ToArrayBuffer", { enumerable: true, get: function () { return __importDefault(base64ToArrayBuffer_1).default; } }); +var base64ToBinaryChange_1 = require("./utils/base64ToBinaryChange"); +Object.defineProperty(exports, "base64ToBinaryChange", { enumerable: true, get: function () { return __importDefault(base64ToBinaryChange_1).default; } }); +var base64ToBinaryDocument_1 = require("./utils/base64ToBinaryDocument"); +Object.defineProperty(exports, "base64ToBinaryDocument", { enumerable: true, get: function () { return __importDefault(base64ToBinaryDocument_1).default; } }); +var base64ToUint8_1 = require("./utils/base64ToUint8"); +Object.defineProperty(exports, "base64ToUint8", { enumerable: true, get: function () { return __importDefault(base64ToUint8_1).default; } }); +var fromBase64_1 = require("./utils/fromBase64"); +Object.defineProperty(exports, "fromBase64", { enumerable: true, get: function () { return __importDefault(fromBase64_1).default; } }); +var generateIv_1 = require("./utils/generateIv"); +Object.defineProperty(exports, "generateIv", { enumerable: true, get: function () { return __importDefault(generateIv_1).default; } }); +var randomAnimal_1 = require("./utils/randomAnimal"); +Object.defineProperty(exports, "randomAnimal", { enumerable: true, get: function () { return __importDefault(randomAnimal_1).default; } }); +var stringToArrayBuffer_1 = require("./utils/stringToArrayBuffer"); +Object.defineProperty(exports, "stringToArrayBuffer", { enumerable: true, get: function () { return __importDefault(stringToArrayBuffer_1).default; } }); +var textRandom_1 = require("./utils/textRandom"); +Object.defineProperty(exports, "textRandom", { enumerable: true, get: function () { return __importDefault(textRandom_1).default; } }); +var toBase64_1 = require("./utils/toBase64"); +Object.defineProperty(exports, "toBase64", { enumerable: true, get: function () { return __importDefault(toBase64_1).default; } }); +var uint8ToBase64_1 = require("./utils/uint8ToBase64"); +Object.defineProperty(exports, "uint8ToBase64", { enumerable: true, get: function () { return __importDefault(uint8ToBase64_1).default; } }); +var verifyMessage_1 = require("./utils/verifyMessage"); +Object.defineProperty(exports, "verifyMessage", { enumerable: true, get: function () { return __importDefault(verifyMessage_1).default; } }); +var decodeKeyString_1 = require("./utils/crypto/decodeKeyString"); +Object.defineProperty(exports, "decodeKeyString", { enumerable: true, get: function () { return __importDefault(decodeKeyString_1).default; } }); +var decryptData_1 = require("./utils/crypto/decryptData"); +Object.defineProperty(exports, "decryptData", { enumerable: true, get: function () { return __importDefault(decryptData_1).default; } }); +var decryptWithPass_1 = require("./utils/crypto/decryptWithPass"); +Object.defineProperty(exports, "decryptWithPass", { enumerable: true, get: function () { return __importDefault(decryptWithPass_1).default; } }); +var deriveSecret_1 = require("./utils/crypto/deriveSecret"); +Object.defineProperty(exports, "deriveSecret", { enumerable: true, get: function () { return __importDefault(deriveSecret_1).default; } }); +var encodeKeyString_1 = require("./utils/crypto/encodeKeyString"); +Object.defineProperty(exports, "encodeKeyString", { enumerable: true, get: function () { return __importDefault(encodeKeyString_1).default; } }); +var encryptData_1 = require("./utils/crypto/encryptData"); +Object.defineProperty(exports, "encryptData", { enumerable: true, get: function () { return __importDefault(encryptData_1).default; } }); +var encryptWithPass_1 = require("./utils/crypto/encryptWithPass"); +Object.defineProperty(exports, "encryptWithPass", { enumerable: true, get: function () { return __importDefault(encryptWithPass_1).default; } }); +var exportKey_1 = require("./utils/crypto/exportKey"); +Object.defineProperty(exports, "exportKey", { enumerable: true, get: function () { return __importDefault(exportKey_1).default; } }); +var generateKeyFromPassword_1 = require("./utils/crypto/generateKeyFromPassword"); +Object.defineProperty(exports, "generateKeyFromPassword", { enumerable: true, get: function () { return __importDefault(generateKeyFromPassword_1).default; } }); +var generateKeyPair_1 = require("./utils/crypto/generateKeyPair"); +Object.defineProperty(exports, "generateKeyPair", { enumerable: true, get: function () { return __importDefault(generateKeyPair_1).default; } }); +var generateKeysComb_1 = require("./utils/crypto/generateKeysComb"); +Object.defineProperty(exports, "generateKeysComb", { enumerable: true, get: function () { return __importDefault(generateKeysComb_1).default; } }); +var importKey_1 = require("./utils/crypto/importKey"); +Object.defineProperty(exports, "importKey", { enumerable: true, get: function () { return __importDefault(importKey_1).default; } }); +var loadKeysComb_1 = require("./utils/crypto/loadKeysComb"); +Object.defineProperty(exports, "loadKeysComb", { enumerable: true, get: function () { return __importDefault(loadKeysComb_1).default; } }); +var saveKeysComb_1 = require("./utils/crypto/saveKeysComb"); +Object.defineProperty(exports, "saveKeysComb", { enumerable: true, get: function () { return __importDefault(saveKeysComb_1).default; } }); +var verifyData_1 = require("./utils/crypto/verifyData"); +Object.defineProperty(exports, "verifyData", { enumerable: true, get: function () { return __importDefault(verifyData_1).default; } }); +var networkAdapterBase_1 = require("./networkAdapterBase"); +Object.defineProperty(exports, "ToolDbNetworkAdapter", { enumerable: true, get: function () { return __importDefault(networkAdapterBase_1).default; } }); +var toolDbNetwork_1 = require("./toolDbNetwork"); +Object.defineProperty(exports, "ToolDbNetwork", { enumerable: true, get: function () { return __importDefault(toolDbNetwork_1).default; } }); +var handleCrdt_1 = require("./messageHandlers/handleCrdt"); +Object.defineProperty(exports, "handleCrdt", { enumerable: true, get: function () { return __importDefault(handleCrdt_1).default; } }); +var handleCrdtGet_1 = require("./messageHandlers/handleCrdtGet"); +Object.defineProperty(exports, "handleCrdtGet", { enumerable: true, get: function () { return __importDefault(handleCrdtGet_1).default; } }); +var handleCrdtPut_1 = require("./messageHandlers/handleCrdtPut"); +Object.defineProperty(exports, "handleCrdtPut", { enumerable: true, get: function () { return __importDefault(handleCrdtPut_1).default; } }); +var handleGet_1 = require("./messageHandlers/handleGet"); +Object.defineProperty(exports, "handleGet", { enumerable: true, get: function () { return __importDefault(handleGet_1).default; } }); +var handlePing_1 = require("./messageHandlers/handlePing"); +Object.defineProperty(exports, "handlePing", { enumerable: true, get: function () { return __importDefault(handlePing_1).default; } }); +var handlePong_1 = require("./messageHandlers/handlePong"); +Object.defineProperty(exports, "handlePong", { enumerable: true, get: function () { return __importDefault(handlePong_1).default; } }); +var handlePut_1 = require("./messageHandlers/handlePut"); +Object.defineProperty(exports, "handlePut", { enumerable: true, get: function () { return __importDefault(handlePut_1).default; } }); +var handleQuery_1 = require("./messageHandlers/handleQuery"); +Object.defineProperty(exports, "handleQuery", { enumerable: true, get: function () { return __importDefault(handleQuery_1).default; } }); +var handleSubscribe_1 = require("./messageHandlers/handleSubscribe"); +Object.defineProperty(exports, "handleSubscribe", { enumerable: true, get: function () { return __importDefault(handleSubscribe_1).default; } }); +var tooldb_1 = require("./tooldb"); +Object.defineProperty(exports, "ToolDb", { enumerable: true, get: function () { return __importDefault(tooldb_1).default; } }); + +}).call(this)}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {},require("buffer").Buffer) +},{"./messageHandlers/handleCrdt":265,"./messageHandlers/handleCrdtGet":266,"./messageHandlers/handleCrdtPut":267,"./messageHandlers/handleGet":269,"./messageHandlers/handlePing":270,"./messageHandlers/handlePong":271,"./messageHandlers/handlePut":272,"./messageHandlers/handleQuery":273,"./messageHandlers/handleSubscribe":274,"./networkAdapterBase":275,"./toolDbNetwork":284,"./tooldb":292,"./types/message":293,"./types/tooldb":294,"./utils/arrayBufferToBase64":295,"./utils/arrayBufferToString":297,"./utils/base64ToArrayBuffer":298,"./utils/base64ToBinaryChange":299,"./utils/base64ToBinaryDocument":300,"./utils/base64ToUint8":301,"./utils/crypto/decodeKeyString":303,"./utils/crypto/decryptData":304,"./utils/crypto/decryptWithPass":305,"./utils/crypto/deriveSecret":306,"./utils/crypto/encodeKeyString":307,"./utils/crypto/encryptData":308,"./utils/crypto/encryptWithPass":309,"./utils/crypto/exportKey":310,"./utils/crypto/generateKeyFromPassword":311,"./utils/crypto/generateKeyPair":312,"./utils/crypto/generateKeysComb":313,"./utils/crypto/importKey":314,"./utils/crypto/loadKeysComb":315,"./utils/crypto/saveKeysComb":316,"./utils/crypto/verifyData":317,"./utils/fromBase64":318,"./utils/generateIv":319,"./utils/proofOfWork":324,"./utils/randomAnimal":325,"./utils/sha1":326,"./utils/sha256":327,"./utils/signData":328,"./utils/stringToArrayBuffer":329,"./utils/textRandom":330,"./utils/toBase64":331,"./utils/uint8ToBase64":332,"./utils/uniq":333,"./utils/verifyMessage":334,"buffer":118,"crypto":131,"elliptic":147}],263:[function(require,module,exports){ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +var automerge_1 = __importDefault(require("automerge")); +function loadCrdtDocument(key, doDefault) { + var _this = this; + if (doDefault === void 0) { doDefault = true; } + return new Promise(function (resolve, reject) { + if (_this.documents[key]) { + resolve(_this.documents[key]); + } + else { + _this.store.get(key + ".crdt", function (err, data) { + var currentDoc = null; + if (data) { + // De-serealize stored crdt document + // console.log("data", typeof data, data); + var loaded_1 = data; + if (typeof data === "string") { + var split = data.split(","); + loaded_1 = new Uint8Array(split.length); + split.forEach(function (s, i) { + loaded_1[i] = parseInt(s); + }); + } + currentDoc = automerge_1.default.load(loaded_1); + // console.log("CRDT LOADED", key, currentDoc); + } + else { + // console.log("CRDT not found for", key); + if (doDefault) { + currentDoc = automerge_1.default.init(); + } + } + resolve(currentDoc); + }); + } + }); +} +exports.default = loadCrdtDocument; + +},{"automerge":81}],264:[function(require,module,exports){ +"use strict"; +var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { + if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { + if (ar || !(i in from)) { + if (!ar) ar = Array.prototype.slice.call(from, 0, i); + ar[i] = from[i]; + } + } + return to.concat(ar || Array.prototype.slice.call(from)); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +var _1 = require("."); +function logger(arg0, arg1, arg2, arg3, arg4, arg5) { + if (this.options.debug) { + var isNode = typeof window === "undefined" ? self.document !== undefined : false; + var title = isNode + ? this.options.storageName + : "%c" + this.options.storageName; + var style = isNode + ? "" + : "background: #" + + (0, _1.sha1)(this.options.storageName).slice(-6) + + "; padding: 2px; color: black"; + console.log.apply(console, __spreadArray([title, + style], [arg0, arg1, arg2, arg3, arg4, arg4, arg5].slice(0, arguments.length), false)); + } +} +exports.default = logger; + +},{".":262}],265:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var __1 = require(".."); +function handleCrdt(message, remotePeerId) { + var key = message.key; + this.triggerKeyListener(key, message); + // OOHH THE TYPECAST PAIN + // This works but the hacking is awful, we need a better solution for storing the crdts + var savedDoc = (0, __1.base64ToBinaryDocument)(message.doc); + this.store.put(key + ".crdt", savedDoc, function (err, data) { + // + }); +} +exports.default = handleCrdt; + +},{"..":262}],266:[function(require,module,exports){ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +var automerge_1 = __importDefault(require("automerge")); +var __1 = require(".."); +function handleCrdtGet(message, remotePeerId) { + var _this = this; + this.loadCrdtDocument(message.key, false).then(function (currentDoc) { + if (currentDoc) { + var saved = automerge_1.default.save(currentDoc || automerge_1.default.init()); + _this.network.sendToClientId(remotePeerId, { + type: "crdt", + id: message.id, + key: message.key, + to: [], + doc: (0, __1.uint8ToBase64)(saved), + }); + } + else { + _this.logger("Local key not found, relay", JSON.stringify(message)); + _this.network.sendToAll(message, true); + } + }); +} +exports.default = handleCrdtGet; + +},{"..":262,"automerge":81}],267:[function(require,module,exports){ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +var automerge_1 = __importDefault(require("automerge")); +var __1 = require(".."); +var toolDbVerificationWrapper_1 = __importDefault(require("../toolDbVerificationWrapper")); +function handleCrdtPut(message, remotePeerId) { + var _this = this; + // key = aggregated, final value + // key.crdt = automerge doc with changes + // const writeStart = new Date().getTime(); + toolDbVerificationWrapper_1.default.call(this, message).then(function (value) { + // console.log("CRDT Verification wrapper result: ", value); + if (value === __1.VerifyResult.Verified) { + var key_1 = message.k; + var data = []; + try { + data = JSON.parse(message.v); + } + catch (e) { + // + } + var changes_1 = data.map(__1.base64ToBinaryChange); + _this.loadCrdtDocument(key_1).then(function (currentDoc) { + // if (currentDoc) { + // console.log( + // "loaded", + // key, + // currentDoc, + // Automerge.getHistory(currentDoc) + // ); + // } + var newDoc = automerge_1.default.init(); + try { + newDoc = automerge_1.default.applyChanges(currentDoc || automerge_1.default.init(), changes_1)[0]; + } + catch (e) { + try { + newDoc = automerge_1.default.applyChanges(automerge_1.default.init(), changes_1)[0]; + } + catch (ee) { + _this.logger(ee); + } + } + // if (newDoc) { + // console.log( + // "new document changes:", + // Automerge.getHistory(newDoc), + // "final: ", + // newDoc + // ); + // } + // persist + _this.documents[key_1] = newDoc; + // OOHH THE TYPECAST PAIN + // This works but the hacking is awful, we need a better solution for storing the crdts + var savedDoc = automerge_1.default.save(newDoc); + _this.store.put(key_1 + ".crdt", savedDoc, function (err, data) { + // const writeEnd = new Date().getTime(); + // console.log("CRDT write: ", (writeEnd - writeStart) / 1000); + }); + var crdtMessage = { + type: "crdt", + key: key_1, + id: message.id, + to: [], + doc: (0, __1.uint8ToBase64)(savedDoc), + }; + _this.triggerKeyListener(key_1, crdtMessage); + // relay to other servers + // !!! + _this.network.sendToAll(crdtMessage, true); + }); + } + else { + console.log("unverified message", value, message); + } + }); +} +exports.default = handleCrdtPut; - for (var i = 1; i < s; i++) { - x = x.redSqr(); +},{"..":262,"../toolDbVerificationWrapper":291,"automerge":81}],268:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +function handleFunction(message, remotePeerId) { + var _this = this; + // executes the given function by message on the server if it exists + if (this.functions[message.function]) { + try { + this.functions[message.function](message.args) + .then(function (ret) { + var messageReturn = { + return: ret, + type: "functionReturn", + id: message.id, + code: "OK", + to: [], + }; + _this.network.sendToClientId(remotePeerId, messageReturn); + }) + .catch(function (e) { + var messageReturn = { + return: e.toString() || JSON.stringify(e.message || e), + type: "functionReturn", + id: message.id, + code: "ERR", + to: [], + }; + _this.network.sendToClientId(remotePeerId, messageReturn); + }); + } + catch (e) { + // something went wrong, nothing to do here + // We might want to return the exception to the client? + var messageReturn = { + return: e.toString() || JSON.stringify(e.message || e), + type: "functionReturn", + id: message.id, + code: "ERR", + to: [], + }; + this.network.sendToClientId(remotePeerId, messageReturn); + } + } + else { + // function not found + var messageReturn = { + return: "Function not found", + type: "functionReturn", + id: message.id, + code: "NOT_FOUND", + to: [], + }; + this.network.sendToClientId(remotePeerId, messageReturn); + } +} +exports.default = handleFunction; - if (x.cmp(rone) === 0) - return false; - if (x.cmp(rn1) === 0) - break; - } +},{}],269:[function(require,module,exports){ +"use strict"; +var __assign = (this && this.__assign) || function () { + __assign = Object.assign || function(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) + t[p] = s[p]; + } + return t; + }; + return __assign.apply(this, arguments); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +function handleGet(message, remotePeerId) { + var _this = this; + this.store.get(message.key, function (err, data) { + if (data) { + try { + // Use the id of the get so the other client knows we are replying + var oldData = __assign(__assign({ type: "put" }, JSON.parse(data)), { id: message.id, to: [] }); + _this.network.sendToClientId(remotePeerId, oldData); + } + catch (e) { + // socket.send(data); + // do nothing + } + } + else { + _this.logger("Local key not found, relay", JSON.stringify(message)); + _this.network.sendToAll(message, true); + } + }); +} +exports.default = handleGet; - if (i === s) - return false; - } +},{}],270:[function(require,module,exports){ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +var verifyPeer_1 = __importDefault(require("../utils/verifyPeer")); +function handlePing(message, remotePeerId) { + var _this = this; + if (!this.isConnected) { + this.isConnected = true; + this.onConnect(); + } + (0, verifyPeer_1.default)(message.peer).then(function (verified) { + // Verify integrity and topic + if (verified && message.peer.topic === _this.options.topic) { + // Add this peer to our list of peers + _this.peers[message.peer.pubkey] = message.peer; + _this.network.sendToClientId(remotePeerId, { + type: "pong", + isServer: _this.options.server, + clientId: _this.network.getClientAddress(), + to: [], + servers: _this.serverPeers, + id: message.id, + }); + _this.onPeerConnect(message.peer.pubkey); + } + else { + _this.logger("Blocked a remote peer from joining; ", message); + // Drop connection here! + } + }); +} +exports.default = handlePing; - return prime; -}; +},{"../utils/verifyPeer":335}],271:[function(require,module,exports){ +"use strict"; +var __assign = (this && this.__assign) || function () { + __assign = Object.assign || function(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) + t[p] = s[p]; + } + return t; + }; + return __assign.apply(this, arguments); +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +var verifyPeer_1 = __importDefault(require("../utils/verifyPeer")); +function handlePong(message, remotePeerId) { + var _this = this; + if (!this.isConnected) { + this.isConnected = true; + this.onConnect(); + } + if (message.servers) { + message.servers.forEach(function (peer) { + (0, verifyPeer_1.default)(peer).then(function (verified) { + // Verify integrity and topic + if (verified && peer.topic === _this.options.topic) { + // Add this peer to our list of peers + _this.peers[peer.pubkey] = __assign(__assign({}, peer), { isServer: true }); + } + }); + }); + } + this.onPeerConnect(message.clientId); +} +exports.default = handlePong; -MillerRabin.prototype.getDivisor = function getDivisor(n, k) { - var len = n.bitLength(); - var red = bn.mont(n); - var rone = new bn(1).toRed(red); +},{"../utils/verifyPeer":335}],272:[function(require,module,exports){ +"use strict"; +var __assign = (this && this.__assign) || function () { + __assign = Object.assign || function(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) + t[p] = s[p]; + } + return t; + }; + return __assign.apply(this, arguments); +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +var __1 = require(".."); +var toolDbVerificationWrapper_1 = __importDefault(require("../toolDbVerificationWrapper")); +function handlePut(message, remotePeerId) { + var _this = this; + toolDbVerificationWrapper_1.default.call(this, message).then(function (value) { + // console.log("Verification wrapper result: ", value, message.k); + if (value === __1.VerifyResult.Verified) { + // relay to other servers !!! + _this.network.sendToAll(message, true); + _this.store.get(message.k, function (err, oldData) { + if (oldData) { + var parsedOldData = __assign({ type: "put", to: [] }, JSON.parse(oldData)); + if (parsedOldData.t < message.t) { + var key = message.k; + _this.triggerKeyListener(key, message); + _this.store.put(message.k, JSON.stringify(message), function (err, data) { + // + }); + } + else { + var key = message.k; + _this.triggerKeyListener(key, parsedOldData); + } + // } else if (this.options.debug) { + // console.log( + // `${message.k} has old data, but its newer. old ${parsedOldData.t} < new ${message.t}` + // ); + // } + } + else { + var key = message.k; + _this.triggerKeyListener(key, message); + _this.store.put(message.k, JSON.stringify(message), function (err, data) { + // + }); + } + }); + } + else { + console.warn("unverified message: ", value, message); + } + }); +} +exports.default = handlePut; - if (!k) - k = Math.max(1, (len / 48) | 0); +},{"..":262,"../toolDbVerificationWrapper":291}],273:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +function handleQuery(message, remotePeerId) { + var _this = this; + if (message.key.length < 3) + return; + this.store.query(message.key).then(function (keys) { + _this.network.sendToClientId(remotePeerId, { + type: "queryAck", + id: message.id, + to: [], + keys: keys, + }); + }); + if (this.options.server) { + this.network.sendToAll(message, true); + } +} +exports.default = handleQuery; - // Find d and s, (n - 1) = (2 ^ s) * d; - var n1 = n.subn(1); - for (var s = 0; !n1.testn(s); s++) {} - var d = n.shrn(s); +},{}],274:[function(require,module,exports){ +"use strict"; +var __assign = (this && this.__assign) || function () { + __assign = Object.assign || function(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) + t[p] = s[p]; + } + return t; + }; + return __assign.apply(this, arguments); +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +var automerge_1 = __importDefault(require("automerge")); +var __1 = require(".."); +function handleSubscribe(message, remotePeerId) { + var _this = this; + if (remotePeerId) { + var subId = remotePeerId + "-" + message.key; + if (!this.subscriptions.includes(subId)) { + this.subscriptions.push(subId); + this.addKeyListener(message.key, function (msg) { + if ((msg.type === "put" || msg.type === "crdt") && remotePeerId) { + // We do not reply to the socket directly + // instead we use the client id, in case the socket reconnects + _this.network.sendToClientId(remotePeerId, msg); + } + }); + } + } + // basically the exact same as GET, below + this.store.get(message.key, function (err, data) { + if (data) { + try { + var oldData = __assign(__assign({}, JSON.parse(data)), { id: message.id, to: [] }); + _this.network.sendToClientId(remotePeerId, oldData); + } + catch (e) { + // do nothing + } + } + }); + this.loadCrdtDocument(message.key, false).then(function (doc) { + // console.log("Load crdt from subscribe", message.key, doc); + if (doc) { + var savedDoc = automerge_1.default.save(doc); + var msg = { + type: "crdt", + key: message.key, + to: [], + id: (0, __1.textRandom)(10), + doc: (0, __1.uint8ToBase64)(savedDoc), + }; + _this.network.sendToClientId(remotePeerId, msg); + } + }); +} +exports.default = handleSubscribe; - var rn1 = n1.toRed(red); +},{"..":262,"automerge":81}],275:[function(require,module,exports){ +"use strict"; +var __assign = (this && this.__assign) || function () { + __assign = Object.assign || function(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) + t[p] = s[p]; + } + return t; + }; + return __assign.apply(this, arguments); +}; +var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { + if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { + if (ar || !(i in from)) { + if (!ar) ar = Array.prototype.slice.call(from, 0, i); + ar[i] = from[i]; + } + } + return to.concat(ar || Array.prototype.slice.call(from)); +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +var _1 = require("."); +var getPeerSignature_1 = __importDefault(require("./utils/getPeerSignature")); +var ToolDbNetworkAdapter = /** @class */ (function () { + function ToolDbNetworkAdapter(db) { + var _this = this; + this._clientToSend = {}; + this._clientSocket = {}; + this._isClientConnected = {}; + this._clientIsServer = {}; + this._tooldb = db; + db.on("init", function () { + if (_this.tooldb.options.server) { + _this.getMeAsPeer().then(function (meAsPeer) { + _this.tooldb.peers[meAsPeer.pubkey] = meAsPeer; + }); + } + }); + } + Object.defineProperty(ToolDbNetworkAdapter.prototype, "clientToSend", { + get: function () { + return this._clientToSend; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(ToolDbNetworkAdapter.prototype, "clientSocket", { + get: function () { + return this._clientSocket; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(ToolDbNetworkAdapter.prototype, "isClientConnected", { + get: function () { + return this._isClientConnected; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(ToolDbNetworkAdapter.prototype, "tooldb", { + get: function () { + return this._tooldb; + }, + enumerable: false, + configurable: true + }); + ToolDbNetworkAdapter.prototype.getMeAsPeer = function () { + var _this = this; + var timestamp = new Date().getTime(); + if (this.tooldb.options.defaultKeys === undefined) + return Promise.reject(); + else + return (0, getPeerSignature_1.default)(this.tooldb.options.defaultKeys.privateKey, this.tooldb.options.topic, timestamp, this.tooldb.options.host, this.tooldb.options.port).then(function (signature) { + var me = { + topic: _this.tooldb.options.topic, + timestamp: timestamp, + host: _this.tooldb.options.host, + port: _this.tooldb.options.port, + pubkey: _this.tooldb.getPubKey(), + sig: signature, + isServer: _this.tooldb.options.server, + }; + return me; + }); + }; + /** + * Check if the specified client is connected or not + * @param clientId Client ID + * @returns boolean + */ + ToolDbNetworkAdapter.prototype.isConnected = function (clientId) { + return this._isClientConnected[clientId] + ? this._isClientConnected[clientId]() + : false; + }; + /** + * Check if the specified client is a server/relay + * @param clientId Client ID + * @returns boolean + */ + ToolDbNetworkAdapter.prototype.isServer = function (clientId) { + return this._clientIsServer[clientId] || false; + }; + ToolDbNetworkAdapter.prototype.craftPingMessage = function () { + var _this = this; + return this.getMeAsPeer().then(function (meAsPeer) { + return JSON.stringify({ + type: "ping", + clientId: _this.getClientAddress(), + to: [_this.getClientAddress()], + isServer: _this.tooldb.options.server, + id: (0, _1.textRandom)(10), + peer: meAsPeer, + }); + }); + }; + /** + * Execute the function to send a message to the specified client ID + * @param clientId Client ID + * @param message Message + */ + ToolDbNetworkAdapter.prototype.executeSendToClient = function (clientId, message) { + if (this._clientToSend[clientId]) { + this._clientToSend[clientId](message); + } + }; + ToolDbNetworkAdapter.prototype.getClientAddress = function () { + // This is not a good idea to use on all adapters, so it should be replaced + // if its causing issues. The only reason we use the last 20 chars is to + // muse the same peer address as the webrtc adapter. + return this.tooldb.pubKey; + }; + ToolDbNetworkAdapter.prototype.onClientDisconnect = function (clientId) { + delete this._clientToSend[clientId]; + delete this._clientIsServer[clientId]; + delete this._isClientConnected[clientId]; + }; + /** + * Should be called as a message payload handler + * This function will take care of processing the messages and also making sure + * we use the correct response methods troughout the adapter. + * @param message message payload + * @param clientId Client ID (can be null for ping/pong) + * @param setClientId Callback to set the client id on the parent class + */ + ToolDbNetworkAdapter.prototype.onClientMessage = function (message, clientId, setClientId) { + // this.tooldb.logger("onClientMessage", clientId); + if (clientId && !this.tooldb.processedOutHashes[clientId]) { + this.tooldb.processedOutHashes[clientId] = []; + } + try { + var parsedMessage = JSON.parse(message); + // We assume the first messages to arrive will always be ping or pong. + // Only after that we can get the client id for this socket. + if (parsedMessage.type === "ping" || parsedMessage.type === "pong") { + var cid = parsedMessage.clientId; + setClientId(cid); + this._clientIsServer[cid] = parsedMessage.isServer; + this.tooldb.processedOutHashes[cid] = []; + this.tooldb.clientOnMessage(parsedMessage, cid); + } + else if (clientId) { + this.tooldb.clientOnMessage(parsedMessage, clientId); + } + } + catch (e) { + this.tooldb.logger("Got message ERR", message); + this.tooldb.logger(e); + } + }; + /** + * Sends a message to all peers connected to us + * This function takes care of the message deduplication, making sure we dont send + * the same message twice to the same peer. + * @param msg message data + * @param crossServerOnly If this message should be send to server peers only + * @param isRelay if we should relay this message + */ + ToolDbNetworkAdapter.prototype.sendToAll = function (msg, crossServerOnly) { + var _this = this; + if (crossServerOnly === void 0) { crossServerOnly = false; } + var pubkey = this.getClientAddress(); + var to = pubkey ? (0, _1.uniq)(__spreadArray(__spreadArray([], msg.to, true), [pubkey], false)) : msg.to; + var finalMessage = JSON.stringify(__assign(__assign({}, msg), { to: to })); + var filteredConns = Object.keys(this.clientToSend) + .filter(function (id) { return !to.includes(id); }) + .filter(function (clientId) { return _this.isConnected(clientId); }); + filteredConns.forEach(function (clientId) { + if ((crossServerOnly && _this.isServer(clientId)) || !crossServerOnly) { + _this.tooldb.logger(to.map(function (k) { return k.slice(-20); }), "Sent out to (all):", clientId.slice(-20)); + if (msg.type === "put" || msg.type === "crdtPut") { + if (!_this.tooldb.processedOutHashes[clientId].includes(msg.h)) { + _this.executeSendToClient(clientId, finalMessage); + _this.tooldb.processedOutHashes[clientId].push(msg.h); + } + } + else { + _this.executeSendToClient(clientId, finalMessage); + } + } + // } else { + // this.tooldb.logger("Fitlered out;", clientId); + // } + }); + }; + /** + * Sends a message to a single peer. + * This function also takes care of the message deduplication. + * @param clientId Peer/Client id we want to send to. + * @param msg message data + */ + ToolDbNetworkAdapter.prototype.sendToClientId = function (clientId, msg) { + var pubkey = this.getClientAddress(); + var to = pubkey ? (0, _1.uniq)(__spreadArray(__spreadArray([], msg.to, true), [pubkey], false)) : msg.to; + var finalMessage = JSON.stringify(__assign(__assign({}, msg), { to: to })); + this.tooldb.logger(to.map(function (k) { return k.slice(-20); }), "Sent out to (single):", clientId.slice(-20)); + if (msg.type === "put" || msg.type === "crdtPut") { + if (clientId && + !this.tooldb.processedOutHashes[clientId].includes(msg.h)) { + this.executeSendToClient(clientId, finalMessage); + this.tooldb.processedOutHashes[clientId].push(msg.h); + } + } + else { + this.executeSendToClient(clientId, finalMessage); + } + }; + return ToolDbNetworkAdapter; +}()); +exports.default = ToolDbNetworkAdapter; - for (; k > 0; k--) { - var a = this._randrange(new bn(2), n1); +},{".":262,"./utils/getPeerSignature":320}],276:[function(require,module,exports){ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +var encodeKeyString_1 = __importDefault(require("./utils/crypto/encodeKeyString")); +var exportKey_1 = __importDefault(require("./utils/crypto/exportKey")); +var generateKeysComb_1 = __importDefault(require("./utils/crypto/generateKeysComb")); +var randomAnimal_1 = __importDefault(require("./utils/randomAnimal")); +function toolDbAnonSignIn() { + var _this = this; + return (0, generateKeysComb_1.default)().then(function (newKeys) { + return (0, exportKey_1.default)("spki", newKeys.signKeys.publicKey) + .then(function (skpub) { return (0, encodeKeyString_1.default)(skpub); }) + .then(function (pubKey) { + _this.user = { + keys: newKeys, + name: "Anonymous " + (0, randomAnimal_1.default)(), + pubKey: pubKey, + }; + return newKeys; + }); + }); +} +exports.default = toolDbAnonSignIn; - var g = n.gcd(a); - if (g.cmpn(1) !== 0) - return g; +},{"./utils/crypto/encodeKeyString":307,"./utils/crypto/exportKey":310,"./utils/crypto/generateKeysComb":313,"./utils/randomAnimal":325}],277:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +function toolDbClientOnMessage(message, remotePeerId) { + if (!this.processedIds[message.type]) { + this.processedIds[message.type] = []; + } + if (this.processedIds[message.type].includes(message.id)) { + // console.warn( + // `Already processed this message > ${message.type} from ${remotePeerId}` + // ); + return; + } + this.processedIds[message.type].push(message.id); + // console.warn(`Got message ${message.type} from ${remotePeerId}`); + this.logger("message", message, remotePeerId); + // Check if we are listening for this ID + if (message.id) { + var msgId = message.id; + if (this._idListeners[msgId]) { + this._idListeners[msgId](message); + this.removeIdListener(msgId); + } + } + if (message === undefined || message.type === undefined) { + this.logger("Message is invalid!", message, typeof message); + return; + } + switch (message.type) { + case "ping": + this.handlePing(message, remotePeerId); + break; + case "pong": + this.handlePong(message, remotePeerId); + break; + case "subscribe": + this.handleSubscribe(message, remotePeerId); + break; + case "get": + this.handleGet(message, remotePeerId); + break; + case "put": + this.handlePut(message, remotePeerId); + break; + case "crdtPut": + this.handleCrdtPut(message, remotePeerId); + break; + case "crdtGet": + this.handleCrdtGet(message, remotePeerId); + break; + case "query": + this.handleQuery(message, remotePeerId); + break; + case "crdt": + this.handleCrdt(message, remotePeerId); + break; + case "function": + this.handleFunction(message, remotePeerId); + break; + default: + break; + } +} +exports.default = toolDbClientOnMessage; - var x = a.toRed(red).redPow(d); - if (x.cmp(rone) === 0 || x.cmp(rn1) === 0) - continue; +},{}],278:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var _1 = require("."); +/** + * Triggers a GET request to other peers. If the data is available locally it will return that instead. + * @param key key of the data + * @param userNamespaced If this key bolongs to a user or its public. Making it private will enforce validation for our public key and signatures. + * @param timeout Max time to wait for remote. + * @returns Promise + */ +function toolDbCrdtGet(key, userNamespaced, timeoutMs) { + var _this = this; + if (userNamespaced === void 0) { userNamespaced = false; } + if (timeoutMs === void 0) { timeoutMs = 1000; } + return new Promise(function (resolve, reject) { + var _a, _b; + if (userNamespaced && ((_a = _this.user) === null || _a === void 0 ? void 0 : _a.pubKey) === undefined) { + reject(new Error("You are not authorized yet!")); + return; + } + var finalKey = userNamespaced ? ":" + ((_b = _this.user) === null || _b === void 0 ? void 0 : _b.pubKey) + "." + key : key; + _this.logger("CRDT GET > " + finalKey); + var msgId = (0, _1.textRandom)(10); + var cancelTimeout = setTimeout(function () { + _this.loadCrdtDocument(finalKey).then(function (data) { + if (data) { + try { + _this.removeIdListener(msgId); + resolve(data); + } + catch (e) { + resolve(null); + } + } + else { + resolve(null); + } + }); + }, timeoutMs); + _this.addIdListener(msgId, function (msg) { + _this.logger("CRDT GET RECV > " + finalKey, msg); + clearTimeout(cancelTimeout); + if (msg.type === "crdt") { + resolve(msg.doc); + } + }); + // Do get + _this.network.sendToAll({ + type: "crdtGet", + to: [], + key: finalKey, + id: msgId, + }); + }); +} +exports.default = toolDbCrdtGet; - for (var i = 1; i < s; i++) { - x = x.redSqr(); +},{".":262}],279:[function(require,module,exports){ +"use strict"; +var __assign = (this && this.__assign) || function () { + __assign = Object.assign || function(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) + t[p] = s[p]; + } + return t; + }; + return __assign.apply(this, arguments); +}; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +var _1 = require("."); +var proofOfWork_1 = __importDefault(require("./utils/proofOfWork")); +var signData_1 = __importDefault(require("./utils/signData")); +/** + * Triggers a PUT request to other peers. + * @param key key where we want to put the data at. + * @param value Data we want to any (any type) + * @param userNamespaced If this key bolongs to a user or its public. Making it private will enforce validation for our public key and signatures. + * @returns Promise + */ +function toolDbCrdtPut(key, value, userNamespaced) { + var _this = this; + if (userNamespaced === void 0) { userNamespaced = false; } + return new Promise(function (resolve, reject) { + if (key.includes(".")) { + // Dots are used as a delimitator character between bublic keys and the key of the user's data + reject(new Error("Key cannot include dots!; " + key)); + return; + } + if (!_this.user) { + reject(new Error("You need to log in before you can PUT.")); + return; + } + var timestamp = new Date().getTime(); + var encodedData = JSON.stringify(value.map(_1.uint8ToBase64)); + var dataString = "" + encodedData + _this.user.pubKey + timestamp; + // WORK + (0, proofOfWork_1.default)(dataString, _this.options.pow) + .then(function (_a) { + var _b; + var hash = _a.hash, nonce = _a.nonce; + if ((_b = _this.user) === null || _b === void 0 ? void 0 : _b.keys) { + // Sign our value + (0, signData_1.default)(hash, _this.user.keys.signKeys.privateKey) + .then(function (signature) { return __awaiter(_this, void 0, void 0, function () { + var data, finalMessage; + var _a, _b; + return __generator(this, function (_c) { + data = { + k: userNamespaced ? ":" + ((_a = this.user) === null || _a === void 0 ? void 0 : _a.pubKey) + "." + key : key, + p: ((_b = this.user) === null || _b === void 0 ? void 0 : _b.pubKey) || "", + n: nonce, + t: timestamp, + h: hash, + s: (0, _1.arrayBufferToBase64)(signature), + v: encodedData, + }; + this.logger("PUT CRDT > " + key, data); + finalMessage = __assign({ type: "crdtPut", id: (0, _1.textRandom)(10), to: [] }, data); + this.network.sendToAll(finalMessage); + resolve(finalMessage); + return [2 /*return*/]; + }); + }); }) + .catch(reject); + } + }) + .catch(reject); + }); +} +exports.default = toolDbCrdtPut; - if (x.cmp(rone) === 0) - return x.fromRed().subn(1).gcd(n); - if (x.cmp(rn1) === 0) - break; - } +},{".":262,"./utils/proofOfWork":324,"./utils/signData":328}],280:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var _1 = require("."); +/** + * Triggers a FUNCTION request to other peers. If the function executes sucessfully it will return code "OK" + * @param function function name + * @param args arguments for the function + * @param timeout Max time to wait for remote. + * @returns Promise + */ +function toolDbFunction(fName, args, timeoutMs) { + var _this = this; + if (timeoutMs === void 0) { timeoutMs = 10000; } + return new Promise(function (resolve, reject) { + _this.logger("FUNCTION > " + fName); + var msgId = (0, _1.textRandom)(10); + var cancelTimeout = setTimeout(function () { + resolve({ return: "Timed out", code: "ERR" }); + }, timeoutMs); + _this.addIdListener(msgId, function (msg) { + _this.logger("FUNCTION RECV > " + fName, msg); + clearTimeout(cancelTimeout); + if (msg.type === "functionReturn") { + resolve({ return: msg.return, code: msg.code }); + } + }); + // Do get + _this.network.sendToAll({ + type: "function", + to: [], + function: fName, + args: args, + id: msgId, + }); + }); +} +exports.default = toolDbFunction; - if (i === s) { - x = x.redSqr(); - return x.fromRed().subn(1).gcd(n); - } - } +},{".":262}],281:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var _1 = require("."); +/** + * Triggers a GET request to other peers. If the data is available locally it will return that instead. + * @param key key of the data + * @param userNamespaced If this key bolongs to a user or its public. Making it private will enforce validation for our public key and signatures. + * @param timeout Max time to wait for remote. + * @returns Promise + */ +function toolDbGet(key, userNamespaced, timeoutMs) { + var _this = this; + if (userNamespaced === void 0) { userNamespaced = false; } + if (timeoutMs === void 0) { timeoutMs = 1000; } + return new Promise(function (resolve, reject) { + var _a, _b; + if (userNamespaced && ((_a = _this.user) === null || _a === void 0 ? void 0 : _a.pubKey) === undefined) { + reject(new Error("You are not authorized yet!")); + return; + } + var finalKey = userNamespaced ? ":" + ((_b = _this.user) === null || _b === void 0 ? void 0 : _b.pubKey) + "." + key : key; + _this.logger("GET > " + finalKey); + var msgId = (0, _1.textRandom)(10); + var cancelTimeout = setTimeout(function () { + _this.store.get(finalKey, function (err, data) { + if (data) { + try { + var message = JSON.parse(data); + resolve(message.v); + } + catch (e) { + resolve(null); + } + } + else { + resolve(null); + } + }); + }, timeoutMs); + _this.addIdListener(msgId, function (msg) { + _this.logger("GET RECV > " + finalKey, msg); + clearTimeout(cancelTimeout); + if (msg.type === "put") { + resolve(msg.v); + } + }); + _this.store.get(finalKey, function (err, data) { + if (data) { + try { + var val = JSON.parse(data).v; + clearTimeout(cancelTimeout); + _this.removeIdListener(msgId); + resolve(val); + } + catch (e) { + // do nothing + } + } + }); + // Do get + _this.network.sendToAll({ + type: "get", + to: [], + key: finalKey, + id: msgId, + }); + }); +} +exports.default = toolDbGet; - return false; -}; +},{".":262}],282:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +function toolDbGetPubKey() { + if (this.pubKey === "" || this.pubKey === undefined) { + throw new Error("You are not authorized yet."); + } + return this.pubKey; +} +exports.default = toolDbGetPubKey; -},{"bn.js":300,"brorand":92}],300:[function(require,module,exports){ -arguments[4][47][0].apply(exports,arguments) -},{"buffer":93,"dup":47}],301:[function(require,module,exports){ -module.exports = assert; +},{}],283:[function(require,module,exports){ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +var encodeKeyString_1 = __importDefault(require("./utils/crypto/encodeKeyString")); +var exportKey_1 = __importDefault(require("./utils/crypto/exportKey")); +var randomAnimal_1 = __importDefault(require("./utils/randomAnimal")); +function toolDbKeysSignIn(keys, username) { + var _this = this; + return (0, exportKey_1.default)("spki", keys.signKeys.publicKey) + .then(function (skpub) { return (0, encodeKeyString_1.default)(skpub); }) + .then(function (pubKey) { + _this.user = { + keys: keys, + name: username || "Anonymous " + (0, randomAnimal_1.default)(), + pubKey: pubKey, + }; + return keys; + }); +} +exports.default = toolDbKeysSignIn; -function assert(val, msg) { - if (!val) - throw new Error(msg || 'Assertion failed'); -} +},{"./utils/crypto/encodeKeyString":307,"./utils/crypto/exportKey":310,"./utils/randomAnimal":325}],284:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = function (d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; + return extendStatics(d, b); + }; + return function (d, b) { + if (typeof b !== "function" && b !== null) + throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +var __assign = (this && this.__assign) || function () { + __assign = Object.assign || function(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) + t[p] = s[p]; + } + return t; + }; + return __assign.apply(this, arguments); +}; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +var ws_1 = __importDefault(require("ws")); +var _1 = require("."); +var arrayBufferToHex_1 = __importDefault(require("./utils/arrayBufferToHex")); +var waitFor_1 = __importDefault(require("./utils/waitFor")); +var defaultTrackerUrls = [ + "wss://tracker.webtorrent.dev", + "wss://tracker.openwebtorrent.com", + "wss://tracker.files.fm:7073/announce", + "wss://tooldb-tracker.herokuapp.com/", + //"wss://tracker.fastcast.nz/announce", + //"wss://tracker.btorrent.xyz/announce", + //"wss://tracker.webtorrent.io/announce", + //"wss://spacetradersapi-chatbox.herokuapp.com:443/announce", +]; +var ToolDbNetwork = /** @class */ (function (_super) { + __extends(ToolDbNetwork, _super); + function ToolDbNetwork(db) { + var _this_1 = _super.call(this, db) || this; + _this_1._window = typeof window === "undefined" ? undefined : window; + _this_1.isNode = typeof jest !== "undefined" || typeof window === "undefined"; + _this_1.isWebWorker = typeof window === "undefined" && + typeof self !== "undefined" && + self.document === undefined; + _this_1.wss = !_this_1.isNode && !_this_1.isWebWorker && _this_1._window + ? _this_1._window.WebSocket || + _this_1._window.webkitWebSocket || + _this_1._window.mozWebSocket + : _this_1.isWebWorker + ? WebSocket + : ws_1.default; + _this_1.sockets = {}; + _this_1.socketListeners = {}; + _this_1.serverPeerData = {}; + _this_1.serversBlacklist = []; + _this_1.serversFinding = []; + _this_1.trackerUrls = defaultTrackerUrls; // .slice(0, 2); + _this_1.handledOffers = {}; + _this_1._awaitingConnections = {}; + _this_1.server = null; + // We need to create a queue to handle a situation when we need + // to contact a server, but we havent connected to it yet. + _this_1._messageQueue = []; + _this_1.removeFromAwaiting = function (pubkey) { + if (_this_1._awaitingConnections[pubkey]) { + delete _this_1._awaitingConnections[pubkey]; + } + }; + /** + * Makes a websocket connection to a tracker + */ + _this_1.makeSocket = function (url) { + return new Promise(function (resolve) { + if (!_this_1.sockets[url]) { + // this.tooldb.logger("begin tracker connection " + url); + _this_1.socketListeners[url] = _this_1.onSocketMessage; + try { + var socket_1 = new _this_1.wss(url); + _this_1.sockets[url] = socket_1; + // eslint-disable-next-line @typescript-eslint/no-this-alias + var _this = _this_1; + socket_1.onopen = function () { + // _this.tooldb.logger("tracker connected " + url); + resolve(this); + }; + socket_1.onmessage = function (e) { return _this_1.socketListeners[url](socket_1, e); }; + // eslint-disable-next-line func-names + socket_1.onerror = function () { + // removing trackers just because the error event seems like a mistake + // trackers can get disconnected and be absolutely healthy. + // const index = this.trackerUrls.indexOf(url); + // this.trackerUrls.splice(index, 1); + delete _this_1.sockets[url]; + resolve(null); + }; + socket_1.onclose = function () { + delete _this_1.sockets[url]; + // this.tooldb.logger("tracker closed " + url); + }; + } + catch (e) { + // this.tooldb.logger("makeSocket error " + url, e); + resolve(null); + } + } + else { + resolve(_this_1.sockets[url]); + } + }); + }; + /* + * Make a serverPeerData object from our keys + */ + _this_1.getServerPeerData = function () { + return new Promise(function (resolve, reject) { + var _a, _b; + if ((_a = _this_1.tooldb.options.defaultKeys) === null || _a === void 0 ? void 0 : _a.privateKey) { + (0, _1.signData)(_this_1.tooldb.options.host, (_b = _this_1.tooldb.options.defaultKeys) === null || _b === void 0 ? void 0 : _b.privateKey).then(function (signature) { + var data = { + host: _this_1.tooldb.options.host, + port: _this_1.tooldb.options.port, + ssl: _this_1.tooldb.options.ssl, + name: _this_1.tooldb.options.serverName, + pubKey: _this_1.tooldb.getPubKey(), + signature: (0, arrayBufferToHex_1.default)(signature), + }; + resolve(data); + }); + } + else { + reject(); + } + }); + }; + /** + * Announce ourselves to a tracker (send "announce") + */ + _this_1.announce = function (socket, infoHash) { return __awaiter(_this_1, void 0, void 0, function () { + var pubKey, message; + return __generator(this, function (_a) { + pubKey = this.getClientAddress(); + // this.tooldb.logger("announce", infoHash, pubKey); + if (pubKey) { + if (this.tooldb.options.server) { + this.getServerPeerData().then(function (offer) { + var offers = [0, 1, 2].map(function (n) { + return { + offer: { sdp: JSON.stringify(offer), type: "offer" }, + offer_id: (0, _1.textRandom)(20), + }; + }); + // this.tooldb.logger("announce offer", offer); + var message = { + action: "announce", + info_hash: infoHash, + peer_id: pubKey.slice(-20), + numwant: 1, + offers: offers, + }; + socket.send(JSON.stringify(message)); + }); + } + else { + message = { + action: "announce", + info_hash: infoHash, + peer_id: pubKey.slice(-20), + numwant: 1, + }; + socket.send(JSON.stringify(message)); + // this.tooldb.logger("announce message", message); + } + } + return [2 /*return*/]; + }); + }); }; + /** + * Announce ourselves to all trackers + */ + _this_1.announceAll = function () { return __awaiter(_this_1, void 0, void 0, function () { + var infoHash; + var _this_1 = this; + return __generator(this, function (_a) { + infoHash = this.codeToHash(this.tooldb.getPubKey()); + // this.tooldb.logger(`announce all start`); + this.trackerUrls.forEach(function (url, index) { return __awaiter(_this_1, void 0, void 0, function () { + var socket; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4 /*yield*/, this.makeSocket(url)]; + case 1: + socket = _a.sent(); + //this.tooldb.logger(" ok tracker " + url); + // this.tooldb.logger("socket", url, index); + if (socket && socket.readyState === 1) { + //this.tooldb.logger("announce to " + url); + this.announce(socket, infoHash); + } + return [2 /*return*/]; + } + }); + }); }); + return [2 /*return*/]; + }); + }); }; + /** + * Announce on trackers for a server + * Connects to it if found + */ + _this_1.findServer = function (serverKey) { return __awaiter(_this_1, void 0, void 0, function () { + var infoHash_1; + var _this_1 = this; + return __generator(this, function (_a) { + if (!this.serversFinding.includes(serverKey)) { + this.serversFinding.push(serverKey); + infoHash_1 = this.codeToHash(serverKey); + this.tooldb.logger("findServer: \"" + serverKey + "\" (" + infoHash_1 + ")"); + this.trackerUrls.forEach(function (url) { return __awaiter(_this_1, void 0, void 0, function () { + var socket; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4 /*yield*/, this.makeSocket(url)]; + case 1: + socket = _a.sent(); + // this.tooldb.logger(`socket:`, socket, url, socket?.readyState); + if (socket && socket.readyState === 1) { + this.announce(socket, infoHash_1); + } + return [2 /*return*/]; + } + }); + }); }); + } + return [2 /*return*/]; + }); + }); }; + _this_1.stopAnnounce = function () { + Object.values(_this_1.sockets).forEach(function (socket) { + if (socket) { + socket.terminate(); + socket.close(); + } + }); + if (_this_1.announceInterval) { + clearInterval(_this_1.announceInterval); + } + }; + /** + * Handle the tracker messages + */ + _this_1.onSocketMessage = function (socket, e) { return __awaiter(_this_1, void 0, void 0, function () { + var val, failure, serverData_1; + var _a; + return __generator(this, function (_b) { + try { + val = JSON.parse(e.data); + // this.tooldb.logger("onSocketMessage", socket.url, val); + } + catch (_e) { + this.tooldb.logger("Received malformed JSON", e.data); + return [2 /*return*/]; + } + failure = val["failure reason"]; + if (failure) { + // this.tooldb.logger(`${e.origin}: torrent tracker failure (${failure})`); + return [2 /*return*/]; + } + if (val.peer_id && val.peer_id === ((_a = this.getClientAddress()) === null || _a === void 0 ? void 0 : _a.slice(-20))) { + // this.tooldb.logger("Peer ids mismatch", val.peer_id, selfId); + return [2 /*return*/]; + } + if (val.offer && val.offer_id) { + if (this.handledOffers[val.offer_id]) { + return [2 /*return*/]; + } + this.handledOffers[val.offer_id] = true; + serverData_1 = JSON.parse(val.offer.sdp); + if (this.tooldb.serverPeers.filter(function (s) { return s.pubkey === serverData_1.pubKey; }) + .length === 0 && + !this._awaitingConnections[serverData_1.pubKey] && + !this.serverPeerData[serverData_1.pubKey] && + this.serversBlacklist.indexOf(serverData_1.pubKey) === -1) { + console.log("Now we connect to ", serverData_1); + this.connectTo(serverData_1); + } + else { + // we already connected, unplug all trackers/unsubscribe + } + return [2 /*return*/]; + } + return [2 /*return*/]; + }); + }); }; + /** + * Open a connection to a server + * @param url URL of the server (including port) + * @returns websocket + */ + _this_1.connectTo = function (serverPeer) { + _this_1.tooldb.logger("connectTo:", serverPeer); + try { + var wsUrl = serverPeer.ssl + ? "wss://" + serverPeer.host + : "ws://" + serverPeer.host + ":" + serverPeer.port; + var wss_1 = new _this_1.wss(wsUrl); + var clientId_1 = serverPeer.pubKey; + // this.serverPeers.push(serverPeer); + // Unlike other network adapters, we can just use the public key + // to identify connections. + // Therefore, we dont have to wait for a pong message to + // initialize these internal functions + _this_1.isClientConnected[serverPeer.pubKey] = function () { + return wss_1.readyState === wss_1.OPEN; + }; + _this_1.clientSocket[serverPeer.pubKey] = wss_1; + _this_1.clientToSend[serverPeer.pubKey] = function (_msg) { + wss_1.send(_msg); + }; + var previousConnection = _this_1._awaitingConnections[serverPeer.pubKey]; + if (previousConnection) { + // this.tooldb.logger("previousConnection"); + _this_1._awaitingConnections[serverPeer.pubKey].socket = wss_1; + } + else { + // this.tooldb.logger("new connection"); + _this_1._awaitingConnections[serverPeer.pubKey] = { + socket: wss_1, + tries: 0, + defer: null, + server: __assign({}, serverPeer), + }; + } + wss_1.onclose = function (_error) { + _this_1.tooldb.logger("wss.onclose", serverPeer); + _this_1.checkDisconnetion(); + if (_this_1.serversBlacklist.indexOf(serverPeer.pubKey) === -1) { + _this_1.reconnect(serverPeer.pubKey); + } + }; + wss_1.onerror = function (_error) { + var _a; + _this_1.tooldb.logger("wss.onerror", serverPeer); + _this_1.checkDisconnetion(); + if (((_a = _error === null || _error === void 0 ? void 0 : _error.error) === null || _a === void 0 ? void 0 : _a.code) !== "ETIMEDOUT" && + _this_1.serversBlacklist.indexOf(serverPeer.pubKey) === -1) { + _this_1.reconnect(serverPeer.pubKey); + } + }; + wss_1.onopen = function () { + _this_1.removeFromAwaiting(serverPeer.pubKey); + _this_1.tooldb.logger("Connected to " + serverPeer.host + ":" + serverPeer.port + " sucessfully."); + // hi peer + _this_1.craftPingMessage().then(function (msg) { + wss_1.send(msg); + }); + _this_1.serverPeerData[serverPeer.pubKey] = serverPeer; + }; + wss_1.onmessage = function (msg) { + if (!msg) { + return; + } + _this_1.onClientMessage(msg.data, clientId_1, function (id) { + clientId_1 = id; + }); + }; + return wss_1; + } + catch (e) { + _this_1.tooldb.logger("onconnect err", e); + } + return undefined; + }; + _this_1.reconnect = function (pubkey) { + var connection = _this_1._awaitingConnections[pubkey]; + if (connection) { + if (connection.defer) { + clearTimeout(connection.defer); + } + _this_1.tooldb.logger("tries: " + connection.tries); + if (connection.tries < _this_1.tooldb.options.maxRetries) { + var defer = function () { + _this_1._awaitingConnections[pubkey].tries += 1; + _this_1.tooldb.logger("connection to " + connection.server.host + ":" + connection.server.port + " retry in " + connection.tries * 2 + " seconds."); + setTimeout(function () { + _this_1.connectTo(connection.server); + }, connection.tries * 2000); + }; + connection.defer = setTimeout(defer, _this_1.tooldb.options.wait); + } + else { + _this_1.tooldb.logger("connection attempts to " + connection.server.host + ":" + connection.server.port + " exceeded,"); + _this_1.removeFromAwaiting(pubkey); + } + } + else { + _this_1.connectTo(_this_1.serverPeerData[pubkey]); + } + }; + _this_1.disconnect = function (pubKey) { + _this_1.tooldb.logger("disconnecting from " + pubKey); + var wss = _this_1.clientSocket[pubKey]; + if (wss && wss.readyState === wss.OPEN) { + wss.close(); + wss.onclose = function () { + _this_1.tooldb.logger("disconnected from " + pubKey + " sucessfully"); + }; + } + _this_1.removeFromAwaiting(pubKey); + _this_1.checkDisconnetion(); + }; + setInterval(function () { + _this_1.tryExecuteMessageQueue(); + }, 500); + // eslint-disable-next-line @typescript-eslint/no-this-alias + var _this = _this_1; + if (_this.tooldb.options.server) { + (0, waitFor_1.default)(function () { + try { + return _this.tooldb.getPubKey() !== undefined; + } + catch (_a) { + return false; + } + }).then(function () { + // Announce every 10 seconds indefinitely + setTimeout(function () { + _this.announceInterval = setInterval(_this.announceAll, 10000); + _this.announceAll(); + }, 500); + }); + } + // Basically the same as the WS network adapter + // Only for Node! + if (_this_1.tooldb.options.server && _this_1.isNode) { + _this_1.server = new ws_1.default.Server({ + port: _this_1.tooldb.options.port, + server: _this_1.tooldb.options.httpServer, + }); + _this_1.server.on("connection", function (socket) { + var clientId = null; + socket.on("close", function () { + if (clientId) { + _this_1.onClientDisconnect(clientId); + } + }); + socket.on("error", function () { + if (clientId) { + _this_1.onClientDisconnect(clientId); + } + }); + socket.on("message", function (message) { + _this_1.onClientMessage(message, clientId || "", function (id) { + clientId = id; + _this_1.isClientConnected[id] = function () { + return socket.readyState === socket.OPEN; + }; + _this_1.clientSocket[id] = socket; + _this_1.clientToSend[id] = function (_msg) { + socket.send(_msg); + }; + }); + }); + }); + } + return _this_1; + } + Object.defineProperty(ToolDbNetwork.prototype, "messageQueue", { + get: function () { + return this._messageQueue; + }, + enumerable: false, + configurable: true + }); + ToolDbNetwork.prototype.checkDisconnetion = function () { + if (Object.values(this.clientSocket).every(function (s) { + return s.readyState !== s.OPEN; + })) { + this.tooldb.onDisconnect(); + this.tooldb.isConnected = false; + } + }; + ToolDbNetwork.prototype.pushToMessageQueue = function (msg, to) { + this._messageQueue.push({ + message: msg, + time: Date.now(), + to: to, + }); + }; + ToolDbNetwork.prototype.codeToHash = function (code) { + return (0, _1.sha1)(code).slice(-20); + }; + ToolDbNetwork.prototype.sendToAll = function (msg, crossServerOnly) { + if (crossServerOnly === void 0) { crossServerOnly = false; } + // this.tooldb.logger("sendToAll", msg, crossServerOnly); + if (crossServerOnly) { + this.sendToAllServers(msg); + } + else { + this.pushToMessageQueue(msg, []); + this.tryExecuteMessageQueue(); + } + }; + ToolDbNetwork.prototype.sendToClientId = function (clientId, msg) { + // this.tooldb.logger("sendToClientId", clientId, msg); + this.pushToMessageQueue(msg, [clientId]); + this.tryExecuteMessageQueue(); + }; + ToolDbNetwork.prototype.sendToAllServers = function (msg) { + var _this_1 = this; + // this.tooldb.logger("sendToAllServers", msg); + var serverPeersList = this.tooldb.serverPeers + .map(function (s) { return s.pubkey; }) + .filter(function (s) { return s !== _this_1.tooldb.getPubKey(); }); + if (serverPeersList.length > 0) { + this.pushToMessageQueue(msg, serverPeersList); + } + this.tryExecuteMessageQueue(); + }; + ToolDbNetwork.prototype.tryExecuteMessageQueue = function () { + var _this_1 = this; + var sentMessageIDs = []; + var messagesToDelete = []; + var pubKey = this.getClientAddress(); + this._messageQueue.forEach(function (q) { + var message = q.message; + if (q.time + 1000 * 60 < Date.now()) { + messagesToDelete.push(message.id); + } + else { + if (pubKey && !message.to.includes(pubKey)) { + message.to.push(pubKey); + } + var finalMessageString_1 = JSON.stringify(message); + if (q.to.length > 0) { + // Send only to select clients + q.to.forEach(function (toClient) { + if (!message.to.includes(toClient) && + _this_1.isClientConnected[toClient] && + _this_1.isClientConnected[toClient]()) { + // this.tooldb.logger("Sending to client", toClient); + _this_1.clientToSend[toClient](finalMessageString_1); + if (sentMessageIDs.indexOf(message.id) === -1) { + sentMessageIDs.push(message.id); + } + } + }); + } + else { + // send to all currently connected clients + Object.keys(_this_1.clientToSend).forEach(function (toClient) { + if (!message.to.includes(toClient) && + _this_1.isClientConnected[toClient] && + _this_1.isClientConnected[toClient]()) { + _this_1.clientToSend[toClient](finalMessageString_1); + if (sentMessageIDs.indexOf(message.id) === -1) { + sentMessageIDs.push(message.id); + } + } + }); + } + } + }); + sentMessageIDs.forEach(function (id) { + var index = _this_1._messageQueue.findIndex(function (msg) { return msg.message.id === id; }); + _this_1._messageQueue.splice(index, 1); + }); + messagesToDelete.forEach(function (id) { + var index = _this_1._messageQueue.findIndex(function (msg) { return msg.message.id === id; }); + _this_1._messageQueue.splice(index, 1); + }); + }; + return ToolDbNetwork; +}(_1.ToolDbNetworkAdapter)); +exports.default = ToolDbNetwork; -assert.equal = function assertEqual(l, r, msg) { - if (l != r) - throw new Error(msg || ('Assertion failed: ' + l + ' != ' + r)); -}; +},{".":262,"./utils/arrayBufferToHex":296,"./utils/waitFor":336,"ws":428}],285:[function(require,module,exports){ +"use strict"; +var __assign = (this && this.__assign) || function () { + __assign = Object.assign || function(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) + t[p] = s[p]; + } + return t; + }; + return __assign.apply(this, arguments); +}; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +var _1 = require("."); +var proofOfWork_1 = __importDefault(require("./utils/proofOfWork")); +var signData_1 = __importDefault(require("./utils/signData")); +/** + * Triggers a PUT request to other peers. + * @param key key where we want to put the data at. + * @param value Data we want to any (any type) + * @param userNamespaced If this key bolongs to a user or its public. Making it private will enforce validation for our public key and signatures. + * @returns Promise + */ +function toolDbPut(key, value, userNamespaced) { + var _this = this; + if (userNamespaced === void 0) { userNamespaced = false; } + return new Promise(function (resolve, reject) { + if (key.includes(".")) { + // Dots are used as a delimitator character between bublic keys and the key of the user's data + reject(new Error("Key cannot include dots!; " + key)); + return; + } + if (!_this.user) { + reject(new Error("You need to log in before you can PUT.")); + return; + } + var timestamp = new Date().getTime(); + var dataString = "" + JSON.stringify(value) + _this.user.pubKey + timestamp; + // WORK + (0, proofOfWork_1.default)(dataString, _this.options.pow) + .then(function (_a) { + var _b; + var hash = _a.hash, nonce = _a.nonce; + if ((_b = _this.user) === null || _b === void 0 ? void 0 : _b.keys) { + // Sign our value + (0, signData_1.default)(hash, _this.user.keys.signKeys.privateKey) + .then(function (signature) { return __awaiter(_this, void 0, void 0, function () { + var finalKey, data, finalMessage; + var _a, _b; + return __generator(this, function (_c) { + finalKey = userNamespaced + ? ":" + ((_a = this.user) === null || _a === void 0 ? void 0 : _a.pubKey) + "." + key + : key; + data = { + k: finalKey, + p: ((_b = this.user) === null || _b === void 0 ? void 0 : _b.pubKey) || "", + n: nonce, + t: timestamp, + h: hash, + s: (0, _1.arrayBufferToBase64)(signature), + v: value, + }; + this.store.put(finalKey, JSON.stringify(data), function (err, data) { + // + }); + this.logger("PUT > " + key, data); + finalMessage = __assign({ type: "put", id: (0, _1.textRandom)(10), to: [] }, data); + this.network.sendToAll(finalMessage); + resolve(finalMessage); + return [2 /*return*/]; + }); + }); }) + .catch(reject); + } + }) + .catch(reject); + }); +} +exports.default = toolDbPut; -},{}],302:[function(require,module,exports){ -'use strict'; +},{".":262,"./utils/proofOfWork":324,"./utils/signData":328}],286:[function(require,module,exports){ +"use strict"; +var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { + if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { + if (ar || !(i in from)) { + if (!ar) ar = Array.prototype.slice.call(from, 0, i); + ar[i] = from[i]; + } + } + return to.concat(ar || Array.prototype.slice.call(from)); +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +var lodash_1 = __importDefault(require("lodash")); +var _1 = require("."); +/** + * Triggers a QUERY request to other peers. + * @param key start of the key + * @param userNamespaced If this key bolongs to a user or its public. + * @param timeout Max time to wait for remote. + * @param remoteOnly Only query remote peers, do not query local store. + * @returns Promise + */ +function toolDbQueryKeys(key, userNamespaced, timeoutMs, remoteOnly) { + var _this = this; + if (userNamespaced === void 0) { userNamespaced = false; } + if (timeoutMs === void 0) { timeoutMs = 1000; } + if (remoteOnly === void 0) { remoteOnly = false; } + return new Promise(function (resolve, reject) { + var _a, _b; + if (userNamespaced && ((_a = _this.user) === null || _a === void 0 ? void 0 : _a.pubKey) === undefined) { + reject(new Error("You are not authorized yet!")); + return; + } + if (!userNamespaced && key.length < 3) { + reject(new Error("Query key is too short")); + return; + } + // if (!userNamespaced && key.startsWith(":")) { + // reject( + // new Error( + // "User namespace queries should use the userNamespaced argument" + // ) + // ); + // return; + // } + var finalKey = userNamespaced ? ":" + ((_b = _this.user) === null || _b === void 0 ? void 0 : _b.pubKey) + "." + key : key; + _this.logger("QUERY > " + finalKey); + var msgId = (0, _1.textRandom)(10); + var foundKeys = []; + var timeout; + var gotLocalKeys = remoteOnly; + if (remoteOnly === false) { + _this.store.query(finalKey).then(function (localKeys) { + gotLocalKeys = true; + foundKeys = __spreadArray(__spreadArray([], foundKeys, true), localKeys, true); + timeout = setTimeout(finishListening, timeoutMs); + }); + } + var finishListening = function () { + resolve(lodash_1.default.uniq(foundKeys)); + }; + _this.addIdListener(msgId, function (msg) { + _this.logger("QUERY RECV > " + finalKey, msg); + if (msg.type === "queryAck") { + foundKeys = __spreadArray(__spreadArray([], foundKeys, true), msg.keys, true); + if (timeout) { + clearTimeout(timeout); + } + if (gotLocalKeys === true) { + timeout = setTimeout(finishListening, timeoutMs); + } + } + }); + // Do get + _this.network.sendToAll({ + type: "query", + to: [], + key: finalKey, + id: msgId, + }); + }); +} +exports.default = toolDbQueryKeys; -var utils = exports; +},{".":262,"lodash":239}],287:[function(require,module,exports){ +"use strict"; +var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { + if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { + if (ar || !(i in from)) { + if (!ar) ar = Array.prototype.slice.call(from, 0, i); + ar[i] = from[i]; + } + } + return to.concat(ar || Array.prototype.slice.call(from)); +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +var lodash_1 = __importDefault(require("lodash")); +var textRandom_1 = __importDefault(require("./utils/textRandom")); +/** + * Queries the given server peer for all documents that arent present + * if our local database. + * Returns the number of documents that were synced. + * @param pubKey server public key + * @returns Promise + */ +function toolDbServerSync(pubKey) { + var _this = this; + return new Promise(function (resolve, reject) { + var localKeys = []; + _this.store.query("").then(function (keys) { + localKeys = keys; + queryAllKeys(_this, pubKey).then(function (remoteKeys) { + if (remoteKeys) { + var missingKeys_1 = lodash_1.default.difference(remoteKeys, localKeys); + if (missingKeys_1.length > 0) { + _this.logger("MISSING KEYS > ", missingKeys_1.length); + var msgId = (0, textRandom_1.default)(10); + var synced_1 = 0; + _this.addIdListener(msgId, function (msg) { + _this.logger("SERVER SYNC RECV > ", msg); + if (msg.type === "put") { + synced_1++; + } + if (synced_1 === missingKeys_1.length) { + resolve(synced_1); + } + }); + // Do get + _this.network.sendToClientId(pubKey, { + type: "get", + to: [], + key: missingKeys_1[0], + id: msgId, + }); + } + } + }); + }); + }); +} +exports.default = toolDbServerSync; +function queryAllKeys(tooldb, serverPubKey, timeoutMs) { + if (timeoutMs === void 0) { timeoutMs = 1000; } + return new Promise(function (resolve, reject) { + var _a; + if (((_a = tooldb.user) === null || _a === void 0 ? void 0 : _a.pubKey) === undefined) { + reject(new Error("You are not authorized yet!")); + return; + } + tooldb.logger("QUERY ALL > " + serverPubKey); + var msgId = (0, textRandom_1.default)(10); + var foundKeys = []; + var timeout; + var finishListening = function () { + resolve(lodash_1.default.uniq(foundKeys)); + }; + tooldb.addIdListener(msgId, function (msg) { + tooldb.logger("QUERY ALL RECV > ", msg); + if (msg.type === "queryAck") { + foundKeys = __spreadArray(__spreadArray([], foundKeys, true), msg.keys, true); + if (timeout) { + clearTimeout(timeout); + } + timeout = setTimeout(finishListening, timeoutMs); + } + }); + // Do get + tooldb.network.sendToClientId(serverPubKey, { + type: "query", + to: [], + key: "", + id: msgId, + }); + }); +} -function toArray(msg, enc) { - if (Array.isArray(msg)) - return msg.slice(); - if (!msg) - return []; - var res = []; - if (typeof msg !== 'string') { - for (var i = 0; i < msg.length; i++) - res[i] = msg[i] | 0; - return res; - } - if (enc === 'hex') { - msg = msg.replace(/[^a-z0-9]+/ig, ''); - if (msg.length % 2 !== 0) - msg = '0' + msg; - for (var i = 0; i < msg.length; i += 2) - res.push(parseInt(msg[i] + msg[i + 1], 16)); - } else { - for (var i = 0; i < msg.length; i++) { - var c = msg.charCodeAt(i); - var hi = c >> 8; - var lo = c & 0xff; - if (hi) - res.push(hi, lo); - else - res.push(lo); - } - } - return res; -} -utils.toArray = toArray; +},{"./utils/textRandom":330,"lodash":239}],288:[function(require,module,exports){ +"use strict"; +var __assign = (this && this.__assign) || function () { + __assign = Object.assign || function(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) + t[p] = s[p]; + } + return t; + }; + return __assign.apply(this, arguments); +}; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +var decodeKeyString_1 = __importDefault(require("./utils/crypto/decodeKeyString")); +var decryptWithPass_1 = __importDefault(require("./utils/crypto/decryptWithPass")); +var importKey_1 = __importDefault(require("./utils/crypto/importKey")); +var base64ToUint8_1 = __importDefault(require("./utils/base64ToUint8")); +var catchReturn_1 = __importDefault(require("./utils/catchReturn")); +var fromBase64_1 = __importDefault(require("./utils/fromBase64")); +var sha256_1 = __importDefault(require("./utils/sha256")); +function toolDbSignIn(user, password) { + var _this = this; + return new Promise(function (resolve, reject) { + _this.getData("==" + user, false, 5000) + .then(function (_user) { + if (!_user) { + reject("Could not find user"); + return; + } + if ((0, sha256_1.default)(password) !== _user.pass) { + reject("Invalid password"); + return; + } + (0, decryptWithPass_1.default)((0, fromBase64_1.default)(_user.keys.skpriv), password, (0, base64ToUint8_1.default)(_user.iv)).then(function (decryptedskpriv) { + (0, decryptWithPass_1.default)((0, fromBase64_1.default)(_user.keys.ekpriv), password, (0, base64ToUint8_1.default)(_user.iv)) + .then(function (decryptedekpriv) { + var parsedKeys = __assign(__assign({}, _user.keys), { skpriv: decryptedskpriv || "", ekpriv: decryptedekpriv || "" }); + // const jsonKeys = { + // skpub: parsedKeys.skpub, + // skpriv: parsedKeys.skpriv, + // ekpub: parsedKeys.ekpub, + // ekpriv: parsedKeys.ekpriv, + // }; + // localStorage.setItem("keys", JSON.stringify(jsonKeys)); + function importKeys() { + return __awaiter(this, void 0, void 0, function () { + var skpub, skpriv, ekpub, ekpriv; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4 /*yield*/, (0, importKey_1.default)((0, decodeKeyString_1.default)(parsedKeys.skpub), "spki", "ECDSA", ["verify"]).catch(catchReturn_1.default)]; + case 1: + skpub = _a.sent(); + return [4 /*yield*/, (0, importKey_1.default)((0, decodeKeyString_1.default)(parsedKeys.skpriv), "pkcs8", "ECDSA", ["sign"]).catch(catchReturn_1.default)]; + case 2: + skpriv = _a.sent(); + return [4 /*yield*/, (0, importKey_1.default)((0, decodeKeyString_1.default)(parsedKeys.ekpub), "spki", "ECDH", []).catch(catchReturn_1.default)]; + case 3: + ekpub = _a.sent(); + return [4 /*yield*/, (0, importKey_1.default)((0, decodeKeyString_1.default)(parsedKeys.ekpriv), "pkcs8", "ECDH", ["deriveKey", "deriveBits"]).catch(catchReturn_1.default)]; + case 4: + ekpriv = _a.sent(); + return [2 /*return*/, { skpub: skpub, skpriv: skpriv, ekpub: ekpub, ekpriv: ekpriv }]; + } + }); + }); + } + importKeys() + .then(function (_a) { + var skpub = _a.skpub, skpriv = _a.skpriv, ekpub = _a.ekpub, ekpriv = _a.ekpriv; + if (!skpub || !skpriv || !ekpub || !ekpriv) { + reject(new Error("Could not import keys")); + } + else { + var newKeys = { + signKeys: { + publicKey: skpub, + privateKey: skpriv, + }, + encryptionKeys: { + publicKey: ekpub, + privateKey: ekpriv, + }, + }; + _this.user = { + keys: newKeys, + name: user, + pubKey: _user.keys.skpub, + }; + resolve(newKeys); + } + }) + .catch(catchReturn_1.default); + }) + .catch(catchReturn_1.default); + }); + }) + .catch(console.warn); + }); +} +exports.default = toolDbSignIn; -function zero2(word) { - if (word.length === 1) - return '0' + word; - else - return word; -} -utils.zero2 = zero2; +},{"./utils/base64ToUint8":301,"./utils/catchReturn":302,"./utils/crypto/decodeKeyString":303,"./utils/crypto/decryptWithPass":305,"./utils/crypto/importKey":314,"./utils/fromBase64":318,"./utils/sha256":327}],289:[function(require,module,exports){ +"use strict"; +var __assign = (this && this.__assign) || function () { + __assign = Object.assign || function(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) + t[p] = s[p]; + } + return t; + }; + return __assign.apply(this, arguments); +}; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +var _1 = require("."); +var encryptWithPass_1 = __importDefault(require("./utils/crypto/encryptWithPass")); +var generateKeysComb_1 = __importDefault(require("./utils/crypto/generateKeysComb")); +var saveKeysComb_1 = __importDefault(require("./utils/crypto/saveKeysComb")); +var generateIv_1 = __importDefault(require("./utils/generateIv")); +var proofOfWork_1 = __importDefault(require("./utils/proofOfWork")); +var sha256_1 = __importDefault(require("./utils/sha256")); +var signData_1 = __importDefault(require("./utils/signData")); +var toBase64_1 = __importDefault(require("./utils/toBase64")); +var uint8ToBase64_1 = __importDefault(require("./utils/uint8ToBase64")); +function toolDbSignUp(user, password) { + return __awaiter(this, void 0, void 0, function () { + var userRoot; + var _this = this; + return __generator(this, function (_a) { + userRoot = "==" + user; + return [2 /*return*/, new Promise(function (resolve, reject) { + _this.getData(userRoot, false, 3000) + .then(function (data) { + if (data === null) { + (0, generateKeysComb_1.default)() + .then(function (keys) { + if (keys) { + (0, saveKeysComb_1.default)(keys.signKeys, keys.encryptionKeys) + .then(function (savedKeys) { + var iv = (0, generateIv_1.default)(); + var encskpriv = ""; + var encekpriv = ""; + // Encrypt sign key + (0, encryptWithPass_1.default)(savedKeys.skpriv, password, iv) + .then(function (skenc) { + (0, encryptWithPass_1.default)(savedKeys.ekpriv, password, iv) + .then(function (ekenc) { + if (skenc) + encskpriv = skenc; + if (ekenc) + encekpriv = ekenc; + var userData = { + keys: { + skpub: savedKeys.skpub, + skpriv: (0, toBase64_1.default)(encskpriv), + ekpub: savedKeys.ekpub, + ekpriv: (0, toBase64_1.default)(encekpriv), + }, + iv: (0, uint8ToBase64_1.default)(iv), + pass: (0, sha256_1.default)(password), + }; + var timestamp = new Date().getTime(); + var userDataString = "" + JSON.stringify(userData) + savedKeys.skpub + timestamp; + (0, proofOfWork_1.default)(userDataString, 0) + .then(function (_a) { + var hash = _a.hash, nonce = _a.nonce; + (0, signData_1.default)(hash, keys.signKeys.privateKey).then(function (signature) { + var signupMessage = { + k: userRoot, + p: savedKeys.skpub, + n: nonce, + t: timestamp, + h: hash, + s: (0, _1.arrayBufferToBase64)(signature), + v: userData, + }; + _this.logger("SIGNUP PUT > " + userRoot, signupMessage); + var finalMsg = __assign({ type: "put", id: (0, _1.textRandom)(10), to: [] }, signupMessage); + _this.network.sendToAll(finalMsg); + resolve(finalMsg); + }); + }) + .catch(reject); + }) + .catch(reject); + }) + .catch(reject); + }) + .catch(function () { return reject(new Error("")); }); + } + else { + reject(new Error("Could not generate keys")); + } + }) + .catch(function () { return reject(new Error("Could not generate keys")); }); + } + else { + reject(new Error("User already exists!")); + } + }) + .catch(function () { + reject(new Error("Could not fetch user")); + }); + })]; + }); + }); +} +exports.default = toolDbSignUp; -function toHex(msg) { - var res = ''; - for (var i = 0; i < msg.length; i++) - res += zero2(msg[i].toString(16)); - return res; -} -utils.toHex = toHex; +},{".":262,"./utils/crypto/encryptWithPass":309,"./utils/crypto/generateKeysComb":313,"./utils/crypto/saveKeysComb":316,"./utils/generateIv":319,"./utils/proofOfWork":324,"./utils/sha256":327,"./utils/signData":328,"./utils/toBase64":331,"./utils/uint8ToBase64":332}],290:[function(require,module,exports){ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +var _1 = require("."); +var automerge_1 = __importDefault(require("automerge")); +/** + * Subscribe to all PUT updates for this key. + * @param key key of the data + * @param userNamespaced If this key bolongs to a user or its public. Making it private will enforce validation for our public key and signatures. + * @returns Promise + */ +function toolDbSubscribe(key, userNamespaced) { + var _this = this; + if (userNamespaced === void 0) { userNamespaced = false; } + return new Promise(function (resolve, reject) { + var _a, _b; + if (userNamespaced && ((_a = _this.user) === null || _a === void 0 ? void 0 : _a.pubKey) === undefined) { + reject(new Error("You are not authorized yet!")); + return; + } + var finalKey = userNamespaced ? ":" + ((_b = _this.user) === null || _b === void 0 ? void 0 : _b.pubKey) + "." + key : key; + _this.logger("Subscribe > " + finalKey); + var msgId = (0, _1.textRandom)(10); + _this.store.get(finalKey, function (err, data) { + if (data) { + try { + var message = JSON.parse(data); + _this.triggerKeyListener(finalKey, message); + } + catch (e) { + // do nothing + } + } + }); + // console.log("do subscribe", finalKey); + _this.loadCrdtDocument(finalKey, false).then(function (doc) { + if (doc) { + var savedDoc = automerge_1.default.save(doc); + var msg = { + type: "crdt", + key: finalKey, + id: (0, _1.textRandom)(10), + to: [], + doc: (0, _1.uint8ToBase64)(savedDoc), + }; + _this.triggerKeyListener(finalKey, msg); + } + }); + _this.network.sendToAll({ + type: "subscribe", + key: finalKey, + to: [], + id: msgId, + }); + resolve(); + }); +} +exports.default = toolDbSubscribe; -utils.encode = function encode(arr, enc) { - if (enc === 'hex') - return toHex(arr); - else - return arr; -}; +},{".":262,"automerge":81}],291:[function(require,module,exports){ +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; +Object.defineProperty(exports, "__esModule", { value: true }); +var _1 = require("."); +function toolDbVerificationWrapper(data) { + var _this = this; + // This wrapper function adds our custom verification functions to all messages. + return new Promise(function (resolve) { + _this.verifyMessage(data, _this.options.pow).then(function (verified) { return __awaiter(_this, void 0, void 0, function () { + var skipCustom_1; + return __generator(this, function (_a) { + if (verified) { + skipCustom_1 = true; + this._customVerificator.forEach(function (listener) { + if (listener && data.k && data.k.startsWith(listener.key)) { + skipCustom_1 = false; + listener + .fn(data) + .then(function (verified) { + if (verified) { + resolve(_1.VerifyResult.Verified); + } + else { + resolve(_1.VerifyResult.CustomVerificationFailed); + } + }) + .catch(function (e) { + resolve(_1.VerifyResult.CustomVerificationFailed); + }); + } + }); + if (skipCustom_1) { + resolve(verified); + } + } + else { + resolve(_1.VerifyResult.InvalidVerification); + } + return [2 /*return*/]; + }); + }); }); + }); +} +exports.default = toolDbVerificationWrapper; -},{}],303:[function(require,module,exports){ +},{".":262}],292:[function(require,module,exports){ "use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = function (d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; + return extendStatics(d, b); + }; + return function (d, b) { + if (typeof b !== "function" && b !== null) + throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +var __assign = (this && this.__assign) || function () { + __assign = Object.assign || function(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) + t[p] = s[p]; + } + return t; + }; + return __assign.apply(this, arguments); +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; Object.defineProperty(exports, "__esModule", { value: true }); -function getCrypto() { - if (typeof window === "undefined") { - if (typeof self !== "undefined" && self.document === undefined) { - // inside a web worker - return crypto; +exports.KEY_PREFIX = void 0; +var events_1 = __importDefault(require("events")); +var _1 = require("."); +var logger_1 = __importDefault(require("./logger")); +var toolDbGet_1 = __importDefault(require("./toolDbGet")); +var toolDbPut_1 = __importDefault(require("./toolDbPut")); +var toolDbSignIn_1 = __importDefault(require("./toolDbSignIn")); +var toolDbSignUp_1 = __importDefault(require("./toolDbSignUp")); +var toolDbNetwork_1 = __importDefault(require("./toolDbNetwork")); +var toolDbCrdtGet_1 = __importDefault(require("./toolDbCrdtGet")); +var toolDbCrdtPut_1 = __importDefault(require("./toolDbCrdtPut")); +var toolDbGetPubKey_1 = __importDefault(require("./toolDbGetPubKey")); +var toolDbAnonSignIn_1 = __importDefault(require("./toolDbAnonSignIn")); +var toolDbServerSync_1 = __importDefault(require("./toolDbServerSync")); +var toolDbClientOnMessage_1 = __importDefault(require("./toolDbClientOnMessage")); +var toolDbVerificationWrapper_1 = __importDefault(require("./toolDbVerificationWrapper")); +var leveldb_1 = __importDefault(require("./utils/leveldb")); +var indexedb_1 = __importDefault(require("./utils/indexedb")); +var toolDbSubscribe_1 = __importDefault(require("./toolDbSubscribe")); +var toolDbQueryKeys_1 = __importDefault(require("./toolDbQueryKeys")); +var loadCrdtDocument_1 = __importDefault(require("./loadCrdtDocument")); +var toolDbKeysSignIn_1 = __importDefault(require("./toolDbKeysSignIn")); +var handleGet_1 = __importDefault(require("./messageHandlers/handleGet")); +var handlePut_1 = __importDefault(require("./messageHandlers/handlePut")); +var handlePing_1 = __importDefault(require("./messageHandlers/handlePing")); +var handlePong_1 = __importDefault(require("./messageHandlers/handlePong")); +var handleCrdt_1 = __importDefault(require("./messageHandlers/handleCrdt")); +var handleQuery_1 = __importDefault(require("./messageHandlers/handleQuery")); +var handleCrdtGet_1 = __importDefault(require("./messageHandlers/handleCrdtGet")); +var handleCrdtPut_1 = __importDefault(require("./messageHandlers/handleCrdtPut")); +var handleSubscribe_1 = __importDefault(require("./messageHandlers/handleSubscribe")); +var arrayBufferToHex_1 = __importDefault(require("./utils/arrayBufferToHex")); +var handleFunction_1 = __importDefault(require("./messageHandlers/handleFunction")); +var toolDbFunction_1 = __importDefault(require("./toolDbFunction")); +exports.KEY_PREFIX = "3059301306072a8648ce3d020106082a8648ce3d03010703420004"; +var ToolDb = /** @class */ (function (_super) { + __extends(ToolDb, _super); + function ToolDb(options) { + if (options === void 0) { options = {}; } + var _this = _super.call(this) || this; + _this._peers = {}; + _this.logger = logger_1.default; + _this._documents = {}; + _this._pubKey = undefined; + _this.clientOnMessage = toolDbClientOnMessage_1.default; + _this.verifyMessage = _1.verifyMessage; + _this._subscriptions = []; + _this.isConnected = false; + _this._processedIds = {}; + _this._processedOutHashes = {}; + _this.subscribeData = toolDbSubscribe_1.default; + // Emitted when there are no more server peers connected to + _this.onDisconnect = function () { + // + }; + // Emitted when a server peer responds with "pong" + _this.onConnect = function () { + // + }; + _this.onPeerDisconnect = function (peerId) { + // + }; + _this.onPeerConnect = function (peerId) { + // + }; + _this.loadCrdtDocument = loadCrdtDocument_1.default; + _this.getData = toolDbGet_1.default; + _this.putData = toolDbPut_1.default; + _this.putCrdt = toolDbCrdtPut_1.default; + _this.getCrdt = toolDbCrdtGet_1.default; + _this.queryKeys = toolDbQueryKeys_1.default; + _this.doFunction = toolDbFunction_1.default; + _this.getPubKey = toolDbGetPubKey_1.default; + _this.serverSync = toolDbServerSync_1.default; + _this.signIn = toolDbSignIn_1.default; + _this.anonSignIn = toolDbAnonSignIn_1.default; + _this.keysSignIn = toolDbKeysSignIn_1.default; + _this.signUp = toolDbSignUp_1.default; + _this.verify = toolDbVerificationWrapper_1.default; + // All message handlers go here + _this.handlePing = handlePing_1.default; + _this.handlePong = handlePong_1.default; + _this.handleCrdt = handleCrdt_1.default; + _this.handleCrdtGet = handleCrdtGet_1.default; + _this.handleCrdtPut = handleCrdtPut_1.default; + _this.handleGet = handleGet_1.default; + _this.handlePut = handlePut_1.default; + _this.handleQuery = handleQuery_1.default; + _this.handleSubscribe = handleSubscribe_1.default; + _this.handleFunction = handleFunction_1.default; + /** + * id listeners listen for a specific message ID just once + */ + _this._idListeners = {}; + _this.addIdListener = function (id, fn) { + _this._idListeners[id] = fn; + }; + _this.removeIdListener = function (id) { + delete _this._idListeners[id]; + }; + /** + * Server functions allow the server to define functions to be executed by the clients + * It is up to the function creator to specify proper security on these. + * Server functions are meant to execute on data stored on the server, in a way the clients + * dont have to overload the server, use with caution! + * Custom functions are expected to be a Promise that resolves to a string, and arguments are + * passed as an array of values. Type and sanity checking is up to the developer. + */ + _this._functions = {}; + /** + * Key listeners listen for a specific key, as long as the listener remains active + */ + _this._keyListeners = []; + _this.addKeyListener = function (key, fn) { + var newListener = { + key: key, + timeout: null, + fn: fn, + }; + _this._keyListeners.push(newListener); + return _this._keyListeners.length; + }; + _this.removeKeyListener = function (id) { + var _a, _b; + if ((_a = _this._keyListeners[id]) === null || _a === void 0 ? void 0 : _a.timeout) { + clearTimeout(((_b = _this._keyListeners[id]) === null || _b === void 0 ? void 0 : _b.timeout) || undefined); + } + _this._keyListeners[id] = null; + }; + _this.triggerKeyListener = function (key, message) { + // console.warn(`triggerKeyListener ${key}`); + _this._keyListeners.forEach(function (listener) { + if ((listener === null || listener === void 0 ? void 0 : listener.key) === key) { + // console.log(`TRIGGER OK`, message); + if (listener.timeout) { + clearTimeout(listener.timeout); + } + listener.timeout = setTimeout(function () { return listener.fn(message); }, _this.options.triggerDebouce); + } + }); + }; + /** + * Custom verificators can enhance default verification on any key field + */ + _this._customVerificator = []; + _this.addCustomVerification = function (key, fn) { + var newListener = { + key: key, + fn: fn, + }; + _this._customVerificator.push(newListener); + return _this._customVerificator.length; + }; + _this.removeCustomVerification = function (id) { + _this._customVerificator[id] = null; + }; + _this.user = undefined; + _this._options = { + db: "tooldb", + maxRetries: 5, + triggerDebouce: 100, + wait: 2000, + pow: 0, + server: false, + host: "127.0.0.1", + port: 8080, + debug: false, + httpServer: undefined, + networkAdapter: toolDbNetwork_1.default, + storageName: "tooldb", + storageAdapter: typeof window === "undefined" ? leveldb_1.default : indexedb_1.default, + topic: "", + defaultKeys: undefined, + maxPeers: 4, + ssl: false, + serverName: "default-server", + }; + _this._options = __assign(__assign({}, _this.options), options); + if (!_this._options.defaultKeys) { + (0, _1.generateKeyPair)("ECDSA", false).then(function (key) { + if (key.publicKey && key.privateKey) { + _this._options.defaultKeys = key; + (0, _1.exportKey)("spki", key.publicKey).then(function (skpub) { + _this._pubKey = (0, arrayBufferToHex_1.default)(skpub); + if (_this._pubKey.startsWith(exports.KEY_PREFIX)) { + _this._pubKey = _this._pubKey.slice(exports.KEY_PREFIX.length); + } + _this.emit("init", _this._pubKey); + }); + } + }); } else { - // inside node - return require("crypto").webcrypto; + (0, _1.exportKey)("spki", _this._options.defaultKeys.publicKey).then(function (skpub) { + _this._pubKey = (0, arrayBufferToHex_1.default)(skpub); + if (_this._pubKey.startsWith(exports.KEY_PREFIX)) { + _this._pubKey = _this._pubKey.slice(exports.KEY_PREFIX.length); + } + _this.emit("init", _this._pubKey); + }); } + // These could be made to be customizable by setting the variables as public + _this._network = new _this.options.networkAdapter(_this); + _this._store = _this.options.storageAdapter(_this.options.storageName); + return _this; } - // browsers - return window.crypto; -} -exports.default = getCrypto; + Object.defineProperty(ToolDb.prototype, "subscriptions", { + get: function () { + return this._subscriptions; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(ToolDb.prototype, "pubKey", { + get: function () { + return this._pubKey; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(ToolDb.prototype, "processedIds", { + get: function () { + return this._processedIds; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(ToolDb.prototype, "processedOutHashes", { + get: function () { + return this._processedOutHashes; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(ToolDb.prototype, "serverPeers", { + get: function () { + return Object.values(this._peers).filter(function (peer) { return peer.isServer; }); + }, + enumerable: false, + configurable: true + }); + ToolDb.prototype.getUserNamespacedKey = function (key) { + var _a; + return ":" + (((_a = this.user) === null || _a === void 0 ? void 0 : _a.pubKey) || "") + "." + key; + }; + Object.defineProperty(ToolDb.prototype, "functions", { + get: function () { + return this._functions; + }, + enumerable: false, + configurable: true + }); + ToolDb.prototype.addServerFunction = function (functionName, fn) { + this._functions[functionName] = fn; + }; + Object.defineProperty(ToolDb.prototype, "options", { + get: function () { + return this._options; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(ToolDb.prototype, "network", { + get: function () { + return this._network; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(ToolDb.prototype, "peers", { + get: function () { + return this._peers; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(ToolDb.prototype, "store", { + get: function () { + return this._store; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(ToolDb.prototype, "documents", { + get: function () { + return this._documents; + }, + enumerable: false, + configurable: true + }); + return ToolDb; +}(events_1.default)); +exports.default = ToolDb; -},{"crypto":168}],304:[function(require,module,exports){ -(function (global,Buffer){(function (){ +},{".":262,"./loadCrdtDocument":263,"./logger":264,"./messageHandlers/handleCrdt":265,"./messageHandlers/handleCrdtGet":266,"./messageHandlers/handleCrdtPut":267,"./messageHandlers/handleFunction":268,"./messageHandlers/handleGet":269,"./messageHandlers/handlePing":270,"./messageHandlers/handlePong":271,"./messageHandlers/handlePut":272,"./messageHandlers/handleQuery":273,"./messageHandlers/handleSubscribe":274,"./toolDbAnonSignIn":276,"./toolDbClientOnMessage":277,"./toolDbCrdtGet":278,"./toolDbCrdtPut":279,"./toolDbFunction":280,"./toolDbGet":281,"./toolDbGetPubKey":282,"./toolDbKeysSignIn":283,"./toolDbNetwork":284,"./toolDbPut":285,"./toolDbQueryKeys":286,"./toolDbServerSync":287,"./toolDbSignIn":288,"./toolDbSignUp":289,"./toolDbSubscribe":290,"./toolDbVerificationWrapper":291,"./utils/arrayBufferToHex":296,"./utils/indexedb":322,"./utils/leveldb":323,"events":172}],293:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.VerifyResult = void 0; +var VerifyResult; +(function (VerifyResult) { + VerifyResult["CustomVerificationFailed"] = "CustomVerificationFailed"; + VerifyResult["InvalidData"] = "InvalidData"; + VerifyResult["InvalidVerification"] = "InvalidVerification"; + VerifyResult["CantOverwrite"] = "CantOverwrite"; + VerifyResult["InvalidTimestamp"] = "InvalidTimestamp"; + VerifyResult["PubKeyMismatch"] = "PubKeyMismatch"; + VerifyResult["NoProofOfWork"] = "NoProofOfWork"; + VerifyResult["InvalidHashNonce"] = "InvalidHashNonce"; + VerifyResult["InvalidSignature"] = "InvalidSignature"; + VerifyResult["Verified"] = "Verified"; +})(VerifyResult = exports.VerifyResult || (exports.VerifyResult = {})); + +},{}],294:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); + +},{}],295:[function(require,module,exports){ "use strict"; -/* eslint-disable no-undef */ -/* eslint-disable global-require */ -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __exportStar = (this && this.__exportStar) || function(m, exports) { - for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); -}; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); -exports.ToolDb = exports.handleSubscribe = exports.handleQuery = exports.handlePut = exports.handlePong = exports.handlePing = exports.handleGet = exports.handleCrdtPut = exports.handleCrdtGet = exports.handleCrdt = exports.ToolDbNetwork = exports.ToolDbNetworkAdapter = exports.verifyData = exports.saveKeysComb = exports.loadKeysComb = exports.importKey = exports.generateKeysComb = exports.generateKeyPair = exports.generateKeyFromPassword = exports.exportKey = exports.encryptWithPass = exports.encryptData = exports.encodeKeyString = exports.deriveSecret = exports.decryptWithPass = exports.decryptData = exports.decodeKeyString = exports.verifyMessage = exports.uint8ToBase64 = exports.toBase64 = exports.textRandom = exports.stringToArrayBuffer = exports.randomAnimal = exports.generateIv = exports.fromBase64 = exports.base64ToUint8 = exports.base64ToBinaryDocument = exports.base64ToBinaryChange = exports.base64ToArrayBuffer = exports.arrayBufferToString = exports.arrayBufferToBase64 = exports.signData = exports.sha256 = exports.sha1 = exports.uniq = exports.proofOfWork = void 0; -var elliptic_1 = __importDefault(require("elliptic")); -__exportStar(require("./types/tooldb"), exports); -__exportStar(require("./types/message"), exports); -global.Buffer = global.Buffer || require("buffer").Buffer; -if (typeof btoa === "undefined") { - global.btoa = function (str) { - return Buffer.from(str, "binary").toString("base64"); - }; -} -if (typeof atob === "undefined") { - global.atob = function (b64Encoded) { - return Buffer.from(b64Encoded, "base64").toString("binary"); - }; +var arrayBufferToString_1 = __importDefault(require("./arrayBufferToString")); +var toBase64_1 = __importDefault(require("./toBase64")); +function arrayBufferToBase64(arr) { + return (0, toBase64_1.default)((0, arrayBufferToString_1.default)(arr)); } -if (typeof window === "undefined") { - // Only set global crypto if we are in node, not for web workers - if (typeof self !== "undefined" && self.document !== undefined) { - global.crypto = require("crypto").webcrypto; +exports.default = arrayBufferToBase64; + +},{"./arrayBufferToString":297,"./toBase64":331}],296:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +function arrayBufferToHex(buffer) { + var data_view = new DataView(buffer); + var iii; + var len; + var hex = ""; + var c; + for (iii = 0, len = data_view.byteLength; iii < len; iii += 1) { + c = data_view.getUint8(iii).toString(16); + if (c.length < 2) { + c = "0" + c; + } + hex += c; } - global.ecp256 = new elliptic_1.default.ec("p256"); + return hex; } -else { - window.ecp256 = new elliptic_1.default.ec("p256"); +exports.default = arrayBufferToHex; + +},{}],297:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +function arrayBufferToString(arr) { + var byteArray = new Uint8Array(arr); + var byteString = ""; + for (var i = 0; i < byteArray.byteLength; i += 1) { + byteString += String.fromCodePoint(byteArray[i]); + } + return byteString; } -var proofOfWork_1 = require("./utils/proofOfWork"); -Object.defineProperty(exports, "proofOfWork", { enumerable: true, get: function () { return __importDefault(proofOfWork_1).default; } }); -var uniq_1 = require("./utils/uniq"); -Object.defineProperty(exports, "uniq", { enumerable: true, get: function () { return __importDefault(uniq_1).default; } }); -var sha1_1 = require("./utils/sha1"); -Object.defineProperty(exports, "sha1", { enumerable: true, get: function () { return __importDefault(sha1_1).default; } }); -var sha256_1 = require("./utils/sha256"); -Object.defineProperty(exports, "sha256", { enumerable: true, get: function () { return __importDefault(sha256_1).default; } }); -var signData_1 = require("./utils/signData"); -Object.defineProperty(exports, "signData", { enumerable: true, get: function () { return __importDefault(signData_1).default; } }); -var arrayBufferToBase64_1 = require("./utils/arrayBufferToBase64"); -Object.defineProperty(exports, "arrayBufferToBase64", { enumerable: true, get: function () { return __importDefault(arrayBufferToBase64_1).default; } }); -var arrayBufferToString_1 = require("./utils/arrayBufferToString"); -Object.defineProperty(exports, "arrayBufferToString", { enumerable: true, get: function () { return __importDefault(arrayBufferToString_1).default; } }); -var base64ToArrayBuffer_1 = require("./utils/base64ToArrayBuffer"); -Object.defineProperty(exports, "base64ToArrayBuffer", { enumerable: true, get: function () { return __importDefault(base64ToArrayBuffer_1).default; } }); -var base64ToBinaryChange_1 = require("./utils/base64ToBinaryChange"); -Object.defineProperty(exports, "base64ToBinaryChange", { enumerable: true, get: function () { return __importDefault(base64ToBinaryChange_1).default; } }); -var base64ToBinaryDocument_1 = require("./utils/base64ToBinaryDocument"); -Object.defineProperty(exports, "base64ToBinaryDocument", { enumerable: true, get: function () { return __importDefault(base64ToBinaryDocument_1).default; } }); -var base64ToUint8_1 = require("./utils/base64ToUint8"); -Object.defineProperty(exports, "base64ToUint8", { enumerable: true, get: function () { return __importDefault(base64ToUint8_1).default; } }); -var fromBase64_1 = require("./utils/fromBase64"); -Object.defineProperty(exports, "fromBase64", { enumerable: true, get: function () { return __importDefault(fromBase64_1).default; } }); -var generateIv_1 = require("./utils/generateIv"); -Object.defineProperty(exports, "generateIv", { enumerable: true, get: function () { return __importDefault(generateIv_1).default; } }); -var randomAnimal_1 = require("./utils/randomAnimal"); -Object.defineProperty(exports, "randomAnimal", { enumerable: true, get: function () { return __importDefault(randomAnimal_1).default; } }); -var stringToArrayBuffer_1 = require("./utils/stringToArrayBuffer"); -Object.defineProperty(exports, "stringToArrayBuffer", { enumerable: true, get: function () { return __importDefault(stringToArrayBuffer_1).default; } }); -var textRandom_1 = require("./utils/textRandom"); -Object.defineProperty(exports, "textRandom", { enumerable: true, get: function () { return __importDefault(textRandom_1).default; } }); -var toBase64_1 = require("./utils/toBase64"); -Object.defineProperty(exports, "toBase64", { enumerable: true, get: function () { return __importDefault(toBase64_1).default; } }); -var uint8ToBase64_1 = require("./utils/uint8ToBase64"); -Object.defineProperty(exports, "uint8ToBase64", { enumerable: true, get: function () { return __importDefault(uint8ToBase64_1).default; } }); -var verifyMessage_1 = require("./utils/verifyMessage"); -Object.defineProperty(exports, "verifyMessage", { enumerable: true, get: function () { return __importDefault(verifyMessage_1).default; } }); -var decodeKeyString_1 = require("./utils/crypto/decodeKeyString"); -Object.defineProperty(exports, "decodeKeyString", { enumerable: true, get: function () { return __importDefault(decodeKeyString_1).default; } }); -var decryptData_1 = require("./utils/crypto/decryptData"); -Object.defineProperty(exports, "decryptData", { enumerable: true, get: function () { return __importDefault(decryptData_1).default; } }); -var decryptWithPass_1 = require("./utils/crypto/decryptWithPass"); -Object.defineProperty(exports, "decryptWithPass", { enumerable: true, get: function () { return __importDefault(decryptWithPass_1).default; } }); -var deriveSecret_1 = require("./utils/crypto/deriveSecret"); -Object.defineProperty(exports, "deriveSecret", { enumerable: true, get: function () { return __importDefault(deriveSecret_1).default; } }); -var encodeKeyString_1 = require("./utils/crypto/encodeKeyString"); -Object.defineProperty(exports, "encodeKeyString", { enumerable: true, get: function () { return __importDefault(encodeKeyString_1).default; } }); -var encryptData_1 = require("./utils/crypto/encryptData"); -Object.defineProperty(exports, "encryptData", { enumerable: true, get: function () { return __importDefault(encryptData_1).default; } }); -var encryptWithPass_1 = require("./utils/crypto/encryptWithPass"); -Object.defineProperty(exports, "encryptWithPass", { enumerable: true, get: function () { return __importDefault(encryptWithPass_1).default; } }); -var exportKey_1 = require("./utils/crypto/exportKey"); -Object.defineProperty(exports, "exportKey", { enumerable: true, get: function () { return __importDefault(exportKey_1).default; } }); -var generateKeyFromPassword_1 = require("./utils/crypto/generateKeyFromPassword"); -Object.defineProperty(exports, "generateKeyFromPassword", { enumerable: true, get: function () { return __importDefault(generateKeyFromPassword_1).default; } }); -var generateKeyPair_1 = require("./utils/crypto/generateKeyPair"); -Object.defineProperty(exports, "generateKeyPair", { enumerable: true, get: function () { return __importDefault(generateKeyPair_1).default; } }); -var generateKeysComb_1 = require("./utils/crypto/generateKeysComb"); -Object.defineProperty(exports, "generateKeysComb", { enumerable: true, get: function () { return __importDefault(generateKeysComb_1).default; } }); -var importKey_1 = require("./utils/crypto/importKey"); -Object.defineProperty(exports, "importKey", { enumerable: true, get: function () { return __importDefault(importKey_1).default; } }); -var loadKeysComb_1 = require("./utils/crypto/loadKeysComb"); -Object.defineProperty(exports, "loadKeysComb", { enumerable: true, get: function () { return __importDefault(loadKeysComb_1).default; } }); -var saveKeysComb_1 = require("./utils/crypto/saveKeysComb"); -Object.defineProperty(exports, "saveKeysComb", { enumerable: true, get: function () { return __importDefault(saveKeysComb_1).default; } }); -var verifyData_1 = require("./utils/crypto/verifyData"); -Object.defineProperty(exports, "verifyData", { enumerable: true, get: function () { return __importDefault(verifyData_1).default; } }); -var networkAdapterBase_1 = require("./networkAdapterBase"); -Object.defineProperty(exports, "ToolDbNetworkAdapter", { enumerable: true, get: function () { return __importDefault(networkAdapterBase_1).default; } }); -var toolDbNetwork_1 = require("./toolDbNetwork"); -Object.defineProperty(exports, "ToolDbNetwork", { enumerable: true, get: function () { return __importDefault(toolDbNetwork_1).default; } }); -var handleCrdt_1 = require("./messageHandlers/handleCrdt"); -Object.defineProperty(exports, "handleCrdt", { enumerable: true, get: function () { return __importDefault(handleCrdt_1).default; } }); -var handleCrdtGet_1 = require("./messageHandlers/handleCrdtGet"); -Object.defineProperty(exports, "handleCrdtGet", { enumerable: true, get: function () { return __importDefault(handleCrdtGet_1).default; } }); -var handleCrdtPut_1 = require("./messageHandlers/handleCrdtPut"); -Object.defineProperty(exports, "handleCrdtPut", { enumerable: true, get: function () { return __importDefault(handleCrdtPut_1).default; } }); -var handleGet_1 = require("./messageHandlers/handleGet"); -Object.defineProperty(exports, "handleGet", { enumerable: true, get: function () { return __importDefault(handleGet_1).default; } }); -var handlePing_1 = require("./messageHandlers/handlePing"); -Object.defineProperty(exports, "handlePing", { enumerable: true, get: function () { return __importDefault(handlePing_1).default; } }); -var handlePong_1 = require("./messageHandlers/handlePong"); -Object.defineProperty(exports, "handlePong", { enumerable: true, get: function () { return __importDefault(handlePong_1).default; } }); -var handlePut_1 = require("./messageHandlers/handlePut"); -Object.defineProperty(exports, "handlePut", { enumerable: true, get: function () { return __importDefault(handlePut_1).default; } }); -var handleQuery_1 = require("./messageHandlers/handleQuery"); -Object.defineProperty(exports, "handleQuery", { enumerable: true, get: function () { return __importDefault(handleQuery_1).default; } }); -var handleSubscribe_1 = require("./messageHandlers/handleSubscribe"); -Object.defineProperty(exports, "handleSubscribe", { enumerable: true, get: function () { return __importDefault(handleSubscribe_1).default; } }); -var tooldb_1 = require("./tooldb"); -Object.defineProperty(exports, "ToolDb", { enumerable: true, get: function () { return __importDefault(tooldb_1).default; } }); +exports.default = arrayBufferToString; -}).call(this)}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {},require("buffer").Buffer) -},{"./messageHandlers/handleCrdt":307,"./messageHandlers/handleCrdtGet":308,"./messageHandlers/handleCrdtPut":309,"./messageHandlers/handleGet":311,"./messageHandlers/handlePing":312,"./messageHandlers/handlePong":313,"./messageHandlers/handlePut":314,"./messageHandlers/handleQuery":315,"./messageHandlers/handleSubscribe":316,"./networkAdapterBase":317,"./toolDbNetwork":326,"./tooldb":334,"./types/message":335,"./types/tooldb":336,"./utils/arrayBufferToBase64":337,"./utils/arrayBufferToString":339,"./utils/base64ToArrayBuffer":340,"./utils/base64ToBinaryChange":341,"./utils/base64ToBinaryDocument":342,"./utils/base64ToUint8":343,"./utils/crypto/decodeKeyString":345,"./utils/crypto/decryptData":346,"./utils/crypto/decryptWithPass":347,"./utils/crypto/deriveSecret":348,"./utils/crypto/encodeKeyString":349,"./utils/crypto/encryptData":350,"./utils/crypto/encryptWithPass":351,"./utils/crypto/exportKey":352,"./utils/crypto/generateKeyFromPassword":353,"./utils/crypto/generateKeyPair":354,"./utils/crypto/generateKeysComb":355,"./utils/crypto/importKey":356,"./utils/crypto/loadKeysComb":357,"./utils/crypto/saveKeysComb":358,"./utils/crypto/verifyData":359,"./utils/fromBase64":360,"./utils/generateIv":361,"./utils/proofOfWork":366,"./utils/randomAnimal":367,"./utils/sha1":368,"./utils/sha256":369,"./utils/signData":370,"./utils/stringToArrayBuffer":371,"./utils/textRandom":372,"./utils/toBase64":373,"./utils/uint8ToBase64":374,"./utils/uniq":375,"./utils/verifyMessage":376,"buffer":137,"crypto":168,"elliptic":185}],305:[function(require,module,exports){ +},{}],298:[function(require,module,exports){ "use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); -var automerge_1 = __importDefault(require("automerge")); -function loadCrdtDocument(key, doDefault) { - var _this = this; - if (doDefault === void 0) { doDefault = true; } - return new Promise(function (resolve, reject) { - if (_this.documents[key]) { - resolve(_this.documents[key]); - } - else { - _this.store.get(key + ".crdt", function (err, data) { - var currentDoc = null; - if (data) { - // De-serealize stored crdt document - // console.log("data", typeof data, data); - var loaded_1 = data; - if (typeof data === "string") { - var split = data.split(","); - loaded_1 = new Uint8Array(split.length); - split.forEach(function (s, i) { - loaded_1[i] = parseInt(s); - }); - } - currentDoc = automerge_1.default.load(loaded_1); - // console.log("CRDT LOADED", key, currentDoc); - } - else { - // console.log("CRDT not found for", key); - if (doDefault) { - currentDoc = automerge_1.default.init(); - } - } - resolve(currentDoc); - }); - } - }); +var fromBase64_1 = __importDefault(require("./fromBase64")); +var stringToArrayBuffer_1 = __importDefault(require("./stringToArrayBuffer")); +function base64ToArrayBuffer(str) { + return (0, stringToArrayBuffer_1.default)((0, fromBase64_1.default)(str)); } -exports.default = loadCrdtDocument; +exports.default = base64ToArrayBuffer; -},{"automerge":86}],306:[function(require,module,exports){ +},{"./fromBase64":318,"./stringToArrayBuffer":329}],299:[function(require,module,exports){ "use strict"; -var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { - if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { - if (ar || !(i in from)) { - if (!ar) ar = Array.prototype.slice.call(from, 0, i); - ar[i] = from[i]; - } - } - return to.concat(ar || Array.prototype.slice.call(from)); +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); -var _1 = require("."); -function logger(arg0, arg1, arg2, arg3, arg4, arg5) { - if (this.options.debug) { - var isNode = typeof window === "undefined" ? self.document !== undefined : false; - var title = isNode - ? this.options.storageName - : "%c" + this.options.storageName; - var style = isNode - ? "" - : "background: #" + - (0, _1.sha1)(this.options.storageName).slice(-6) + - "; padding: 2px; color: black"; - console.log.apply(console, __spreadArray([title, - style], [arg0, arg1, arg2, arg3, arg4, arg4, arg5].slice(0, arguments.length), false)); +var fromBase64_1 = __importDefault(require("./fromBase64")); +function base64ToBinaryChange(based) { + var str = (0, fromBase64_1.default)(based); + var buf = new ArrayBuffer(str.length); + var bufView = new Uint8Array(buf); + for (var i = 0, strLen = str.length; i < strLen; i += 1) { + bufView[i] = str.charCodeAt(i); } + bufView.__binaryChange = true; + return bufView; } -exports.default = logger; - -},{".":304}],307:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -var __1 = require(".."); -function handleCrdt(message, remotePeerId) { - var key = message.key; - this.triggerKeyListener(key, message); - // OOHH THE TYPECAST PAIN - // This works but the hacking is awful, we need a better solution for storing the crdts - var savedDoc = (0, __1.base64ToBinaryDocument)(message.doc); - this.store.put(key + ".crdt", savedDoc, function (err, data) { - // - }); -} -exports.default = handleCrdt; +exports.default = base64ToBinaryChange; -},{"..":304}],308:[function(require,module,exports){ +},{"./fromBase64":318}],300:[function(require,module,exports){ "use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); -var automerge_1 = __importDefault(require("automerge")); -var __1 = require(".."); -function handleCrdtGet(message, remotePeerId) { - var _this = this; - this.loadCrdtDocument(message.key, false).then(function (currentDoc) { - if (currentDoc) { - var saved = automerge_1.default.save(currentDoc || automerge_1.default.init()); - _this.network.sendToClientId(remotePeerId, { - type: "crdt", - id: message.id, - key: message.key, - to: [], - doc: (0, __1.uint8ToBase64)(saved), - }); - } - else { - _this.logger("Local key not found, relay", JSON.stringify(message)); - _this.network.sendToAll(message, true); - } - }); +var fromBase64_1 = __importDefault(require("./fromBase64")); +function base64ToBinaryDocument(based) { + var str = (0, fromBase64_1.default)(based); + var buf = new ArrayBuffer(str.length); + var bufView = new Uint8Array(buf); + for (var i = 0, strLen = str.length; i < strLen; i += 1) { + bufView[i] = str.charCodeAt(i); + } + bufView.__binaryDocument = true; + return bufView; } -exports.default = handleCrdtGet; +exports.default = base64ToBinaryDocument; -},{"..":304,"automerge":86}],309:[function(require,module,exports){ +},{"./fromBase64":318}],301:[function(require,module,exports){ "use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); -var automerge_1 = __importDefault(require("automerge")); -var __1 = require(".."); -var toolDbVerificationWrapper_1 = __importDefault(require("../toolDbVerificationWrapper")); -function handleCrdtPut(message, remotePeerId) { - var _this = this; - // key = aggregated, final value - // key.crdt = automerge doc with changes - // const writeStart = new Date().getTime(); - toolDbVerificationWrapper_1.default.call(this, message).then(function (value) { - // console.log("CRDT Verification wrapper result: ", value); - if (value === __1.VerifyResult.Verified) { - var key_1 = message.k; - var data = []; - try { - data = JSON.parse(message.v); - } - catch (e) { - // - } - var changes_1 = data.map(__1.base64ToBinaryChange); - _this.loadCrdtDocument(key_1).then(function (currentDoc) { - // if (currentDoc) { - // console.log( - // "loaded", - // key, - // currentDoc, - // Automerge.getHistory(currentDoc) - // ); - // } - var newDoc = automerge_1.default.init(); - try { - newDoc = automerge_1.default.applyChanges(currentDoc || automerge_1.default.init(), changes_1)[0]; - } - catch (e) { - try { - newDoc = automerge_1.default.applyChanges(automerge_1.default.init(), changes_1)[0]; - } - catch (ee) { - _this.logger(ee); - } - } - // if (newDoc) { - // console.log( - // "new document changes:", - // Automerge.getHistory(newDoc), - // "final: ", - // newDoc - // ); - // } - // persist - _this.documents[key_1] = newDoc; - // OOHH THE TYPECAST PAIN - // This works but the hacking is awful, we need a better solution for storing the crdts - var savedDoc = automerge_1.default.save(newDoc); - _this.store.put(key_1 + ".crdt", savedDoc, function (err, data) { - // const writeEnd = new Date().getTime(); - // console.log("CRDT write: ", (writeEnd - writeStart) / 1000); - }); - var crdtMessage = { - type: "crdt", - key: key_1, - id: message.id, - to: [], - doc: (0, __1.uint8ToBase64)(savedDoc), - }; - _this.triggerKeyListener(key_1, crdtMessage); - // relay to other servers - // !!! - _this.network.sendToAll(crdtMessage, true); - }); - } - else { - console.log("unverified message", value, message); - } - }); +var fromBase64_1 = __importDefault(require("./fromBase64")); +function base64ToUint8(based) { + var str = (0, fromBase64_1.default)(based); + var buf = new ArrayBuffer(str.length); + var bufView = new Uint8Array(buf); + for (var i = 0, strLen = str.length; i < strLen; i += 1) { + bufView[i] = str.charCodeAt(i); + } + return bufView; } -exports.default = handleCrdtPut; +exports.default = base64ToUint8; -},{"..":304,"../toolDbVerificationWrapper":333,"automerge":86}],310:[function(require,module,exports){ +},{"./fromBase64":318}],302:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -function handleFunction(message, remotePeerId) { - var _this = this; - // executes the given function by message on the server if it exists - if (this.functions[message.function]) { - try { - this.functions[message.function](message.args) - .then(function (ret) { - var messageReturn = { - return: ret, - type: "functionReturn", - id: message.id, - code: "OK", - to: [], - }; - _this.network.sendToClientId(remotePeerId, messageReturn); - }) - .catch(function (e) { - var messageReturn = { - return: JSON.stringify(e), - type: "functionReturn", - id: message.id, - code: "ERR", - to: [], - }; - _this.network.sendToClientId(remotePeerId, messageReturn); - }); - } - catch (e) { - // something went wrong, nothing to do here - // We might want to return the exception to the client? - var messageReturn = { - return: e.toString(), - type: "functionReturn", - id: message.id, - code: "ERR", - to: [], - }; - this.network.sendToClientId(remotePeerId, messageReturn); - } - } - else { - // function not found - var messageReturn = { - return: "Function not found", - type: "functionReturn", - id: message.id, - code: "NOT_FOUND", - to: [], - }; - this.network.sendToClientId(remotePeerId, messageReturn); - } +function catchReturn(arg) { + // console.error(arg); + return undefined; } -exports.default = handleFunction; +exports.default = catchReturn; -},{}],311:[function(require,module,exports){ +},{}],303:[function(require,module,exports){ +(function (global){(function (){ "use strict"; -var __assign = (this && this.__assign) || function () { - __assign = Object.assign || function(t) { - for (var s, i = 1, n = arguments.length; i < n; i++) { - s = arguments[i]; - for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) - t[p] = s[p]; - } - return t; - }; - return __assign.apply(this, arguments); +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); -function handleGet(message, remotePeerId) { - var _this = this; - this.store.get(message.key, function (err, data) { - if (data) { - try { - // Use the id of the get so the other client knows we are replying - var oldData = __assign(__assign({ type: "put" }, JSON.parse(data)), { id: message.id, to: [] }); - _this.network.sendToClientId(remotePeerId, oldData); - } - catch (e) { - // socket.send(data); - // do nothing - } - } - else { - _this.logger("Local key not found, relay", JSON.stringify(message)); - _this.network.sendToAll(message, true); - } - }); +var stringToArrayBuffer_1 = __importDefault(require("../stringToArrayBuffer")); +function decodeKeyString(keydataB64) { + var keydataS = global.atob(keydataB64); + var keydata = (0, stringToArrayBuffer_1.default)(keydataS); + return keydata; } -exports.default = handleGet; +exports.default = decodeKeyString; -},{}],312:[function(require,module,exports){ +}).call(this)}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"../stringToArrayBuffer":329}],304:[function(require,module,exports){ "use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); -var verifyPeer_1 = __importDefault(require("../utils/verifyPeer")); -function handlePing(message, remotePeerId) { - var _this = this; - if (!this.isConnected) { - this.isConnected = true; - this.onConnect(); - } - (0, verifyPeer_1.default)(message.peer).then(function (verified) { - // Verify integrity and topic - if (verified && message.peer.topic === _this.options.topic) { - // Add this peer to our list of peers - _this.peers[message.peer.pubkey] = message.peer; - _this.network.sendToClientId(remotePeerId, { - type: "pong", - isServer: _this.options.server, - clientId: _this.network.getClientAddress(), - to: [], - servers: _this.serverPeers, - id: message.id, - }); - _this.onPeerConnect(message.peer.pubkey); - } - else { - _this.logger("Blocked a remote peer from joining; ", message); - // Drop connection here! - } - }); +var getCrypto_1 = __importDefault(require("../../getCrypto")); +var arrayBufferToString_1 = __importDefault(require("../arrayBufferToString")); +var base64ToUint8_1 = __importDefault(require("../base64ToUint8")); +var catchReturn_1 = __importDefault(require("../catchReturn")); +var stringToArrayBuffer_1 = __importDefault(require("../stringToArrayBuffer")); +function decryptData(data, privateKey, iv) { + var crypto = (0, getCrypto_1.default)(); + return crypto.subtle + .decrypt({ + name: "AES-GCM", + iv: (0, base64ToUint8_1.default)(iv), + tagLength: 128, // The tagLength you used to encrypt (if any) + }, privateKey, // from generateKey or importKey above + (0, stringToArrayBuffer_1.default)(data) // ArrayBuffer of the data + ) + .then(function (decrypted) { + // returns an ArrayBuffer containing the decrypted data + return (0, arrayBufferToString_1.default)(decrypted); + }) + .catch(catchReturn_1.default); } -exports.default = handlePing; +exports.default = decryptData; -},{"../utils/verifyPeer":377}],313:[function(require,module,exports){ +},{"../../getCrypto":261,"../arrayBufferToString":297,"../base64ToUint8":301,"../catchReturn":302,"../stringToArrayBuffer":329}],305:[function(require,module,exports){ "use strict"; -var __assign = (this && this.__assign) || function () { - __assign = Object.assign || function(t) { - for (var s, i = 1, n = arguments.length; i < n; i++) { - s = arguments[i]; - for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) - t[p] = s[p]; - } - return t; - }; - return __assign.apply(this, arguments); -}; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); -var verifyPeer_1 = __importDefault(require("../utils/verifyPeer")); -function handlePong(message, remotePeerId) { - var _this = this; - if (!this.isConnected) { - this.isConnected = true; - this.onConnect(); - } - if (message.servers) { - message.servers.forEach(function (peer) { - (0, verifyPeer_1.default)(peer).then(function (verified) { - // Verify integrity and topic - if (verified && peer.topic === _this.options.topic) { - // Add this peer to our list of peers - _this.peers[peer.pubkey] = __assign(__assign({}, peer), { isServer: true }); - } - }); - }); - } - this.onPeerConnect(message.clientId); +var arrayBufferToString_1 = __importDefault(require("../arrayBufferToString")); +var catchReturn_1 = __importDefault(require("../catchReturn")); +var generateKeyFromPassword_1 = __importDefault(require("./generateKeyFromPassword")); +var stringToArrayBuffer_1 = __importDefault(require("../stringToArrayBuffer")); +var getCrypto_1 = __importDefault(require("../../getCrypto")); +function decryptWithPass(data, password, vector) { + var crypto = (0, getCrypto_1.default)(); + return (0, generateKeyFromPassword_1.default)(password) + .then(function (keyObject) { + return crypto.subtle + .decrypt({ name: "AES-GCM", iv: vector }, keyObject, (0, stringToArrayBuffer_1.default)(data)) + .then(function (result) { return (0, arrayBufferToString_1.default)(result); }) + .catch(catchReturn_1.default); + }) + .catch(catchReturn_1.default); } -exports.default = handlePong; +exports.default = decryptWithPass; -},{"../utils/verifyPeer":377}],314:[function(require,module,exports){ +},{"../../getCrypto":261,"../arrayBufferToString":297,"../catchReturn":302,"../stringToArrayBuffer":329,"./generateKeyFromPassword":311}],306:[function(require,module,exports){ "use strict"; -var __assign = (this && this.__assign) || function () { - __assign = Object.assign || function(t) { - for (var s, i = 1, n = arguments.length; i < n; i++) { - s = arguments[i]; - for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) - t[p] = s[p]; - } - return t; - }; - return __assign.apply(this, arguments); +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; }; +Object.defineProperty(exports, "__esModule", { value: true }); +var getCrypto_1 = __importDefault(require("../../getCrypto")); +function deriveSecret(keys) { + var crypto = (0, getCrypto_1.default)(); + return crypto.subtle.deriveKey({ + name: "ECDH", + public: keys.publicKey, + }, keys.privateKey, { + name: "AES-GCM", + length: 256, + }, true, ["encrypt", "decrypt"]); +} +exports.default = deriveSecret; + +},{"../../getCrypto":261}],307:[function(require,module,exports){ +(function (global){(function (){ +"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); -var __1 = require(".."); -var toolDbVerificationWrapper_1 = __importDefault(require("../toolDbVerificationWrapper")); -function handlePut(message, remotePeerId) { - var _this = this; - toolDbVerificationWrapper_1.default.call(this, message).then(function (value) { - // console.log("Verification wrapper result: ", value, message.k); - if (value === __1.VerifyResult.Verified) { - // relay to other servers !!! - _this.network.sendToAll(message, true); - _this.store.get(message.k, function (err, oldData) { - if (oldData) { - var parsedOldData = __assign({ type: "put", to: [] }, JSON.parse(oldData)); - if (parsedOldData.t < message.t) { - var key = message.k; - _this.triggerKeyListener(key, message); - _this.store.put(message.k, JSON.stringify(message), function (err, data) { - // - }); - } - else { - var key = message.k; - _this.triggerKeyListener(key, parsedOldData); - } - // } else if (this.options.debug) { - // console.log( - // `${message.k} has old data, but its newer. old ${parsedOldData.t} < new ${message.t}` - // ); - // } - } - else { - var key = message.k; - _this.triggerKeyListener(key, message); - _this.store.put(message.k, JSON.stringify(message), function (err, data) { - // - }); - } - }); - } - else { - console.warn("unverified message: ", value, message); - } - }); +var arrayBufferToString_1 = __importDefault(require("../arrayBufferToString")); +function encodeKeyString(keydata) { + var keydataS = (0, arrayBufferToString_1.default)(keydata); + var keydataB64 = global.btoa(keydataS); + return keydataB64; } -exports.default = handlePut; +exports.default = encodeKeyString; -},{"..":304,"../toolDbVerificationWrapper":333}],315:[function(require,module,exports){ +}).call(this)}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"../arrayBufferToString":297}],308:[function(require,module,exports){ "use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; Object.defineProperty(exports, "__esModule", { value: true }); -function handleQuery(message, remotePeerId) { - var _this = this; - if (message.key.length < 3) - return; - this.store.query(message.key).then(function (keys) { - _this.network.sendToClientId(remotePeerId, { - type: "queryAck", - id: message.id, - to: [], - keys: keys, - }); - }); - if (this.options.server) { - this.network.sendToAll(message, true); - } +var getCrypto_1 = __importDefault(require("../../getCrypto")); +var arrayBufferToString_1 = __importDefault(require("../arrayBufferToString")); +var stringToArrayBuffer_1 = __importDefault(require("../stringToArrayBuffer")); +function encryptData(data, publicKey, iv) { + var crypto = (0, getCrypto_1.default)(); + return crypto.subtle + .encrypt({ + name: "AES-GCM", + // Don't re-use initialization vectors! + // Always generate a new iv every time your encrypt! + // Recommended to use 12 bytes length + iv: iv, + // Tag length (optional) + tagLength: 128, // can be 32, 64, 96, 104, 112, 120 or 128 (default) + }, publicKey, // from generateKey or importKey above + (0, stringToArrayBuffer_1.default)(data) // ArrayBuffer of data you want to encrypt + ) + .then(function (encrypted) { + // returns an ArrayBuffer containing the encrypted data + return (0, arrayBufferToString_1.default)(encrypted); + }) + .catch(console.error); } -exports.default = handleQuery; +exports.default = encryptData; -},{}],316:[function(require,module,exports){ +},{"../../getCrypto":261,"../arrayBufferToString":297,"../stringToArrayBuffer":329}],309:[function(require,module,exports){ "use strict"; -var __assign = (this && this.__assign) || function () { - __assign = Object.assign || function(t) { - for (var s, i = 1, n = arguments.length; i < n; i++) { - s = arguments[i]; - for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) - t[p] = s[p]; - } - return t; - }; - return __assign.apply(this, arguments); +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; }; +Object.defineProperty(exports, "__esModule", { value: true }); +var arrayBufferToString_1 = __importDefault(require("../arrayBufferToString")); +var catchReturn_1 = __importDefault(require("../catchReturn")); +var generateKeyFromPassword_1 = __importDefault(require("./generateKeyFromPassword")); +var stringToArrayBuffer_1 = __importDefault(require("../stringToArrayBuffer")); +var getCrypto_1 = __importDefault(require("../../getCrypto")); +function encryptWithPass(secretmessage, password, vector) { + var crypto = (0, getCrypto_1.default)(); + return (0, generateKeyFromPassword_1.default)(password) + .then(function (keyObject) { + // encrypt promise + return crypto.subtle + .encrypt({ name: "AES-GCM", iv: vector }, keyObject, (0, stringToArrayBuffer_1.default)(secretmessage)) + .then(function (result) { + return (0, arrayBufferToString_1.default)(result); + }) + .catch(catchReturn_1.default); + }) + .catch(catchReturn_1.default); +} +exports.default = encryptWithPass; + +},{"../../getCrypto":261,"../arrayBufferToString":297,"../catchReturn":302,"../stringToArrayBuffer":329,"./generateKeyFromPassword":311}],310:[function(require,module,exports){ +"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); -var automerge_1 = __importDefault(require("automerge")); -var __1 = require(".."); -function handleSubscribe(message, remotePeerId) { - var _this = this; - if (remotePeerId) { - var subId = remotePeerId + "-" + message.key; - if (!this.subscriptions.includes(subId)) { - this.subscriptions.push(subId); - this.addKeyListener(message.key, function (msg) { - if ((msg.type === "put" || msg.type === "crdt") && remotePeerId) { - // We do not reply to the socket directly - // instead we use the client id, in case the socket reconnects - _this.network.sendToClientId(remotePeerId, msg); - } - }); - } - } - // basically the exact same as GET, below - this.store.get(message.key, function (err, data) { - if (data) { - try { - var oldData = __assign(__assign({}, JSON.parse(data)), { id: message.id, to: [] }); - _this.network.sendToClientId(remotePeerId, oldData); - } - catch (e) { - // do nothing - } - } - }); - this.loadCrdtDocument(message.key, false).then(function (doc) { - // console.log("Load crdt from subscribe", message.key, doc); - if (doc) { - var savedDoc = automerge_1.default.save(doc); - var msg = { - type: "crdt", - key: message.key, - to: [], - id: (0, __1.textRandom)(10), - doc: (0, __1.uint8ToBase64)(savedDoc), - }; - _this.network.sendToClientId(remotePeerId, msg); - } - }); +var getCrypto_1 = __importDefault(require("../../getCrypto")); +function exportKey(format, key) { + var crypto = (0, getCrypto_1.default)(); + return crypto.subtle.exportKey(format, // can be "jwk" (public or private), "spki" (public only), or "pkcs8" (private only) + key // can be a publicKey or privateKey, as long as extractable was true, + ); } -exports.default = handleSubscribe; +exports.default = exportKey; -},{"..":304,"automerge":86}],317:[function(require,module,exports){ +},{"../../getCrypto":261}],311:[function(require,module,exports){ "use strict"; -var __assign = (this && this.__assign) || function () { - __assign = Object.assign || function(t) { - for (var s, i = 1, n = arguments.length; i < n; i++) { - s = arguments[i]; - for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) - t[p] = s[p]; - } - return t; - }; - return __assign.apply(this, arguments); -}; -var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { - if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { - if (ar || !(i in from)) { - if (!ar) ar = Array.prototype.slice.call(from, 0, i); - ar[i] = from[i]; - } - } - return to.concat(ar || Array.prototype.slice.call(from)); -}; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); -var _1 = require("."); -var getPeerSignature_1 = __importDefault(require("./utils/getPeerSignature")); -var ToolDbNetworkAdapter = /** @class */ (function () { - function ToolDbNetworkAdapter(db) { - var _this = this; - this._clientToSend = {}; - this._clientSocket = {}; - this._isClientConnected = {}; - this._clientIsServer = {}; - this._tooldb = db; - db.on("init", function () { - if (_this.tooldb.options.server) { - _this.getMeAsPeer().then(function (meAsPeer) { - _this.tooldb.peers[meAsPeer.pubkey] = meAsPeer; - }); - } - }); - } - Object.defineProperty(ToolDbNetworkAdapter.prototype, "clientToSend", { - get: function () { - return this._clientToSend; - }, - enumerable: false, - configurable: true - }); - Object.defineProperty(ToolDbNetworkAdapter.prototype, "clientSocket", { - get: function () { - return this._clientSocket; - }, - enumerable: false, - configurable: true - }); - Object.defineProperty(ToolDbNetworkAdapter.prototype, "isClientConnected", { - get: function () { - return this._isClientConnected; - }, - enumerable: false, - configurable: true - }); - Object.defineProperty(ToolDbNetworkAdapter.prototype, "tooldb", { - get: function () { - return this._tooldb; - }, - enumerable: false, - configurable: true +var getCrypto_1 = __importDefault(require("../../getCrypto")); +var stringToArrayBuffer_1 = __importDefault(require("../stringToArrayBuffer")); +function generateKeyFromPassword(password) { + var crypto = (0, getCrypto_1.default)(); + return crypto.subtle + .importKey("raw", (0, stringToArrayBuffer_1.default)(password), { name: "PBKDF2" }, false, ["deriveKey"]) + .then(function (importedPassword) { + return crypto.subtle.deriveKey({ + name: "PBKDF2", + salt: (0, stringToArrayBuffer_1.default)("t6sa@8d7!2ñs?=adjq2ng"), + iterations: 100000, + hash: "SHA-256", + }, importedPassword, { + name: "AES-GCM", + length: 128, + }, false, ["encrypt", "decrypt"]); }); - ToolDbNetworkAdapter.prototype.getMeAsPeer = function () { - var _this = this; - var timestamp = new Date().getTime(); - if (this.tooldb.options.defaultKeys === undefined) - return Promise.reject(); - else - return (0, getPeerSignature_1.default)(this.tooldb.options.defaultKeys.privateKey, this.tooldb.options.topic, timestamp, this.tooldb.options.host, this.tooldb.options.port).then(function (signature) { - var me = { - topic: _this.tooldb.options.topic, - timestamp: timestamp, - host: _this.tooldb.options.host, - port: _this.tooldb.options.port, - pubkey: _this.tooldb.getPubKey(), - sig: signature, - isServer: _this.tooldb.options.server, - }; - return me; - }); - }; - /** - * Check if the specified client is connected or not - * @param clientId Client ID - * @returns boolean - */ - ToolDbNetworkAdapter.prototype.isConnected = function (clientId) { - return this._isClientConnected[clientId] - ? this._isClientConnected[clientId]() - : false; - }; - /** - * Check if the specified client is a server/relay - * @param clientId Client ID - * @returns boolean - */ - ToolDbNetworkAdapter.prototype.isServer = function (clientId) { - return this._clientIsServer[clientId] || false; - }; - ToolDbNetworkAdapter.prototype.craftPingMessage = function () { - var _this = this; - return this.getMeAsPeer().then(function (meAsPeer) { - return JSON.stringify({ - type: "ping", - clientId: _this.getClientAddress(), - to: [_this.getClientAddress()], - isServer: _this.tooldb.options.server, - id: (0, _1.textRandom)(10), - peer: meAsPeer, - }); - }); - }; - /** - * Execute the function to send a message to the specified client ID - * @param clientId Client ID - * @param message Message - */ - ToolDbNetworkAdapter.prototype.executeSendToClient = function (clientId, message) { - if (this._clientToSend[clientId]) { - this._clientToSend[clientId](message); - } - }; - ToolDbNetworkAdapter.prototype.getClientAddress = function () { - // This is not a good idea to use on all adapters, so it should be replaced - // if its causing issues. The only reason we use the last 20 chars is to - // muse the same peer address as the webrtc adapter. - return this.tooldb.pubKey; - }; - ToolDbNetworkAdapter.prototype.onClientDisconnect = function (clientId) { - delete this._clientToSend[clientId]; - delete this._clientIsServer[clientId]; - delete this._isClientConnected[clientId]; - }; - /** - * Should be called as a message payload handler - * This function will take care of processing the messages and also making sure - * we use the correct response methods troughout the adapter. - * @param message message payload - * @param clientId Client ID (can be null for ping/pong) - * @param setClientId Callback to set the client id on the parent class - */ - ToolDbNetworkAdapter.prototype.onClientMessage = function (message, clientId, setClientId) { - // this.tooldb.logger("onClientMessage", clientId); - if (clientId && !this.tooldb.processedOutHashes[clientId]) { - this.tooldb.processedOutHashes[clientId] = []; - } - try { - var parsedMessage = JSON.parse(message); - // We assume the first messages to arrive will always be ping or pong. - // Only after that we can get the client id for this socket. - if (parsedMessage.type === "ping" || parsedMessage.type === "pong") { - var cid = parsedMessage.clientId; - setClientId(cid); - this._clientIsServer[cid] = parsedMessage.isServer; - this.tooldb.processedOutHashes[cid] = []; - this.tooldb.clientOnMessage(parsedMessage, cid); - } - else if (clientId) { - this.tooldb.clientOnMessage(parsedMessage, clientId); - } - } - catch (e) { - this.tooldb.logger("Got message ERR", message); - this.tooldb.logger(e); - } - }; - /** - * Sends a message to all peers connected to us - * This function takes care of the message deduplication, making sure we dont send - * the same message twice to the same peer. - * @param msg message data - * @param crossServerOnly If this message should be send to server peers only - * @param isRelay if we should relay this message - */ - ToolDbNetworkAdapter.prototype.sendToAll = function (msg, crossServerOnly) { - var _this = this; - if (crossServerOnly === void 0) { crossServerOnly = false; } - var pubkey = this.getClientAddress(); - var to = pubkey ? (0, _1.uniq)(__spreadArray(__spreadArray([], msg.to, true), [pubkey], false)) : msg.to; - var finalMessage = JSON.stringify(__assign(__assign({}, msg), { to: to })); - var filteredConns = Object.keys(this.clientToSend) - .filter(function (id) { return !to.includes(id); }) - .filter(function (clientId) { return _this.isConnected(clientId); }); - filteredConns.forEach(function (clientId) { - if ((crossServerOnly && _this.isServer(clientId)) || !crossServerOnly) { - _this.tooldb.logger(to.map(function (k) { return k.slice(-20); }), "Sent out to (all):", clientId.slice(-20)); - if (msg.type === "put" || msg.type === "crdtPut") { - if (!_this.tooldb.processedOutHashes[clientId].includes(msg.h)) { - _this.executeSendToClient(clientId, finalMessage); - _this.tooldb.processedOutHashes[clientId].push(msg.h); - } - } - else { - _this.executeSendToClient(clientId, finalMessage); - } - } - // } else { - // this.tooldb.logger("Fitlered out;", clientId); - // } - }); - }; - /** - * Sends a message to a single peer. - * This function also takes care of the message deduplication. - * @param clientId Peer/Client id we want to send to. - * @param msg message data - */ - ToolDbNetworkAdapter.prototype.sendToClientId = function (clientId, msg) { - var pubkey = this.getClientAddress(); - var to = pubkey ? (0, _1.uniq)(__spreadArray(__spreadArray([], msg.to, true), [pubkey], false)) : msg.to; - var finalMessage = JSON.stringify(__assign(__assign({}, msg), { to: to })); - this.tooldb.logger(to.map(function (k) { return k.slice(-20); }), "Sent out to (single):", clientId.slice(-20)); - if (msg.type === "put" || msg.type === "crdtPut") { - if (clientId && - !this.tooldb.processedOutHashes[clientId].includes(msg.h)) { - this.executeSendToClient(clientId, finalMessage); - this.tooldb.processedOutHashes[clientId].push(msg.h); - } - } - else { - this.executeSendToClient(clientId, finalMessage); - } - }; - return ToolDbNetworkAdapter; -}()); -exports.default = ToolDbNetworkAdapter; +} +exports.default = generateKeyFromPassword; -},{".":304,"./utils/getPeerSignature":362}],318:[function(require,module,exports){ +},{"../../getCrypto":261,"../stringToArrayBuffer":329}],312:[function(require,module,exports){ "use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); -var encodeKeyString_1 = __importDefault(require("./utils/crypto/encodeKeyString")); -var exportKey_1 = __importDefault(require("./utils/crypto/exportKey")); -var generateKeysComb_1 = __importDefault(require("./utils/crypto/generateKeysComb")); -var randomAnimal_1 = __importDefault(require("./utils/randomAnimal")); -function toolDbAnonSignIn() { - var _this = this; - return (0, generateKeysComb_1.default)().then(function (newKeys) { - return (0, exportKey_1.default)("spki", newKeys.signKeys.publicKey) - .then(function (skpub) { return (0, encodeKeyString_1.default)(skpub); }) - .then(function (pubKey) { - _this.user = { - keys: newKeys, - name: "Anonymous " + (0, randomAnimal_1.default)(), - pubKey: pubKey, - }; - return newKeys; +var getCrypto_1 = __importDefault(require("../../getCrypto")); +function generateKeyPair(mode, extractable) { + if (extractable === void 0) { extractable = false; } + var crypto = (0, getCrypto_1.default)(); + return crypto.subtle.generateKey({ + name: mode, + namedCurve: "P-256", // can be "P-256", "P-384", or "P-521" + }, extractable, // whether the key is extractable (i.e. can be used in exportKey) + mode === "ECDSA" ? ["sign", "verify"] : ["deriveKey", "deriveBits"]); +} +exports.default = generateKeyPair; + +},{"../../getCrypto":261}],313:[function(require,module,exports){ +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +var generateKeyPair_1 = __importDefault(require("./generateKeyPair")); +function generateKeysComb() { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2 /*return*/, new Promise(function (resolve) { + return (0, generateKeyPair_1.default)("ECDSA", true).then(function (signKeys) { + return (0, generateKeyPair_1.default)("ECDH", true).then(function (encryptionKeys) { + resolve({ + signKeys: signKeys, + encryptionKeys: encryptionKeys, + }); + }); + }); + })]; }); }); } -exports.default = toolDbAnonSignIn; +exports.default = generateKeysComb; -},{"./utils/crypto/encodeKeyString":349,"./utils/crypto/exportKey":352,"./utils/crypto/generateKeysComb":355,"./utils/randomAnimal":367}],319:[function(require,module,exports){ +},{"./generateKeyPair":312}],314:[function(require,module,exports){ "use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; Object.defineProperty(exports, "__esModule", { value: true }); -function toolDbClientOnMessage(message, remotePeerId) { - if (!this.processedIds[message.type]) { - this.processedIds[message.type] = []; - } - if (this.processedIds[message.type].includes(message.id)) { - // console.warn( - // `Already processed this message > ${message.type} from ${remotePeerId}` - // ); - return; - } - this.processedIds[message.type].push(message.id); - // console.warn(`Got message ${message.type} from ${remotePeerId}`); - this.logger("message", message, remotePeerId); - // Check if we are listening for this ID - if (message.id) { - var msgId = message.id; - if (this._idListeners[msgId]) { - this._idListeners[msgId](message); - this.removeIdListener(msgId); - } - } - if (message === undefined || message.type === undefined) { - this.logger("Message is invalid!", message, typeof message); - return; - } - switch (message.type) { - case "ping": - this.handlePing(message, remotePeerId); - break; - case "pong": - this.handlePong(message, remotePeerId); - break; - case "subscribe": - this.handleSubscribe(message, remotePeerId); - break; - case "get": - this.handleGet(message, remotePeerId); - break; - case "put": - this.handlePut(message, remotePeerId); - break; - case "crdtPut": - this.handleCrdtPut(message, remotePeerId); - break; - case "crdtGet": - this.handleCrdtGet(message, remotePeerId); - break; - case "query": - this.handleQuery(message, remotePeerId); - break; - case "crdt": - this.handleCrdt(message, remotePeerId); - break; - case "function": - this.handleFunction(message, remotePeerId); - break; - default: - break; - } +var getCrypto_1 = __importDefault(require("../../getCrypto")); +// JsonWebKey +function importKey( +// eslint-disable-next-line no-undef +key, type, algorithm, +// eslint-disable-next-line no-undef +ops) { + var crypto = (0, getCrypto_1.default)(); + return crypto.subtle.importKey(type, // can be "jwk" (public or private), "spki" (public only), or "pkcs8" (private only) + key, { + name: algorithm, + namedCurve: "P-256", + }, true, // whether the key is extractable (i.e. can be used in exportKey) + ops // "verify" for public key import, "sign" for private key imports + ); } -exports.default = toolDbClientOnMessage; +exports.default = importKey; -},{}],320:[function(require,module,exports){ +},{"../../getCrypto":261}],315:[function(require,module,exports){ "use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; Object.defineProperty(exports, "__esModule", { value: true }); -var _1 = require("."); -/** - * Triggers a GET request to other peers. If the data is available locally it will return that instead. - * @param key key of the data - * @param userNamespaced If this key bolongs to a user or its public. Making it private will enforce validation for our public key and signatures. - * @param timeout Max time to wait for remote. - * @returns Promise - */ -function toolDbCrdtGet(key, userNamespaced, timeoutMs) { - var _this = this; - if (userNamespaced === void 0) { userNamespaced = false; } - if (timeoutMs === void 0) { timeoutMs = 1000; } - return new Promise(function (resolve, reject) { - var _a, _b; - if (userNamespaced && ((_a = _this.user) === null || _a === void 0 ? void 0 : _a.pubKey) === undefined) { - reject(new Error("You are not authorized yet!")); - return; - } - var finalKey = userNamespaced ? ":" + ((_b = _this.user) === null || _b === void 0 ? void 0 : _b.pubKey) + "." + key : key; - _this.logger("CRDT GET > " + finalKey); - var msgId = (0, _1.textRandom)(10); - var cancelTimeout = setTimeout(function () { - _this.loadCrdtDocument(finalKey).then(function (data) { - if (data) { - try { - _this.removeIdListener(msgId); - resolve(data); - } - catch (e) { - resolve(null); - } - } - else { - resolve(null); - } - }); - }, timeoutMs); - _this.addIdListener(msgId, function (msg) { - _this.logger("CRDT GET RECV > " + finalKey, msg); - clearTimeout(cancelTimeout); - if (msg.type === "crdt") { - resolve(msg.doc); +var catchReturn_1 = __importDefault(require("../catchReturn")); +var decodeKeyString_1 = __importDefault(require("./decodeKeyString")); +var importKey_1 = __importDefault(require("./importKey")); +function importKeys(parsedKeys) { + return __awaiter(this, void 0, void 0, function () { + var skpub, skpriv, ekpub, ekpriv; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4 /*yield*/, (0, importKey_1.default)((0, decodeKeyString_1.default)(parsedKeys.skpub), "spki", "ECDSA", ["verify"]).catch(catchReturn_1.default)]; + case 1: + skpub = _a.sent(); + return [4 /*yield*/, (0, importKey_1.default)((0, decodeKeyString_1.default)(parsedKeys.skpriv), "pkcs8", "ECDSA", ["sign"]).catch(catchReturn_1.default)]; + case 2: + skpriv = _a.sent(); + return [4 /*yield*/, (0, importKey_1.default)((0, decodeKeyString_1.default)(parsedKeys.ekpub), "spki", "ECDH", []).catch(catchReturn_1.default)]; + case 3: + ekpub = _a.sent(); + return [4 /*yield*/, (0, importKey_1.default)((0, decodeKeyString_1.default)(parsedKeys.ekpriv), "pkcs8", "ECDH", ["deriveKey", "deriveBits"]).catch(catchReturn_1.default)]; + case 4: + ekpriv = _a.sent(); + return [2 /*return*/, { skpub: skpub, skpriv: skpriv, ekpub: ekpub, ekpriv: ekpriv }]; } }); - // Do get - _this.network.sendToAll({ - type: "crdtGet", - to: [], - key: finalKey, - id: msgId, + }); +} +function loadKeysComb(parsedKeys) { + return new Promise(function (resolve, reject) { + importKeys(parsedKeys).then(function (_a) { + var skpub = _a.skpub, skpriv = _a.skpriv, ekpub = _a.ekpub, ekpriv = _a.ekpriv; + if (!skpub || !skpriv || !ekpub || !ekpriv) { + reject(new Error("Could not import keys")); + } + else { + resolve({ + signKeys: { + publicKey: skpub, + privateKey: skpriv, + }, + encryptionKeys: { + publicKey: ekpub, + privateKey: ekpriv, + }, + }); + } }); }); } -exports.default = toolDbCrdtGet; +exports.default = loadKeysComb; -},{".":304}],321:[function(require,module,exports){ +},{"../catchReturn":302,"./decodeKeyString":303,"./importKey":314}],316:[function(require,module,exports){ "use strict"; -var __assign = (this && this.__assign) || function () { - __assign = Object.assign || function(t) { - for (var s, i = 1, n = arguments.length; i < n; i++) { - s = arguments[i]; - for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) - t[p] = s[p]; - } - return t; - }; - return __assign.apply(this, arguments); -}; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { @@ -65811,241 +64075,504 @@ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); -var _1 = require("."); -var proofOfWork_1 = __importDefault(require("./utils/proofOfWork")); -var signData_1 = __importDefault(require("./utils/signData")); -/** - * Triggers a PUT request to other peers. - * @param key key where we want to put the data at. - * @param value Data we want to any (any type) - * @param userNamespaced If this key bolongs to a user or its public. Making it private will enforce validation for our public key and signatures. - * @returns Promise - */ -function toolDbCrdtPut(key, value, userNamespaced) { - var _this = this; - if (userNamespaced === void 0) { userNamespaced = false; } - return new Promise(function (resolve, reject) { - if (key.includes(".")) { - // Dots are used as a delimitator character between bublic keys and the key of the user's data - reject(new Error("Key cannot include dots!; " + key)); - return; +var encodeKeyString_1 = __importDefault(require("./encodeKeyString")); +var exportKey_1 = __importDefault(require("./exportKey")); +function saveKeysComb(signKeys, encryptionKeys) { + return __awaiter(this, void 0, void 0, function () { + var skpub, skpriv, ekpub, ekpriv, jsonKeys; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4 /*yield*/, (0, exportKey_1.default)("spki", signKeys.publicKey)]; + case 1: + skpub = _a.sent(); + return [4 /*yield*/, (0, exportKey_1.default)("pkcs8", signKeys.privateKey)]; + case 2: + skpriv = _a.sent(); + return [4 /*yield*/, (0, exportKey_1.default)("spki", encryptionKeys.publicKey)]; + case 3: + ekpub = _a.sent(); + return [4 /*yield*/, (0, exportKey_1.default)("pkcs8", encryptionKeys.privateKey)]; + case 4: + ekpriv = _a.sent(); + jsonKeys = { + skpub: (0, encodeKeyString_1.default)(skpub), + skpriv: (0, encodeKeyString_1.default)(skpriv), + ekpub: (0, encodeKeyString_1.default)(ekpub), + ekpriv: (0, encodeKeyString_1.default)(ekpriv), + }; + // ONLY FOR TESTING! NEVER ENABLE IN PROD + // localStorage.setItem("keys", JSON.stringify(jsonKeys)); + return [2 /*return*/, jsonKeys]; + } + }); + }); +} +exports.default = saveKeysComb; + +},{"./encodeKeyString":307,"./exportKey":310}],317:[function(require,module,exports){ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +var getCrypto_1 = __importDefault(require("../../getCrypto")); +var stringToArrayBuffer_1 = __importDefault(require("../stringToArrayBuffer")); +function verifyData(data, signature, publicKey, hashName) { + if (hashName === void 0) { hashName = "SHA-256"; } + var crypto = (0, getCrypto_1.default)(); + return crypto.subtle.verify({ + name: "ECDSA", + hash: { name: hashName }, // can be "SHA-1", "SHA-256", "SHA-384", or "SHA-512" + }, publicKey, // from generateKey or importKey above + signature, // ArrayBuffer of the signature + (0, stringToArrayBuffer_1.default)(data) // ArrayBuffer of the data + ); +} +exports.default = verifyData; + +},{"../../getCrypto":261,"../stringToArrayBuffer":329}],318:[function(require,module,exports){ +(function (global){(function (){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +function fromBase64(str) { + return decodeURIComponent(escape(global.atob(str))); +} +exports.default = fromBase64; + +}).call(this)}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{}],319:[function(require,module,exports){ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +var getCrypto_1 = __importDefault(require("../getCrypto")); +function generateIv() { + var crypto = (0, getCrypto_1.default)(); + return crypto.getRandomValues(new Uint8Array(12)); +} +exports.default = generateIv; + +},{"../getCrypto":261}],320:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var __1 = require(".."); +function getPeerSignature(privateKey, topic, timestamp, host, port) { + var dataToSign = (0, __1.sha256)(topic + "-" + timestamp + "-" + host + ":" + port); + return (0, __1.signData)(dataToSign, privateKey, "SHA-1").then(__1.arrayBufferToBase64); +} +exports.default = getPeerSignature; + +},{"..":262}],321:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +function hexToArrayBuffer(hex) { + var pairs = hex.toUpperCase().match(/[\dA-F]{2}/gi); + if (!pairs) + return new Uint8Array(); + // convert the octets to integers + var integers = pairs.map(function (s) { + return parseInt(s, 16); + }); + var array = new Uint8Array(integers); + return array.buffer; +} +exports.default = hexToArrayBuffer; + +},{}],322:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +function indexedb(dbName) { + if (dbName === void 0) { dbName = "tooldb"; } + var db = null; + var store = { + start: function () { + // + }, + put: function (key, data, callback) { + // + }, + get: function (key, callback) { + // + }, + query: function (key) { return Promise.resolve([]); }, + quit: function () { + // + }, + }; + store.start = function () { + // console.warn("store start"); + var open = indexedDB.open(dbName, 1); + open.onupgradeneeded = function (eve) { + eve.target.result.createObjectStore(dbName); + }; + open.onsuccess = function () { + db = open.result; + }; + open.onerror = function (eve) { + console.warn(eve || 1); + }; + }; + store.start(); + store.quit = function () { + // console.warn("store quit"); + if (db) { + db.close(); + db = null; } - if (!_this.user) { - reject(new Error("You need to log in before you can PUT.")); + }; + store.put = function (key, data, cb) { + // console.warn("store put", key); + if (!db) { + setTimeout(function () { + store.put(key, data, cb); + }, 1); return; } - var timestamp = new Date().getTime(); - var encodedData = JSON.stringify(value.map(_1.uint8ToBase64)); - var dataString = "" + encodedData + _this.user.pubKey + timestamp; - // WORK - (0, proofOfWork_1.default)(dataString, _this.options.pow) - .then(function (_a) { - var _b; - var hash = _a.hash, nonce = _a.nonce; - if ((_b = _this.user) === null || _b === void 0 ? void 0 : _b.keys) { - // Sign our value - (0, signData_1.default)(hash, _this.user.keys.signKeys.privateKey) - .then(function (signature) { return __awaiter(_this, void 0, void 0, function () { - var data, finalMessage; - var _a, _b; - return __generator(this, function (_c) { - data = { - k: userNamespaced ? ":" + ((_a = this.user) === null || _a === void 0 ? void 0 : _a.pubKey) + "." + key : key, - p: ((_b = this.user) === null || _b === void 0 ? void 0 : _b.pubKey) || "", - n: nonce, - t: timestamp, - h: hash, - s: (0, _1.arrayBufferToBase64)(signature), - v: encodedData, + var tx = db.transaction([dbName], "readwrite"); + var obj = tx.objectStore(dbName); + var req = obj.put(data, "" + key); + if (cb) { + req.onsuccess = + obj.onsuccess = + tx.onsuccess = + function () { + cb(false); }; - this.logger("PUT CRDT > " + key, data); - finalMessage = __assign({ type: "crdtPut", id: (0, _1.textRandom)(10), to: [] }, data); - this.network.sendToAll(finalMessage); - resolve(finalMessage); - return [2 /*return*/]; - }); - }); }) - .catch(reject); + req.onabort = + obj.onabort = + tx.onabort = + function (eve) { + cb(eve || "put.tx.abort"); + }; + req.onerror = + obj.onerror = + tx.onerror = + function (eve) { + cb(eve || "put.tx.error"); + }; + } + }; + store.get = function (key, cb) { + // console.warn("store get", key); + if (!db) { + setTimeout(function () { + store.get(key, cb); + }, 9); + return; + } + var tx = db.transaction([dbName], "readonly"); + var obj = tx.objectStore(dbName); + var req = obj.get("" + key); + req.onsuccess = function () { + cb(false, req.result); + }; + req.onabort = function (eve) { + cb(eve || 4); + }; + req.onerror = function (eve) { + cb(eve || 5); + }; + }; + store.query = function (key) { + return new Promise(function (resolve, reject) { + try { + var keyRange = IDBKeyRange.bound(key, key + "|", true, true); + var tx = db.transaction([dbName], "readonly"); + var obj = tx.objectStore(dbName); + var keysArray_1 = []; + obj.openCursor(keyRange).onsuccess = function (event) { + var cursor = event.target.result; + if (cursor) { + keysArray_1.push(event.target.result.key); + cursor.continue(); + } + else { + resolve(keysArray_1); + } + }; } - }) - .catch(reject); - }); + catch (error) { + reject(error); + } + }); + }; + setInterval(function () { + db && db.close(); + db = null; + store.start(); + }, 1000 * 15); // reset webkit bug? + return store; } -exports.default = toolDbCrdtPut; +exports.default = indexedb; -},{".":304,"./utils/proofOfWork":366,"./utils/signData":370}],322:[function(require,module,exports){ +},{}],323:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -var _1 = require("."); -/** - * Triggers a FUNCTION request to other peers. If the function executes sucessfully it will return code "OK" - * @param function function name - * @param args arguments for the function - * @param timeout Max time to wait for remote. - * @returns Promise - */ -function toolDbFunction(fName, args, timeoutMs) { - var _this = this; - if (timeoutMs === void 0) { timeoutMs = 10000; } - return new Promise(function (resolve, reject) { - _this.logger("FUNCTION > " + fName); - var msgId = (0, _1.textRandom)(10); - var cancelTimeout = setTimeout(function () { - resolve({ return: "Timed out", code: "ERR" }); - }, timeoutMs); - _this.addIdListener(msgId, function (msg) { - _this.logger("FUNCTION RECV > " + fName, msg); - clearTimeout(cancelTimeout); - if (msg.type === "functionReturn") { - resolve({ return: msg.return, code: msg.code }); +function leveldb(dbName) { + if (dbName === void 0) { dbName = "tooldb"; } + var level = require("level"); + var db = null; + var store = { + start: function () { + // + }, + put: function (key, data, callback) { + // + }, + get: function (key, callback) { + // + }, + query: function (key) { return Promise.resolve([]); }, + quit: function () { + // + }, + }; + store.start = function () { + db = level(dbName); + }; + store.start(); + store.quit = function () { + db.close(); + }; + store.put = function (key, data, cb) { + db.put(key, data, function (err) { + if (err) { + if (cb) + cb(err); + } + else { + if (cb) + cb(false); } }); - // Do get - _this.network.sendToAll({ - type: "function", - to: [], - function: fName, - args: args, - id: msgId, + }; + store.get = function (key, cb) { + // console.warn("store get", key); + if (!db) { + setTimeout(function () { + store.get(key, cb); + }, 9); + return; + } + db.get(key, function (err, value) { + if (err) { + if (cb) + cb(err); + } + else { + if (cb) + cb(false, value); + } + }); + }; + store.query = function (key) { + return new Promise(function (resolve, reject) { + try { + var array_1 = []; + db.createKeyStream({ + gte: key, + lte: key + "\uffff", + }) + .on("data", function (data) { + // if (data.startsWith(key)) { + array_1.push(data); + // } + }) + .on("error", function (err) { + reject(err); + }) + .on("close", function () { + resolve(array_1); + }); + } + catch (error) { + reject(error); + } }); + }; + return store; +} +exports.default = leveldb; + +},{"level":234}],324:[function(require,module,exports){ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +var sha256_1 = __importDefault(require("./sha256")); +function proofOfWork(value, difficulty) { + return new Promise(function (resolve) { + var nonce = 0; + var hash = (0, sha256_1.default)("" + value + nonce); + while (hash.substring(0, difficulty) !== Array(difficulty + 1).join("0")) { + nonce += 1; + hash = (0, sha256_1.default)("" + value + nonce); + } + resolve({ nonce: nonce, hash: hash }); }); } -exports.default = toolDbFunction; +exports.default = proofOfWork; + +},{"./sha256":327}],325:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var animals = [ + "Pug", + "Chicken", + "Slug", + "Snail", + "Pig", + "Cow", + "Sheep", + "Horse", + "Squirrel", + "Turtle", + "Unicorn", + "Dragon", + "Dolphin", + "Cat", + "Chow Chow", + "Elephant", + "Meerkat", + "Polar Bear", + "Bear", + "Rabbit", + "Koala", + "Parrot", + "Raven", + "Frog", + "Rat", + "Mouse", + "Bee", + "Tiger", + "Lion", + "Giraffe", + "Ant", + "Spider", + "Zebra", +]; +function randomAnimal() { + return animals[Math.round(Math.random() * animals.length)]; +} +exports.default = randomAnimal; + +},{}],326:[function(require,module,exports){ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +var crypto_1 = __importDefault(require("crypto")); +function sha1(str, hex) { + if (hex === void 0) { hex = true; } + var hash = crypto_1.default.createHash("sha1"); + hash.update(str); + return hash.digest(hex ? "hex" : "base64"); +} +exports.default = sha1; + +},{"crypto":131}],327:[function(require,module,exports){ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +var crypto_1 = __importDefault(require("crypto")); +function sha256(str, hex) { + if (hex === void 0) { hex = true; } + var hash = crypto_1.default.createHash("sha256"); + hash.update(str); + return hash.digest(hex ? "hex" : "base64"); +} +exports.default = sha256; -},{".":304}],323:[function(require,module,exports){ +},{"crypto":131}],328:[function(require,module,exports){ "use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; Object.defineProperty(exports, "__esModule", { value: true }); -var _1 = require("."); -/** - * Triggers a GET request to other peers. If the data is available locally it will return that instead. - * @param key key of the data - * @param userNamespaced If this key bolongs to a user or its public. Making it private will enforce validation for our public key and signatures. - * @param timeout Max time to wait for remote. - * @returns Promise - */ -function toolDbGet(key, userNamespaced, timeoutMs) { - var _this = this; - if (userNamespaced === void 0) { userNamespaced = false; } - if (timeoutMs === void 0) { timeoutMs = 1000; } - return new Promise(function (resolve, reject) { - var _a, _b; - if (userNamespaced && ((_a = _this.user) === null || _a === void 0 ? void 0 : _a.pubKey) === undefined) { - reject(new Error("You are not authorized yet!")); - return; - } - var finalKey = userNamespaced ? ":" + ((_b = _this.user) === null || _b === void 0 ? void 0 : _b.pubKey) + "." + key : key; - _this.logger("GET > " + finalKey); - var msgId = (0, _1.textRandom)(10); - var cancelTimeout = setTimeout(function () { - _this.store.get(finalKey, function (err, data) { - if (data) { - try { - var message = JSON.parse(data); - resolve(message.v); - } - catch (e) { - resolve(null); - } - } - else { - resolve(null); - } - }); - }, timeoutMs); - _this.addIdListener(msgId, function (msg) { - _this.logger("GET RECV > " + finalKey, msg); - clearTimeout(cancelTimeout); - if (msg.type === "put") { - resolve(msg.v); - } - }); - _this.store.get(finalKey, function (err, data) { - if (data) { - try { - var val = JSON.parse(data).v; - clearTimeout(cancelTimeout); - _this.removeIdListener(msgId); - resolve(val); - } - catch (e) { - // do nothing - } - } - }); - // Do get - _this.network.sendToAll({ - type: "get", - to: [], - key: finalKey, - id: msgId, - }); - }); +var getCrypto_1 = __importDefault(require("../getCrypto")); +var stringToArrayBuffer_1 = __importDefault(require("./stringToArrayBuffer")); +function signData(data, privateKey, hashName) { + if (hashName === void 0) { hashName = "SHA-256"; } + var crypto = (0, getCrypto_1.default)(); + return crypto.subtle.sign({ + name: "ECDSA", + hash: { name: hashName }, // can be "SHA-1", "SHA-256", "SHA-384", or "SHA-512" + }, privateKey, // from generateKey or importKey above + (0, stringToArrayBuffer_1.default)(data) // ArrayBuffer of data you want to sign + ); } -exports.default = toolDbGet; +exports.default = signData; -},{".":304}],324:[function(require,module,exports){ +},{"../getCrypto":261,"./stringToArrayBuffer":329}],329:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -function toolDbGetPubKey() { - if (this.pubKey === "" || this.pubKey === undefined) { - throw new Error("You are not authorized yet."); +function stringToArrayBuffer(str) { + var buf = new ArrayBuffer(str.length); + var bufView = new Uint8Array(buf); + for (var i = 0, strLen = str.length; i < strLen; i += 1) { + bufView[i] = str.charCodeAt(i); } - return this.pubKey; + return buf; } -exports.default = toolDbGetPubKey; +exports.default = stringToArrayBuffer; + +},{}],330:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +function textRandom(_l, _c) { + if (_l === void 0) { _l = 24; } + var l = _l; + var s = ""; + var c = _c || "0123456789ABCDEFGHIJKLMNOPQRSTUVWXZabcdefghijklmnopqrstuvwxyz"; + while (l > 0) { + s += c.charAt(Math.floor(Math.random() * c.length)); + l -= 1; + } + return s; +} +exports.default = textRandom; + +},{}],331:[function(require,module,exports){ +(function (global){(function (){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +function toBase64(str) { + return global.btoa(unescape(encodeURIComponent(str))); +} +exports.default = toBase64; -},{}],325:[function(require,module,exports){ +}).call(this)}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{}],332:[function(require,module,exports){ "use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); -var encodeKeyString_1 = __importDefault(require("./utils/crypto/encodeKeyString")); -var exportKey_1 = __importDefault(require("./utils/crypto/exportKey")); -var randomAnimal_1 = __importDefault(require("./utils/randomAnimal")); -function toolDbKeysSignIn(keys, username) { - var _this = this; - return (0, exportKey_1.default)("spki", keys.signKeys.publicKey) - .then(function (skpub) { return (0, encodeKeyString_1.default)(skpub); }) - .then(function (pubKey) { - _this.user = { - keys: keys, - name: username || "Anonymous " + (0, randomAnimal_1.default)(), - pubKey: pubKey, - }; - return keys; - }); +var toBase64_1 = __importDefault(require("./toBase64")); +function uint8ToBase64(byteArray) { + var byteString = ""; + for (var i = 0; i < byteArray.byteLength; i += 1) { + byteString += String.fromCodePoint(byteArray[i]); + } + return (0, toBase64_1.default)(byteString); } -exports.default = toolDbKeysSignIn; +exports.default = uint8ToBase64; -},{"./utils/crypto/encodeKeyString":349,"./utils/crypto/exportKey":352,"./utils/randomAnimal":367}],326:[function(require,module,exports){ +},{"./toBase64":331}],333:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +function uniq(array) { + return Array.from(new Set(array)); +} +exports.default = uniq; + +},{}],334:[function(require,module,exports){ "use strict"; -var __extends = (this && this.__extends) || (function () { - var extendStatics = function (d, b) { - extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; - return extendStatics(d, b); - }; - return function (d, b) { - if (typeof b !== "function" && b !== null) - throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -})(); -var __assign = (this && this.__assign) || function () { - __assign = Object.assign || function(t) { - for (var s, i = 1, n = arguments.length; i < n; i++) { - s = arguments[i]; - for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) - t[p] = s[p]; - } - return t; - }; - return __assign.apply(this, arguments); -}; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { @@ -66086,5777 +64613,7068 @@ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); -var ws_1 = __importDefault(require("ws")); -var _1 = require("."); -var arrayBufferToHex_1 = __importDefault(require("./utils/arrayBufferToHex")); -var waitFor_1 = __importDefault(require("./utils/waitFor")); -var defaultTrackerUrls = [ - "wss://tracker.webtorrent.dev", - "wss://tracker.openwebtorrent.com", - "wss://tracker.files.fm:7073/announce", - "wss://tooldb-tracker.herokuapp.com/", - //"wss://tracker.fastcast.nz/announce", - //"wss://tracker.btorrent.xyz/announce", - //"wss://tracker.webtorrent.io/announce", - //"wss://spacetradersapi-chatbox.herokuapp.com:443/announce", -]; -var ToolDbNetwork = /** @class */ (function (_super) { - __extends(ToolDbNetwork, _super); - function ToolDbNetwork(db) { - var _this_1 = _super.call(this, db) || this; - _this_1._window = typeof window === "undefined" ? undefined : window; - _this_1.isNode = typeof jest !== "undefined" || typeof window === "undefined"; - _this_1.isWebWorker = typeof window === "undefined" && - typeof self !== "undefined" && - self.document === undefined; - _this_1.wss = !_this_1.isNode && !_this_1.isWebWorker && _this_1._window - ? _this_1._window.WebSocket || - _this_1._window.webkitWebSocket || - _this_1._window.mozWebSocket - : _this_1.isWebWorker - ? WebSocket - : ws_1.default; - _this_1.sockets = {}; - _this_1.socketListeners = {}; - _this_1.serverPeerData = {}; - _this_1.serversBlacklist = []; - _this_1.serversFinding = []; - _this_1.trackerUrls = defaultTrackerUrls; // .slice(0, 2); - _this_1.handledOffers = {}; - _this_1._awaitingConnections = {}; - _this_1.server = null; - // We need to create a queue to handle a situation when we need - // to contact a server, but we havent connected to it yet. - _this_1._messageQueue = []; - _this_1.removeFromAwaiting = function (pubkey) { - if (_this_1._awaitingConnections[pubkey]) { - delete _this_1._awaitingConnections[pubkey]; - } - }; - /** - * Makes a websocket connection to a tracker - */ - _this_1.makeSocket = function (url) { - return new Promise(function (resolve) { - if (!_this_1.sockets[url]) { - // this.tooldb.logger("begin tracker connection " + url); - _this_1.socketListeners[url] = _this_1.onSocketMessage; - try { - var socket_1 = new _this_1.wss(url); - _this_1.sockets[url] = socket_1; - // eslint-disable-next-line @typescript-eslint/no-this-alias - var _this = _this_1; - socket_1.onopen = function () { - // _this.tooldb.logger("tracker connected " + url); - resolve(this); - }; - socket_1.onmessage = function (e) { return _this_1.socketListeners[url](socket_1, e); }; - // eslint-disable-next-line func-names - socket_1.onerror = function () { - // removing trackers just because the error event seems like a mistake - // trackers can get disconnected and be absolutely healthy. - // const index = this.trackerUrls.indexOf(url); - // this.trackerUrls.splice(index, 1); - delete _this_1.sockets[url]; - resolve(null); - }; - socket_1.onclose = function () { - delete _this_1.sockets[url]; - // this.tooldb.logger("tracker closed " + url); - }; - } - catch (e) { - // this.tooldb.logger("makeSocket error " + url, e); - resolve(null); - } - } - else { - resolve(_this_1.sockets[url]); - } - }); - }; - /* - * Make a serverPeerData object from our keys - */ - _this_1.getServerPeerData = function () { - return new Promise(function (resolve, reject) { - var _a, _b; - if ((_a = _this_1.tooldb.options.defaultKeys) === null || _a === void 0 ? void 0 : _a.privateKey) { - (0, _1.signData)(_this_1.tooldb.options.host, (_b = _this_1.tooldb.options.defaultKeys) === null || _b === void 0 ? void 0 : _b.privateKey).then(function (signature) { - var data = { - host: _this_1.tooldb.options.host, - port: _this_1.tooldb.options.port, - ssl: _this_1.tooldb.options.ssl, - name: _this_1.tooldb.options.serverName, - pubKey: _this_1.tooldb.getPubKey(), - signature: (0, arrayBufferToHex_1.default)(signature), - }; - resolve(data); - }); - } - else { - reject(); - } - }); - }; - /** - * Announce ourselves to a tracker (send "announce") - */ - _this_1.announce = function (socket, infoHash) { return __awaiter(_this_1, void 0, void 0, function () { - var pubKey, message; - return __generator(this, function (_a) { - pubKey = this.getClientAddress(); - // this.tooldb.logger("announce", infoHash, pubKey); - if (pubKey) { - if (this.tooldb.options.server) { - this.getServerPeerData().then(function (offer) { - var offers = [0, 1, 2].map(function (n) { - return { - offer: { sdp: JSON.stringify(offer), type: "offer" }, - offer_id: (0, _1.textRandom)(20), - }; - }); - // this.tooldb.logger("announce offer", offer); - var message = { - action: "announce", - info_hash: infoHash, - peer_id: pubKey.slice(-20), - numwant: 1, - offers: offers, - }; - socket.send(JSON.stringify(message)); - }); - } - else { - message = { - action: "announce", - info_hash: infoHash, - peer_id: pubKey.slice(-20), - numwant: 1, - }; - socket.send(JSON.stringify(message)); - // this.tooldb.logger("announce message", message); - } - } - return [2 /*return*/]; - }); - }); }; - /** - * Announce ourselves to all trackers - */ - _this_1.announceAll = function () { return __awaiter(_this_1, void 0, void 0, function () { - var infoHash; - var _this_1 = this; - return __generator(this, function (_a) { - infoHash = this.codeToHash(this.tooldb.getPubKey()); - // this.tooldb.logger(`announce all start`); - this.trackerUrls.forEach(function (url, index) { return __awaiter(_this_1, void 0, void 0, function () { - var socket; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: return [4 /*yield*/, this.makeSocket(url)]; - case 1: - socket = _a.sent(); - //this.tooldb.logger(" ok tracker " + url); - // this.tooldb.logger("socket", url, index); - if (socket && socket.readyState === 1) { - //this.tooldb.logger("announce to " + url); - this.announce(socket, infoHash); - } - return [2 /*return*/]; - } - }); - }); }); - return [2 /*return*/]; - }); - }); }; - /** - * Announce on trackers for a server - * Connects to it if found - */ - _this_1.findServer = function (serverKey) { return __awaiter(_this_1, void 0, void 0, function () { - var infoHash_1; - var _this_1 = this; - return __generator(this, function (_a) { - if (!this.serversFinding.includes(serverKey)) { - this.serversFinding.push(serverKey); - infoHash_1 = this.codeToHash(serverKey); - this.tooldb.logger("findServer: \"" + serverKey + "\" (" + infoHash_1 + ")"); - this.trackerUrls.forEach(function (url) { return __awaiter(_this_1, void 0, void 0, function () { - var socket; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: return [4 /*yield*/, this.makeSocket(url)]; - case 1: - socket = _a.sent(); - // this.tooldb.logger(`socket:`, socket, url, socket?.readyState); - if (socket && socket.readyState === 1) { - this.announce(socket, infoHash_1); - } - return [2 /*return*/]; - } - }); - }); }); - } - return [2 /*return*/]; - }); - }); }; - _this_1.stopAnnounce = function () { - Object.values(_this_1.sockets).forEach(function (socket) { - if (socket) { - socket.terminate(); - socket.close(); - } - }); - if (_this_1.announceInterval) { - clearInterval(_this_1.announceInterval); - } - }; - /** - * Handle the tracker messages - */ - _this_1.onSocketMessage = function (socket, e) { return __awaiter(_this_1, void 0, void 0, function () { - var val, failure, serverData_1; - var _a; - return __generator(this, function (_b) { - try { - val = JSON.parse(e.data); - // this.tooldb.logger("onSocketMessage", socket.url, val); - } - catch (_e) { - this.tooldb.logger("Received malformed JSON", e.data); - return [2 /*return*/]; - } - failure = val["failure reason"]; - if (failure) { - // this.tooldb.logger(`${e.origin}: torrent tracker failure (${failure})`); - return [2 /*return*/]; - } - if (val.peer_id && val.peer_id === ((_a = this.getClientAddress()) === null || _a === void 0 ? void 0 : _a.slice(-20))) { - // this.tooldb.logger("Peer ids mismatch", val.peer_id, selfId); - return [2 /*return*/]; - } - if (val.offer && val.offer_id) { - if (this.handledOffers[val.offer_id]) { - return [2 /*return*/]; - } - this.handledOffers[val.offer_id] = true; - serverData_1 = JSON.parse(val.offer.sdp); - if (this.tooldb.serverPeers.filter(function (s) { return s.pubkey === serverData_1.pubKey; }) - .length === 0 && - !this._awaitingConnections[serverData_1.pubKey] && - !this.serverPeerData[serverData_1.pubKey] && - this.serversBlacklist.indexOf(serverData_1.pubKey) === -1) { - console.log("Now we connect to ", serverData_1); - this.connectTo(serverData_1); - } - else { - // we already connected, unplug all trackers/unsubscribe - } - return [2 /*return*/]; - } - return [2 /*return*/]; - }); - }); }; - /** - * Open a connection to a server - * @param url URL of the server (including port) - * @returns websocket - */ - _this_1.connectTo = function (serverPeer) { - _this_1.tooldb.logger("connectTo:", serverPeer); - try { - var wsUrl = serverPeer.ssl - ? "wss://" + serverPeer.host - : "ws://" + serverPeer.host + ":" + serverPeer.port; - var wss_1 = new _this_1.wss(wsUrl); - var clientId_1 = serverPeer.pubKey; - // this.serverPeers.push(serverPeer); - // Unlike other network adapters, we can just use the public key - // to identify connections. - // Therefore, we dont have to wait for a pong message to - // initialize these internal functions - _this_1.isClientConnected[serverPeer.pubKey] = function () { - return wss_1.readyState === wss_1.OPEN; - }; - _this_1.clientSocket[serverPeer.pubKey] = wss_1; - _this_1.clientToSend[serverPeer.pubKey] = function (_msg) { - wss_1.send(_msg); - }; - var previousConnection = _this_1._awaitingConnections[serverPeer.pubKey]; - if (previousConnection) { - // this.tooldb.logger("previousConnection"); - _this_1._awaitingConnections[serverPeer.pubKey].socket = wss_1; - } - else { - // this.tooldb.logger("new connection"); - _this_1._awaitingConnections[serverPeer.pubKey] = { - socket: wss_1, - tries: 0, - defer: null, - server: __assign({}, serverPeer), - }; - } - wss_1.onclose = function (_error) { - _this_1.tooldb.logger("wss.onclose", serverPeer); - _this_1.checkDisconnetion(); - if (_this_1.serversBlacklist.indexOf(serverPeer.pubKey) === -1) { - _this_1.reconnect(serverPeer.pubKey); - } - }; - wss_1.onerror = function (_error) { - var _a; - _this_1.tooldb.logger("wss.onerror", serverPeer); - _this_1.checkDisconnetion(); - if (((_a = _error === null || _error === void 0 ? void 0 : _error.error) === null || _a === void 0 ? void 0 : _a.code) !== "ETIMEDOUT" && - _this_1.serversBlacklist.indexOf(serverPeer.pubKey) === -1) { - _this_1.reconnect(serverPeer.pubKey); +var sha256_1 = __importDefault(require("./sha256")); +var message_1 = require("../types/message"); +var decodeKeyString_1 = __importDefault(require("./crypto/decodeKeyString")); +var importKey_1 = __importDefault(require("./crypto/importKey")); +var verifyData_1 = __importDefault(require("./crypto/verifyData")); +var __1 = require(".."); +/** + * Verifies a message validity (PoW, pubKey, timestamp, signatures) + * @param msg AnyMessage + * @param pow amount of proof of work required, number of leading zeroes (default is 0/no pow) + * @returns boolean or undefined if the message type does not match + */ +function verifyMessage(msg, pow) { + if (pow === void 0) { pow = 0; } + return __awaiter(this, void 0, void 0, function () { + var strData, publicKeyNamespace, key_1, data, pubKeyString, pubKey, verified; + var _this = this; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + strData = JSON.stringify(msg.v); + if (msg.t === undefined || + msg.k === undefined || + msg.h === undefined || + msg.p === undefined || + msg.s === undefined) { + return [2 /*return*/, message_1.VerifyResult.InvalidData]; } - }; - wss_1.onopen = function () { - _this_1.removeFromAwaiting(serverPeer.pubKey); - _this_1.tooldb.logger("Connected to " + serverPeer.host + ":" + serverPeer.port + " sucessfully."); - // hi peer - _this_1.craftPingMessage().then(function (msg) { - wss_1.send(msg); - }); - _this_1.serverPeerData[serverPeer.pubKey] = serverPeer; - }; - wss_1.onmessage = function (msg) { - if (!msg) { - return; + // Max clock shift allowed is 30 seconds. + // Ten seconds was my original threshold but it failed some times. + if (msg.t > new Date().getTime() + 30000) { + // console.warn("Invalid message timestamp."); + return [2 /*return*/, message_1.VerifyResult.InvalidTimestamp]; } - _this_1.onClientMessage(msg.data, clientId_1, function (id) { - clientId_1 = id; - }); - }; - return wss_1; - } - catch (e) { - _this_1.tooldb.logger("onconnect err", e); - } - return undefined; - }; - _this_1.reconnect = function (pubkey) { - var connection = _this_1._awaitingConnections[pubkey]; - if (connection) { - if (connection.defer) { - clearTimeout(connection.defer); - } - _this_1.tooldb.logger("tries: " + connection.tries); - if (connection.tries < _this_1.tooldb.options.maxRetries) { - var defer = function () { - _this_1._awaitingConnections[pubkey].tries += 1; - _this_1.tooldb.logger("connection to " + connection.server.host + ":" + connection.server.port + " retry in " + connection.tries * 2 + " seconds."); - setTimeout(function () { - _this_1.connectTo(connection.server); - }, connection.tries * 2000); - }; - connection.defer = setTimeout(defer, _this_1.tooldb.options.wait); - } - else { - _this_1.tooldb.logger("connection attempts to " + connection.server.host + ":" + connection.server.port + " exceeded,"); - _this_1.removeFromAwaiting(pubkey); - } - } - else { - _this_1.connectTo(_this_1.serverPeerData[pubkey]); - } - }; - _this_1.disconnect = function (pubKey) { - _this_1.tooldb.logger("disconnecting from " + pubKey); - var wss = _this_1.clientSocket[pubKey]; - if (wss && wss.readyState === wss.OPEN) { - wss.close(); - wss.onclose = function () { - _this_1.tooldb.logger("disconnected from " + pubKey + " sucessfully"); - }; - } - _this_1.removeFromAwaiting(pubKey); - _this_1.checkDisconnetion(); - }; - setInterval(function () { - _this_1.tryExecuteMessageQueue(); - }, 500); - // eslint-disable-next-line @typescript-eslint/no-this-alias - var _this = _this_1; - if (_this.tooldb.options.server) { - (0, waitFor_1.default)(function () { - try { - return _this.tooldb.getPubKey() !== undefined; - } - catch (_a) { - return false; - } - }).then(function () { - // Announce every 10 seconds indefinitely - setTimeout(function () { - _this.announceInterval = setInterval(_this.announceAll, 10000); - _this.announceAll(); - }, 500); - }); - } - // Basically the same as the WS network adapter - // Only for Node! - if (_this_1.tooldb.options.server && _this_1.isNode) { - _this_1.server = new ws_1.default.Server({ - port: _this_1.tooldb.options.port, - server: _this_1.tooldb.options.httpServer, - }); - _this_1.server.on("connection", function (socket) { - var clientId = null; - socket.on("close", function () { - if (clientId) { - _this_1.onClientDisconnect(clientId); + publicKeyNamespace = false; + if (msg.k.slice(0, 1) == ":") { + publicKeyNamespace = msg.k.split(".")[0].slice(1); } - }); - socket.on("error", function () { - if (clientId) { - _this_1.onClientDisconnect(clientId); + if (!(msg.k.slice(0, 2) == "==")) return [3 /*break*/, 2]; + key_1 = msg.k; + return [4 /*yield*/, new Promise(function (resolve) { + _this.store.get(key_1, function (err, data) { + if (data) { + try { + var message = JSON.parse(data); + resolve(message); + } + catch (e) { + resolve(null); + } + } + else { + resolve(null); + } + }); + })]; + case 1: + data = _a.sent(); + if (data && data.p !== msg.p) + return [2 /*return*/, message_1.VerifyResult.CantOverwrite]; + _a.label = 2; + case 2: + pubKeyString = msg.p; + if (publicKeyNamespace && publicKeyNamespace !== pubKeyString) { + // console.warn("Provided pub keys do not match"); + return [2 /*return*/, message_1.VerifyResult.PubKeyMismatch]; } - }); - socket.on("message", function (message) { - _this_1.onClientMessage(message, clientId || "", function (id) { - clientId = id; - _this_1.isClientConnected[id] = function () { - return socket.readyState === socket.OPEN; - }; - _this_1.clientSocket[id] = socket; - _this_1.clientToSend[id] = function (_msg) { - socket.send(_msg); - }; - }); - }); - }); - } - return _this_1; - } - Object.defineProperty(ToolDbNetwork.prototype, "messageQueue", { - get: function () { - return this._messageQueue; - }, - enumerable: false, - configurable: true - }); - ToolDbNetwork.prototype.checkDisconnetion = function () { - if (Object.values(this.clientSocket).every(function (s) { - return s.readyState !== s.OPEN; - })) { - this.tooldb.onDisconnect(); - this.tooldb.isConnected = false; - } - }; - ToolDbNetwork.prototype.pushToMessageQueue = function (msg, to) { - this._messageQueue.push({ - message: msg, - time: Date.now(), - to: to, - }); - }; - ToolDbNetwork.prototype.codeToHash = function (code) { - return (0, _1.sha1)(code).slice(-20); - }; - ToolDbNetwork.prototype.sendToAll = function (msg, crossServerOnly) { - if (crossServerOnly === void 0) { crossServerOnly = false; } - // this.tooldb.logger("sendToAll", msg, crossServerOnly); - if (crossServerOnly) { - this.sendToAllServers(msg); - } - else { - this.pushToMessageQueue(msg, []); - this.tryExecuteMessageQueue(); - } - }; - ToolDbNetwork.prototype.sendToClientId = function (clientId, msg) { - // this.tooldb.logger("sendToClientId", clientId, msg); - this.pushToMessageQueue(msg, [clientId]); - this.tryExecuteMessageQueue(); - }; - ToolDbNetwork.prototype.sendToAllServers = function (msg) { - var _this_1 = this; - // this.tooldb.logger("sendToAllServers", msg); - var serverPeersList = this.tooldb.serverPeers - .map(function (s) { return s.pubkey; }) - .filter(function (s) { return s !== _this_1.tooldb.getPubKey(); }); - if (serverPeersList.length > 0) { - this.pushToMessageQueue(msg, serverPeersList); - } - this.tryExecuteMessageQueue(); - }; - ToolDbNetwork.prototype.tryExecuteMessageQueue = function () { - var _this_1 = this; - var sentMessageIDs = []; - var messagesToDelete = []; - var pubKey = this.getClientAddress(); - this._messageQueue.forEach(function (q) { - var message = q.message; - if (q.time + 1000 * 60 < Date.now()) { - messagesToDelete.push(message.id); - } - else { - if (pubKey && !message.to.includes(pubKey)) { - message.to.push(pubKey); - } - var finalMessageString_1 = JSON.stringify(message); - if (q.to.length > 0) { - // Send only to select clients - q.to.forEach(function (toClient) { - if (!message.to.includes(toClient) && - _this_1.isClientConnected[toClient] && - _this_1.isClientConnected[toClient]()) { - // this.tooldb.logger("Sending to client", toClient); - _this_1.clientToSend[toClient](finalMessageString_1); - if (sentMessageIDs.indexOf(message.id) === -1) { - sentMessageIDs.push(message.id); - } + // Verify hash and nonce (adjust zeroes for difficulty of the network) + // While this POW does not enforce security per-se, it does make it harder + // for attackers to spam the network, and could be adjusted by peers. + // Disabled for now because it is painful on large requests + if (pow > 0) { + if (msg.h.slice(0, pow) !== new Array(pow).fill("0").join("")) { + // console.warn("No valid hash (no pow)"); + return [2 /*return*/, message_1.VerifyResult.NoProofOfWork]; } - }); - } - else { - // send to all currently connected clients - Object.keys(_this_1.clientToSend).forEach(function (toClient) { - if (!message.to.includes(toClient) && - _this_1.isClientConnected[toClient] && - _this_1.isClientConnected[toClient]()) { - _this_1.clientToSend[toClient](finalMessageString_1); - if (sentMessageIDs.indexOf(message.id) === -1) { - sentMessageIDs.push(message.id); - } + if ((0, sha256_1.default)("" + strData + pubKeyString + msg.t + msg.n) !== msg.h) { + // console.warn("Specified hash does not generate a valid pow"); + return [2 /*return*/, message_1.VerifyResult.InvalidHashNonce]; } - }); - } + } + return [4 /*yield*/, (0, importKey_1.default)((0, decodeKeyString_1.default)(pubKeyString), "spki", "ECDSA", ["verify"])]; + case 3: + pubKey = _a.sent(); + return [4 /*yield*/, (0, verifyData_1.default)(msg.h, (0, __1.base64ToArrayBuffer)(msg.s), pubKey)]; + case 4: + verified = _a.sent(); + // console.warn(`Signature validation: ${verified ? "Sucess" : "Failed"}`); + return [2 /*return*/, verified ? message_1.VerifyResult.Verified : message_1.VerifyResult.InvalidSignature]; } }); - sentMessageIDs.forEach(function (id) { - var index = _this_1._messageQueue.findIndex(function (msg) { return msg.message.id === id; }); - _this_1._messageQueue.splice(index, 1); - }); - messagesToDelete.forEach(function (id) { - var index = _this_1._messageQueue.findIndex(function (msg) { return msg.message.id === id; }); - _this_1._messageQueue.splice(index, 1); - }); - }; - return ToolDbNetwork; -}(_1.ToolDbNetworkAdapter)); -exports.default = ToolDbNetwork; + }); +} +exports.default = verifyMessage; + +},{"..":262,"../types/message":293,"./crypto/decodeKeyString":303,"./crypto/importKey":314,"./crypto/verifyData":317,"./sha256":327}],335:[function(require,module,exports){ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +var __1 = require(".."); +var tooldb_1 = require("../tooldb"); +var hexToArrayBuffer_1 = __importDefault(require("./hexToArrayBuffer")); +function verifyPeer(peer) { + // Import the public key string + return (0, __1.importKey)((0, hexToArrayBuffer_1.default)(tooldb_1.KEY_PREFIX + peer.pubkey), "spki", "ECDSA", ["verify"]).then(function (pubKey) { + return (0, __1.verifyData)((0, __1.sha256)(peer.topic + "-" + peer.timestamp + "-" + peer.host + ":" + peer.port), (0, __1.base64ToArrayBuffer)(peer.sig), pubKey, "SHA-1"); + }); +} +exports.default = verifyPeer; + +},{"..":262,"../tooldb":292,"./hexToArrayBuffer":321}],336:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +function waitFor(fn, interval, timeout) { + if (interval === void 0) { interval = 100; } + if (timeout === void 0) { timeout = 30000; } + return new Promise(function (resolve, reject) { + var intervalFn = setInterval(function () { + if (fn()) { + clearInterval(intervalFn); + clearTimeout(timeoutFn); + resolve(); + } + }, interval); + var timeoutFn = setTimeout(function () { + clearInterval(intervalFn); + reject(); + }, timeout); + }); +} +exports.default = waitFor; + +},{}],337:[function(require,module,exports){ +module.exports={"2.16.840.1.101.3.4.1.1": "aes-128-ecb", +"2.16.840.1.101.3.4.1.2": "aes-128-cbc", +"2.16.840.1.101.3.4.1.3": "aes-128-ofb", +"2.16.840.1.101.3.4.1.4": "aes-128-cfb", +"2.16.840.1.101.3.4.1.21": "aes-192-ecb", +"2.16.840.1.101.3.4.1.22": "aes-192-cbc", +"2.16.840.1.101.3.4.1.23": "aes-192-ofb", +"2.16.840.1.101.3.4.1.24": "aes-192-cfb", +"2.16.840.1.101.3.4.1.41": "aes-256-ecb", +"2.16.840.1.101.3.4.1.42": "aes-256-cbc", +"2.16.840.1.101.3.4.1.43": "aes-256-ofb", +"2.16.840.1.101.3.4.1.44": "aes-256-cfb" +} +},{}],338:[function(require,module,exports){ +// from https://github.com/indutny/self-signed/blob/gh-pages/lib/asn1.js +// Fedor, you are amazing. + +'use strict'; + +var asn1 = require('asn1.js'); + +exports.certificate = require('./certificate'); + +var RSAPrivateKey = asn1.define('RSAPrivateKey', function () { + this.seq().obj( + this.key('version')['int'](), + this.key('modulus')['int'](), + this.key('publicExponent')['int'](), + this.key('privateExponent')['int'](), + this.key('prime1')['int'](), + this.key('prime2')['int'](), + this.key('exponent1')['int'](), + this.key('exponent2')['int'](), + this.key('coefficient')['int']() + ); +}); +exports.RSAPrivateKey = RSAPrivateKey; + +var RSAPublicKey = asn1.define('RSAPublicKey', function () { + this.seq().obj( + this.key('modulus')['int'](), + this.key('publicExponent')['int']() + ); +}); +exports.RSAPublicKey = RSAPublicKey; + +var AlgorithmIdentifier = asn1.define('AlgorithmIdentifier', function () { + this.seq().obj( + this.key('algorithm').objid(), + this.key('none').null_().optional(), + this.key('curve').objid().optional(), + this.key('params').seq().obj( + this.key('p')['int'](), + this.key('q')['int'](), + this.key('g')['int']() + ).optional() + ); +}); + +var PublicKey = asn1.define('SubjectPublicKeyInfo', function () { + this.seq().obj( + this.key('algorithm').use(AlgorithmIdentifier), + this.key('subjectPublicKey').bitstr() + ); +}); +exports.PublicKey = PublicKey; + +var PrivateKeyInfo = asn1.define('PrivateKeyInfo', function () { + this.seq().obj( + this.key('version')['int'](), + this.key('algorithm').use(AlgorithmIdentifier), + this.key('subjectPrivateKey').octstr() + ); +}); +exports.PrivateKey = PrivateKeyInfo; +var EncryptedPrivateKeyInfo = asn1.define('EncryptedPrivateKeyInfo', function () { + this.seq().obj( + this.key('algorithm').seq().obj( + this.key('id').objid(), + this.key('decrypt').seq().obj( + this.key('kde').seq().obj( + this.key('id').objid(), + this.key('kdeparams').seq().obj( + this.key('salt').octstr(), + this.key('iters')['int']() + ) + ), + this.key('cipher').seq().obj( + this.key('algo').objid(), + this.key('iv').octstr() + ) + ) + ), + this.key('subjectPrivateKey').octstr() + ); +}); + +exports.EncryptedPrivateKey = EncryptedPrivateKeyInfo; + +var DSAPrivateKey = asn1.define('DSAPrivateKey', function () { + this.seq().obj( + this.key('version')['int'](), + this.key('p')['int'](), + this.key('q')['int'](), + this.key('g')['int'](), + this.key('pub_key')['int'](), + this.key('priv_key')['int']() + ); +}); +exports.DSAPrivateKey = DSAPrivateKey; + +exports.DSAparam = asn1.define('DSAparam', function () { + this['int'](); +}); + +var ECParameters = asn1.define('ECParameters', function () { + this.choice({ + namedCurve: this.objid() + }); +}); + +var ECPrivateKey = asn1.define('ECPrivateKey', function () { + this.seq().obj( + this.key('version')['int'](), + this.key('privateKey').octstr(), + this.key('parameters').optional().explicit(0).use(ECParameters), + this.key('publicKey').optional().explicit(1).bitstr() + ); +}); +exports.ECPrivateKey = ECPrivateKey; + +exports.signature = asn1.define('signature', function () { + this.seq().obj( + this.key('r')['int'](), + this.key('s')['int']() + ); +}); + +},{"./certificate":339,"asn1.js":34}],339:[function(require,module,exports){ +// from https://github.com/Rantanen/node-dtls/blob/25a7dc861bda38cfeac93a723500eea4f0ac2e86/Certificate.js +// thanks to @Rantanen + +'use strict'; + +var asn = require('asn1.js'); + +var Time = asn.define('Time', function () { + this.choice({ + utcTime: this.utctime(), + generalTime: this.gentime() + }); +}); + +var AttributeTypeValue = asn.define('AttributeTypeValue', function () { + this.seq().obj( + this.key('type').objid(), + this.key('value').any() + ); +}); + +var AlgorithmIdentifier = asn.define('AlgorithmIdentifier', function () { + this.seq().obj( + this.key('algorithm').objid(), + this.key('parameters').optional(), + this.key('curve').objid().optional() + ); +}); + +var SubjectPublicKeyInfo = asn.define('SubjectPublicKeyInfo', function () { + this.seq().obj( + this.key('algorithm').use(AlgorithmIdentifier), + this.key('subjectPublicKey').bitstr() + ); +}); + +var RelativeDistinguishedName = asn.define('RelativeDistinguishedName', function () { + this.setof(AttributeTypeValue); +}); + +var RDNSequence = asn.define('RDNSequence', function () { + this.seqof(RelativeDistinguishedName); +}); + +var Name = asn.define('Name', function () { + this.choice({ + rdnSequence: this.use(RDNSequence) + }); +}); + +var Validity = asn.define('Validity', function () { + this.seq().obj( + this.key('notBefore').use(Time), + this.key('notAfter').use(Time) + ); +}); + +var Extension = asn.define('Extension', function () { + this.seq().obj( + this.key('extnID').objid(), + this.key('critical').bool().def(false), + this.key('extnValue').octstr() + ); +}); + +var TBSCertificate = asn.define('TBSCertificate', function () { + this.seq().obj( + this.key('version').explicit(0)['int']().optional(), + this.key('serialNumber')['int'](), + this.key('signature').use(AlgorithmIdentifier), + this.key('issuer').use(Name), + this.key('validity').use(Validity), + this.key('subject').use(Name), + this.key('subjectPublicKeyInfo').use(SubjectPublicKeyInfo), + this.key('issuerUniqueID').implicit(1).bitstr().optional(), + this.key('subjectUniqueID').implicit(2).bitstr().optional(), + this.key('extensions').explicit(3).seqof(Extension).optional() + ); +}); + +var X509Certificate = asn.define('X509Certificate', function () { + this.seq().obj( + this.key('tbsCertificate').use(TBSCertificate), + this.key('signatureAlgorithm').use(AlgorithmIdentifier), + this.key('signatureValue').bitstr() + ); +}); + +module.exports = X509Certificate; + +},{"asn1.js":34}],340:[function(require,module,exports){ +'use strict'; + +// adapted from https://github.com/apatil/pemstrip +var findProc = /Proc-Type: 4,ENCRYPTED[\n\r]+DEK-Info: AES-((?:128)|(?:192)|(?:256))-CBC,([0-9A-H]+)[\n\r]+([0-9A-z\n\r+/=]+)[\n\r]+/m; +var startRegex = /^-----BEGIN ((?:.*? KEY)|CERTIFICATE)-----/m; +var fullRegex = /^-----BEGIN ((?:.*? KEY)|CERTIFICATE)-----([0-9A-z\n\r+/=]+)-----END \1-----$/m; +var evp = require('evp_bytestokey'); +var ciphers = require('browserify-aes'); +var Buffer = require('safe-buffer').Buffer; +module.exports = function (okey, password) { + var key = okey.toString(); + var match = key.match(findProc); + var decrypted; + if (!match) { + var match2 = key.match(fullRegex); + decrypted = Buffer.from(match2[2].replace(/[\r\n]/g, ''), 'base64'); + } else { + var suite = 'aes' + match[1]; + var iv = Buffer.from(match[2], 'hex'); + var cipherText = Buffer.from(match[3].replace(/[\r\n]/g, ''), 'base64'); + var cipherKey = evp(password, iv.slice(0, 8), parseInt(match[1], 10)).key; + var out = []; + var cipher = ciphers.createDecipheriv(suite, cipherKey, iv); + out.push(cipher.update(cipherText)); + out.push(cipher['final']()); + decrypted = Buffer.concat(out); + } + var tag = key.match(startRegex)[1]; + return { + tag: tag, + data: decrypted + }; +}; + +},{"browserify-aes":91,"evp_bytestokey":173,"safe-buffer":390}],341:[function(require,module,exports){ +'use strict'; + +var asn1 = require('./asn1'); +var aesid = require('./aesid.json'); +var fixProc = require('./fixProc'); +var ciphers = require('browserify-aes'); +var compat = require('pbkdf2'); +var Buffer = require('safe-buffer').Buffer; + +function decrypt(data, password) { + var salt = data.algorithm.decrypt.kde.kdeparams.salt; + var iters = parseInt(data.algorithm.decrypt.kde.kdeparams.iters.toString(), 10); + var algo = aesid[data.algorithm.decrypt.cipher.algo.join('.')]; + var iv = data.algorithm.decrypt.cipher.iv; + var cipherText = data.subjectPrivateKey; + var keylen = parseInt(algo.split('-')[1], 10) / 8; + var key = compat.pbkdf2Sync(password, salt, iters, keylen, 'sha1'); + var cipher = ciphers.createDecipheriv(algo, key, iv); + var out = []; + out.push(cipher.update(cipherText)); + out.push(cipher['final']()); + return Buffer.concat(out); +} + +function parseKeys(buffer) { + var password; + if (typeof buffer === 'object' && !Buffer.isBuffer(buffer)) { + password = buffer.passphrase; + buffer = buffer.key; + } + if (typeof buffer === 'string') { + buffer = Buffer.from(buffer); + } + + var stripped = fixProc(buffer, password); + + var type = stripped.tag; + var data = stripped.data; + var subtype, ndata; + switch (type) { + case 'CERTIFICATE': + ndata = asn1.certificate.decode(data, 'der').tbsCertificate.subjectPublicKeyInfo; + // falls through + case 'PUBLIC KEY': + if (!ndata) { + ndata = asn1.PublicKey.decode(data, 'der'); + } + subtype = ndata.algorithm.algorithm.join('.'); + switch (subtype) { + case '1.2.840.113549.1.1.1': + return asn1.RSAPublicKey.decode(ndata.subjectPublicKey.data, 'der'); + case '1.2.840.10045.2.1': + ndata.subjectPrivateKey = ndata.subjectPublicKey; + return { + type: 'ec', + data: ndata + }; + case '1.2.840.10040.4.1': + ndata.algorithm.params.pub_key = asn1.DSAparam.decode(ndata.subjectPublicKey.data, 'der'); + return { + type: 'dsa', + data: ndata.algorithm.params + }; + default: throw new Error('unknown key id ' + subtype); + } + // throw new Error('unknown key type ' + type) + case 'ENCRYPTED PRIVATE KEY': + data = asn1.EncryptedPrivateKey.decode(data, 'der'); + data = decrypt(data, password); + // falls through + case 'PRIVATE KEY': + ndata = asn1.PrivateKey.decode(data, 'der'); + subtype = ndata.algorithm.algorithm.join('.'); + switch (subtype) { + case '1.2.840.113549.1.1.1': + return asn1.RSAPrivateKey.decode(ndata.subjectPrivateKey, 'der'); + case '1.2.840.10045.2.1': + return { + curve: ndata.algorithm.curve, + privateKey: asn1.ECPrivateKey.decode(ndata.subjectPrivateKey, 'der').privateKey + }; + case '1.2.840.10040.4.1': + ndata.algorithm.params.priv_key = asn1.DSAparam.decode(ndata.subjectPrivateKey, 'der'); + return { + type: 'dsa', + params: ndata.algorithm.params + }; + default: throw new Error('unknown key id ' + subtype); + } + // throw new Error('unknown key type ' + type) + case 'RSA PUBLIC KEY': + return asn1.RSAPublicKey.decode(data, 'der'); + case 'RSA PRIVATE KEY': + return asn1.RSAPrivateKey.decode(data, 'der'); + case 'DSA PRIVATE KEY': + return { + type: 'dsa', + params: asn1.DSAPrivateKey.decode(data, 'der') + }; + case 'EC PRIVATE KEY': + data = asn1.ECPrivateKey.decode(data, 'der'); + return { + curve: data.parameters.value, + privateKey: data.privateKey + }; + default: throw new Error('unknown key type ' + type); + } +} +parseKeys.signature = asn1.signature; + +module.exports = parseKeys; + +},{"./aesid.json":337,"./asn1":338,"./fixProc":340,"browserify-aes":91,"pbkdf2":342,"safe-buffer":390}],342:[function(require,module,exports){ +exports.pbkdf2 = require('./lib/async') +exports.pbkdf2Sync = require('./lib/sync') + +},{"./lib/async":343,"./lib/sync":346}],343:[function(require,module,exports){ +(function (global){(function (){ +var Buffer = require('safe-buffer').Buffer + +var checkParameters = require('./precondition') +var defaultEncoding = require('./default-encoding') +var sync = require('./sync') +var toBuffer = require('./to-buffer') + +var ZERO_BUF +var subtle = global.crypto && global.crypto.subtle +var toBrowser = { + sha: 'SHA-1', + 'sha-1': 'SHA-1', + sha1: 'SHA-1', + sha256: 'SHA-256', + 'sha-256': 'SHA-256', + sha384: 'SHA-384', + 'sha-384': 'SHA-384', + 'sha-512': 'SHA-512', + sha512: 'SHA-512' +} +var checks = [] +function checkNative (algo) { + if (global.process && !global.process.browser) { + return Promise.resolve(false) + } + if (!subtle || !subtle.importKey || !subtle.deriveBits) { + return Promise.resolve(false) + } + if (checks[algo] !== undefined) { + return checks[algo] + } + ZERO_BUF = ZERO_BUF || Buffer.alloc(8) + var prom = browserPbkdf2(ZERO_BUF, ZERO_BUF, 10, 128, algo) + .then(function () { + return true + }).catch(function () { + return false + }) + checks[algo] = prom + return prom +} +var nextTick +function getNextTick () { + if (nextTick) { + return nextTick + } + if (global.process && global.process.nextTick) { + nextTick = global.process.nextTick + } else if (global.queueMicrotask) { + nextTick = global.queueMicrotask + } else if (global.setImmediate) { + nextTick = global.setImmediate + } else { + nextTick = global.setTimeout + } + return nextTick +} +function browserPbkdf2 (password, salt, iterations, length, algo) { + return subtle.importKey( + 'raw', password, { name: 'PBKDF2' }, false, ['deriveBits'] + ).then(function (key) { + return subtle.deriveBits({ + name: 'PBKDF2', + salt: salt, + iterations: iterations, + hash: { + name: algo + } + }, key, length << 3) + }).then(function (res) { + return Buffer.from(res) + }) +} + +function resolvePromise (promise, callback) { + promise.then(function (out) { + getNextTick()(function () { + callback(null, out) + }) + }, function (e) { + getNextTick()(function () { + callback(e) + }) + }) +} +module.exports = function (password, salt, iterations, keylen, digest, callback) { + if (typeof digest === 'function') { + callback = digest + digest = undefined + } + + digest = digest || 'sha1' + var algo = toBrowser[digest.toLowerCase()] + + if (!algo || typeof global.Promise !== 'function') { + getNextTick()(function () { + var out + try { + out = sync(password, salt, iterations, keylen, digest) + } catch (e) { + return callback(e) + } + callback(null, out) + }) + return + } + + checkParameters(iterations, keylen) + password = toBuffer(password, defaultEncoding, 'Password') + salt = toBuffer(salt, defaultEncoding, 'Salt') + if (typeof callback !== 'function') throw new Error('No callback provided to pbkdf2') + + resolvePromise(checkNative(algo).then(function (resp) { + if (resp) return browserPbkdf2(password, salt, iterations, keylen, algo) + + return sync(password, salt, iterations, keylen, digest) + }), callback) +} + +}).call(this)}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"./default-encoding":344,"./precondition":345,"./sync":346,"./to-buffer":347,"safe-buffer":390}],344:[function(require,module,exports){ +(function (process,global){(function (){ +var defaultEncoding +/* istanbul ignore next */ +if (global.process && global.process.browser) { + defaultEncoding = 'utf-8' +} else if (global.process && global.process.version) { + var pVersionMajor = parseInt(process.version.split('.')[0].slice(1), 10) + + defaultEncoding = pVersionMajor >= 6 ? 'utf-8' : 'binary' +} else { + defaultEncoding = 'utf-8' +} +module.exports = defaultEncoding + +}).call(this)}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"_process":350}],345:[function(require,module,exports){ +var MAX_ALLOC = Math.pow(2, 30) - 1 // default in iojs + +module.exports = function (iterations, keylen) { + if (typeof iterations !== 'number') { + throw new TypeError('Iterations not a number') + } + + if (iterations < 0) { + throw new TypeError('Bad iterations') + } + + if (typeof keylen !== 'number') { + throw new TypeError('Key length not a number') + } + + if (keylen < 0 || keylen > MAX_ALLOC || keylen !== keylen) { /* eslint no-self-compare: 0 */ + throw new TypeError('Bad key length') + } +} + +},{}],346:[function(require,module,exports){ +var md5 = require('create-hash/md5') +var RIPEMD160 = require('ripemd160') +var sha = require('sha.js') +var Buffer = require('safe-buffer').Buffer + +var checkParameters = require('./precondition') +var defaultEncoding = require('./default-encoding') +var toBuffer = require('./to-buffer') + +var ZEROS = Buffer.alloc(128) +var sizes = { + md5: 16, + sha1: 20, + sha224: 28, + sha256: 32, + sha384: 48, + sha512: 64, + rmd160: 20, + ripemd160: 20 +} + +function Hmac (alg, key, saltLen) { + var hash = getDigest(alg) + var blocksize = (alg === 'sha512' || alg === 'sha384') ? 128 : 64 + + if (key.length > blocksize) { + key = hash(key) + } else if (key.length < blocksize) { + key = Buffer.concat([key, ZEROS], blocksize) + } + + var ipad = Buffer.allocUnsafe(blocksize + sizes[alg]) + var opad = Buffer.allocUnsafe(blocksize + sizes[alg]) + for (var i = 0; i < blocksize; i++) { + ipad[i] = key[i] ^ 0x36 + opad[i] = key[i] ^ 0x5C + } + + var ipad1 = Buffer.allocUnsafe(blocksize + saltLen + 4) + ipad.copy(ipad1, 0, 0, blocksize) + this.ipad1 = ipad1 + this.ipad2 = ipad + this.opad = opad + this.alg = alg + this.blocksize = blocksize + this.hash = hash + this.size = sizes[alg] +} + +Hmac.prototype.run = function (data, ipad) { + data.copy(ipad, this.blocksize) + var h = this.hash(ipad) + h.copy(this.opad, this.blocksize) + return this.hash(this.opad) +} + +function getDigest (alg) { + function shaFunc (data) { + return sha(alg).update(data).digest() + } + function rmd160Func (data) { + return new RIPEMD160().update(data).digest() + } + + if (alg === 'rmd160' || alg === 'ripemd160') return rmd160Func + if (alg === 'md5') return md5 + return shaFunc +} + +function pbkdf2 (password, salt, iterations, keylen, digest) { + checkParameters(iterations, keylen) + password = toBuffer(password, defaultEncoding, 'Password') + salt = toBuffer(salt, defaultEncoding, 'Salt') + + digest = digest || 'sha1' + + var hmac = new Hmac(digest, password, salt.length) + + var DK = Buffer.allocUnsafe(keylen) + var block1 = Buffer.allocUnsafe(salt.length + 4) + salt.copy(block1, 0, 0, salt.length) + + var destPos = 0 + var hLen = sizes[digest] + var l = Math.ceil(keylen / hLen) + + for (var i = 1; i <= l; i++) { + block1.writeUInt32BE(i, salt.length) + + var T = hmac.run(block1, hmac.ipad1) + var U = T + + for (var j = 1; j < iterations; j++) { + U = hmac.run(U, hmac.ipad2) + for (var k = 0; k < hLen; k++) T[k] ^= U[k] + } + + T.copy(DK, destPos) + destPos += hLen + } + + return DK +} + +module.exports = pbkdf2 + +},{"./default-encoding":344,"./precondition":345,"./to-buffer":347,"create-hash/md5":128,"ripemd160":372,"safe-buffer":390,"sha.js":393}],347:[function(require,module,exports){ +var Buffer = require('safe-buffer').Buffer + +module.exports = function (thing, encoding, name) { + if (Buffer.isBuffer(thing)) { + return thing + } else if (typeof thing === 'string') { + return Buffer.from(thing, encoding) + } else if (ArrayBuffer.isView(thing)) { + return Buffer.from(thing.buffer) + } else { + throw new TypeError(name + ' must be a string, a Buffer, a typed array or a DataView') + } +} + +},{"safe-buffer":390}],348:[function(require,module,exports){ +'use strict'; + +/** @type {import('.')} */ +module.exports = [ + 'Float32Array', + 'Float64Array', + 'Int8Array', + 'Int16Array', + 'Int32Array', + 'Uint8Array', + 'Uint8ClampedArray', + 'Uint16Array', + 'Uint32Array', + 'BigInt64Array', + 'BigUint64Array' +]; + +},{}],349:[function(require,module,exports){ +(function (process){(function (){ +'use strict'; + +if (typeof process === 'undefined' || + !process.version || + process.version.indexOf('v0.') === 0 || + process.version.indexOf('v1.') === 0 && process.version.indexOf('v1.8.') !== 0) { + module.exports = { nextTick: nextTick }; +} else { + module.exports = process +} + +function nextTick(fn, arg1, arg2, arg3) { + if (typeof fn !== 'function') { + throw new TypeError('"callback" argument must be a function'); + } + var len = arguments.length; + var args, i; + switch (len) { + case 0: + case 1: + return process.nextTick(fn); + case 2: + return process.nextTick(function afterTickOne() { + fn.call(null, arg1); + }); + case 3: + return process.nextTick(function afterTickTwo() { + fn.call(null, arg1, arg2); + }); + case 4: + return process.nextTick(function afterTickThree() { + fn.call(null, arg1, arg2, arg3); + }); + default: + args = new Array(len - 1); + i = 0; + while (i < args.length) { + args[i++] = arguments[i]; + } + return process.nextTick(function afterTick() { + fn.apply(null, args); + }); + } +} + + +}).call(this)}).call(this,require('_process')) +},{"_process":350}],350:[function(require,module,exports){ +// shim for using process in browser +var process = module.exports = {}; + +// cached from whatever global is present so that test runners that stub it +// don't break things. But we need to wrap it in a try catch in case it is +// wrapped in strict mode code which doesn't define any globals. It's inside a +// function because try/catches deoptimize in certain engines. + +var cachedSetTimeout; +var cachedClearTimeout; + +function defaultSetTimout() { + throw new Error('setTimeout has not been defined'); +} +function defaultClearTimeout () { + throw new Error('clearTimeout has not been defined'); +} +(function () { + try { + if (typeof setTimeout === 'function') { + cachedSetTimeout = setTimeout; + } else { + cachedSetTimeout = defaultSetTimout; + } + } catch (e) { + cachedSetTimeout = defaultSetTimout; + } + try { + if (typeof clearTimeout === 'function') { + cachedClearTimeout = clearTimeout; + } else { + cachedClearTimeout = defaultClearTimeout; + } + } catch (e) { + cachedClearTimeout = defaultClearTimeout; + } +} ()) +function runTimeout(fun) { + if (cachedSetTimeout === setTimeout) { + //normal enviroments in sane situations + return setTimeout(fun, 0); + } + // if setTimeout wasn't available but was latter defined + if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) { + cachedSetTimeout = setTimeout; + return setTimeout(fun, 0); + } + try { + // when when somebody has screwed with setTimeout but no I.E. maddness + return cachedSetTimeout(fun, 0); + } catch(e){ + try { + // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally + return cachedSetTimeout.call(null, fun, 0); + } catch(e){ + // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error + return cachedSetTimeout.call(this, fun, 0); + } + } + + +} +function runClearTimeout(marker) { + if (cachedClearTimeout === clearTimeout) { + //normal enviroments in sane situations + return clearTimeout(marker); + } + // if clearTimeout wasn't available but was latter defined + if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) { + cachedClearTimeout = clearTimeout; + return clearTimeout(marker); + } + try { + // when when somebody has screwed with setTimeout but no I.E. maddness + return cachedClearTimeout(marker); + } catch (e){ + try { + // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally + return cachedClearTimeout.call(null, marker); + } catch (e){ + // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error. + // Some versions of I.E. have different rules for clearTimeout vs setTimeout + return cachedClearTimeout.call(this, marker); + } + } + + + +} +var queue = []; +var draining = false; +var currentQueue; +var queueIndex = -1; + +function cleanUpNextTick() { + if (!draining || !currentQueue) { + return; + } + draining = false; + if (currentQueue.length) { + queue = currentQueue.concat(queue); + } else { + queueIndex = -1; + } + if (queue.length) { + drainQueue(); + } +} + +function drainQueue() { + if (draining) { + return; + } + var timeout = runTimeout(cleanUpNextTick); + draining = true; + + var len = queue.length; + while(len) { + currentQueue = queue; + queue = []; + while (++queueIndex < len) { + if (currentQueue) { + currentQueue[queueIndex].run(); + } + } + queueIndex = -1; + len = queue.length; + } + currentQueue = null; + draining = false; + runClearTimeout(timeout); +} + +process.nextTick = function (fun) { + var args = new Array(arguments.length - 1); + if (arguments.length > 1) { + for (var i = 1; i < arguments.length; i++) { + args[i - 1] = arguments[i]; + } + } + queue.push(new Item(fun, args)); + if (queue.length === 1 && !draining) { + runTimeout(drainQueue); + } +}; + +// v8 likes predictible objects +function Item(fun, array) { + this.fun = fun; + this.array = array; +} +Item.prototype.run = function () { + this.fun.apply(null, this.array); +}; +process.title = 'browser'; +process.browser = true; +process.env = {}; +process.argv = []; +process.version = ''; // empty string to avoid regexp issues +process.versions = {}; + +function noop() {} + +process.on = noop; +process.addListener = noop; +process.once = noop; +process.off = noop; +process.removeListener = noop; +process.removeAllListeners = noop; +process.emit = noop; +process.prependListener = noop; +process.prependOnceListener = noop; + +process.listeners = function (name) { return [] } + +process.binding = function (name) { + throw new Error('process.binding is not supported'); +}; + +process.cwd = function () { return '/' }; +process.chdir = function (dir) { + throw new Error('process.chdir is not supported'); +}; +process.umask = function() { return 0; }; + +},{}],351:[function(require,module,exports){ +exports.publicEncrypt = require('./publicEncrypt') +exports.privateDecrypt = require('./privateDecrypt') + +exports.privateEncrypt = function privateEncrypt (key, buf) { + return exports.publicEncrypt(key, buf, true) +} + +exports.publicDecrypt = function publicDecrypt (key, buf) { + return exports.privateDecrypt(key, buf, true) +} + +},{"./privateDecrypt":353,"./publicEncrypt":354}],352:[function(require,module,exports){ +var createHash = require('create-hash') +var Buffer = require('safe-buffer').Buffer + +module.exports = function (seed, len) { + var t = Buffer.alloc(0) + var i = 0 + var c + while (t.length < len) { + c = i2ops(i++) + t = Buffer.concat([t, createHash('sha1').update(seed).update(c).digest()]) + } + return t.slice(0, len) +} + +function i2ops (c) { + var out = Buffer.allocUnsafe(4) + out.writeUInt32BE(c, 0) + return out +} + +},{"create-hash":127,"safe-buffer":390}],353:[function(require,module,exports){ +var parseKeys = require('parse-asn1') +var mgf = require('./mgf') +var xor = require('./xor') +var BN = require('bn.js') +var crt = require('browserify-rsa') +var createHash = require('create-hash') +var withPublic = require('./withPublic') +var Buffer = require('safe-buffer').Buffer + +module.exports = function privateDecrypt (privateKey, enc, reverse) { + var padding + if (privateKey.padding) { + padding = privateKey.padding + } else if (reverse) { + padding = 1 + } else { + padding = 4 + } + + var key = parseKeys(privateKey) + var k = key.modulus.byteLength() + if (enc.length > k || new BN(enc).cmp(key.modulus) >= 0) { + throw new Error('decryption error') + } + var msg + if (reverse) { + msg = withPublic(new BN(enc), key) + } else { + msg = crt(enc, key) + } + var zBuffer = Buffer.alloc(k - msg.length) + msg = Buffer.concat([zBuffer, msg], k) + if (padding === 4) { + return oaep(key, msg) + } else if (padding === 1) { + return pkcs1(key, msg, reverse) + } else if (padding === 3) { + return msg + } else { + throw new Error('unknown padding') + } +} + +function oaep (key, msg) { + var k = key.modulus.byteLength() + var iHash = createHash('sha1').update(Buffer.alloc(0)).digest() + var hLen = iHash.length + if (msg[0] !== 0) { + throw new Error('decryption error') + } + var maskedSeed = msg.slice(1, hLen + 1) + var maskedDb = msg.slice(hLen + 1) + var seed = xor(maskedSeed, mgf(maskedDb, hLen)) + var db = xor(maskedDb, mgf(seed, k - hLen - 1)) + if (compare(iHash, db.slice(0, hLen))) { + throw new Error('decryption error') + } + var i = hLen + while (db[i] === 0) { + i++ + } + if (db[i++] !== 1) { + throw new Error('decryption error') + } + return db.slice(i) +} + +function pkcs1 (key, msg, reverse) { + var p1 = msg.slice(0, 2) + var i = 2 + var status = 0 + while (msg[i++] !== 0) { + if (i >= msg.length) { + status++ + break + } + } + var ps = msg.slice(2, i - 1) + + if ((p1.toString('hex') !== '0002' && !reverse) || (p1.toString('hex') !== '0001' && reverse)) { + status++ + } + if (ps.length < 8) { + status++ + } + if (status) { + throw new Error('decryption error') + } + return msg.slice(i) +} +function compare (a, b) { + a = Buffer.from(a) + b = Buffer.from(b) + var dif = 0 + var len = a.length + if (a.length !== b.length) { + dif++ + len = Math.min(a.length, b.length) + } + var i = -1 + while (++i < len) { + dif += (a[i] ^ b[i]) + } + return dif +} + +},{"./mgf":352,"./withPublic":355,"./xor":356,"bn.js":86,"browserify-rsa":109,"create-hash":127,"parse-asn1":341,"safe-buffer":390}],354:[function(require,module,exports){ +var parseKeys = require('parse-asn1') +var randomBytes = require('randombytes') +var createHash = require('create-hash') +var mgf = require('./mgf') +var xor = require('./xor') +var BN = require('bn.js') +var withPublic = require('./withPublic') +var crt = require('browserify-rsa') +var Buffer = require('safe-buffer').Buffer + +module.exports = function publicEncrypt (publicKey, msg, reverse) { + var padding + if (publicKey.padding) { + padding = publicKey.padding + } else if (reverse) { + padding = 1 + } else { + padding = 4 + } + var key = parseKeys(publicKey) + var paddedMsg + if (padding === 4) { + paddedMsg = oaep(key, msg) + } else if (padding === 1) { + paddedMsg = pkcs1(key, msg, reverse) + } else if (padding === 3) { + paddedMsg = new BN(msg) + if (paddedMsg.cmp(key.modulus) >= 0) { + throw new Error('data too long for modulus') + } + } else { + throw new Error('unknown padding') + } + if (reverse) { + return crt(paddedMsg, key) + } else { + return withPublic(paddedMsg, key) + } +} + +function oaep (key, msg) { + var k = key.modulus.byteLength() + var mLen = msg.length + var iHash = createHash('sha1').update(Buffer.alloc(0)).digest() + var hLen = iHash.length + var hLen2 = 2 * hLen + if (mLen > k - hLen2 - 2) { + throw new Error('message too long') + } + var ps = Buffer.alloc(k - mLen - hLen2 - 2) + var dblen = k - hLen - 1 + var seed = randomBytes(hLen) + var maskedDb = xor(Buffer.concat([iHash, ps, Buffer.alloc(1, 1), msg], dblen), mgf(seed, dblen)) + var maskedSeed = xor(seed, mgf(maskedDb, hLen)) + return new BN(Buffer.concat([Buffer.alloc(1), maskedSeed, maskedDb], k)) +} +function pkcs1 (key, msg, reverse) { + var mLen = msg.length + var k = key.modulus.byteLength() + if (mLen > k - 11) { + throw new Error('message too long') + } + var ps + if (reverse) { + ps = Buffer.alloc(k - mLen - 3, 0xff) + } else { + ps = nonZero(k - mLen - 3) + } + return new BN(Buffer.concat([Buffer.from([0, reverse ? 1 : 2]), ps, Buffer.alloc(1), msg], k)) +} +function nonZero (len) { + var out = Buffer.allocUnsafe(len) + var i = 0 + var cache = randomBytes(len * 2) + var cur = 0 + var num + while (i < len) { + if (cur === cache.length) { + cache = randomBytes(len * 2) + cur = 0 + } + num = cache[cur++] + if (num) { + out[i++] = num + } + } + return out +} + +},{"./mgf":352,"./withPublic":355,"./xor":356,"bn.js":86,"browserify-rsa":109,"create-hash":127,"parse-asn1":341,"randombytes":358,"safe-buffer":390}],355:[function(require,module,exports){ +var BN = require('bn.js') +var Buffer = require('safe-buffer').Buffer + +function withPublic (paddedMsg, key) { + return Buffer.from(paddedMsg + .toRed(BN.mont(key.modulus)) + .redPow(new BN(key.publicExponent)) + .fromRed() + .toArray()) +} + +module.exports = withPublic + +},{"bn.js":86,"safe-buffer":390}],356:[function(require,module,exports){ +module.exports = function xor (a, b) { + var len = a.length + var i = -1 + while (++i < len) { + a[i] ^= b[i] + } + return a +} + +},{}],357:[function(require,module,exports){ +(function (global){(function (){ +/*! queue-microtask. MIT License. Feross Aboukhadijeh */ +let promise + +module.exports = typeof queueMicrotask === 'function' + ? queueMicrotask.bind(typeof window !== 'undefined' ? window : global) + // reuse resolved promise, and allocate it lazily + : cb => (promise || (promise = Promise.resolve())) + .then(cb) + .catch(err => setTimeout(() => { throw err }, 0)) + +}).call(this)}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{}],358:[function(require,module,exports){ +(function (process,global){(function (){ +'use strict' + +// limit of Crypto.getRandomValues() +// https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues +var MAX_BYTES = 65536 + +// Node supports requesting up to this number of bytes +// https://github.com/nodejs/node/blob/master/lib/internal/crypto/random.js#L48 +var MAX_UINT32 = 4294967295 + +function oldBrowser () { + throw new Error('Secure random number generation is not supported by this browser.\nUse Chrome, Firefox or Internet Explorer 11') +} + +var Buffer = require('safe-buffer').Buffer +var crypto = global.crypto || global.msCrypto + +if (crypto && crypto.getRandomValues) { + module.exports = randomBytes +} else { + module.exports = oldBrowser +} + +function randomBytes (size, cb) { + // phantomjs needs to throw + if (size > MAX_UINT32) throw new RangeError('requested too many random bytes') + + var bytes = Buffer.allocUnsafe(size) + + if (size > 0) { // getRandomValues fails on IE if size == 0 + if (size > MAX_BYTES) { // this is the max bytes crypto.getRandomValues + // can do at once see https://developer.mozilla.org/en-US/docs/Web/API/window.crypto.getRandomValues + for (var generated = 0; generated < size; generated += MAX_BYTES) { + // buffer.slice automatically checks if the end is past the end of + // the buffer so we don't have to here + crypto.getRandomValues(bytes.slice(generated, generated + MAX_BYTES)) + } + } else { + crypto.getRandomValues(bytes) + } + } + + if (typeof cb === 'function') { + return process.nextTick(function () { + cb(null, bytes) + }) + } + + return bytes +} + +}).call(this)}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"_process":350,"safe-buffer":390}],359:[function(require,module,exports){ +(function (process,global){(function (){ +'use strict' + +function oldBrowser () { + throw new Error('secure random number generation not supported by this browser\nuse chrome, FireFox or Internet Explorer 11') +} +var safeBuffer = require('safe-buffer') +var randombytes = require('randombytes') +var Buffer = safeBuffer.Buffer +var kBufferMaxLength = safeBuffer.kMaxLength +var crypto = global.crypto || global.msCrypto +var kMaxUint32 = Math.pow(2, 32) - 1 +function assertOffset (offset, length) { + if (typeof offset !== 'number' || offset !== offset) { // eslint-disable-line no-self-compare + throw new TypeError('offset must be a number') + } + + if (offset > kMaxUint32 || offset < 0) { + throw new TypeError('offset must be a uint32') + } + + if (offset > kBufferMaxLength || offset > length) { + throw new RangeError('offset out of range') + } +} + +function assertSize (size, offset, length) { + if (typeof size !== 'number' || size !== size) { // eslint-disable-line no-self-compare + throw new TypeError('size must be a number') + } + + if (size > kMaxUint32 || size < 0) { + throw new TypeError('size must be a uint32') + } + + if (size + offset > length || size > kBufferMaxLength) { + throw new RangeError('buffer too small') + } +} +if ((crypto && crypto.getRandomValues) || !process.browser) { + exports.randomFill = randomFill + exports.randomFillSync = randomFillSync +} else { + exports.randomFill = oldBrowser + exports.randomFillSync = oldBrowser +} +function randomFill (buf, offset, size, cb) { + if (!Buffer.isBuffer(buf) && !(buf instanceof global.Uint8Array)) { + throw new TypeError('"buf" argument must be a Buffer or Uint8Array') + } + + if (typeof offset === 'function') { + cb = offset + offset = 0 + size = buf.length + } else if (typeof size === 'function') { + cb = size + size = buf.length - offset + } else if (typeof cb !== 'function') { + throw new TypeError('"cb" argument must be a function') + } + assertOffset(offset, buf.length) + assertSize(size, offset, buf.length) + return actualFill(buf, offset, size, cb) +} + +function actualFill (buf, offset, size, cb) { + if (process.browser) { + var ourBuf = buf.buffer + var uint = new Uint8Array(ourBuf, offset, size) + crypto.getRandomValues(uint) + if (cb) { + process.nextTick(function () { + cb(null, buf) + }) + return + } + return buf + } + if (cb) { + randombytes(size, function (err, bytes) { + if (err) { + return cb(err) + } + bytes.copy(buf, offset) + cb(null, buf) + }) + return + } + var bytes = randombytes(size) + bytes.copy(buf, offset) + return buf +} +function randomFillSync (buf, offset, size) { + if (typeof offset === 'undefined') { + offset = 0 + } + if (!Buffer.isBuffer(buf) && !(buf instanceof global.Uint8Array)) { + throw new TypeError('"buf" argument must be a Buffer or Uint8Array') + } + + assertOffset(offset, buf.length) + + if (size === undefined) size = buf.length - offset + + assertSize(size, offset, buf.length) + + return actualFill(buf, offset, size) +} + +}).call(this)}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"_process":350,"randombytes":358,"safe-buffer":390}],360:[function(require,module,exports){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +// a duplex stream is just a stream that is both readable and writable. +// Since JS doesn't have multiple prototypal inheritance, this class +// prototypally inherits from Readable, and then parasitically from +// Writable. + +'use strict'; + +/**/ + +var pna = require('process-nextick-args'); +/**/ + +/**/ +var objectKeys = Object.keys || function (obj) { + var keys = []; + for (var key in obj) { + keys.push(key); + }return keys; +}; +/**/ + +module.exports = Duplex; + +/**/ +var util = Object.create(require('core-util-is')); +util.inherits = require('inherits'); +/**/ + +var Readable = require('./_stream_readable'); +var Writable = require('./_stream_writable'); + +util.inherits(Duplex, Readable); + +{ + // avoid scope creep, the keys array can then be collected + var keys = objectKeys(Writable.prototype); + for (var v = 0; v < keys.length; v++) { + var method = keys[v]; + if (!Duplex.prototype[method]) Duplex.prototype[method] = Writable.prototype[method]; + } +} + +function Duplex(options) { + if (!(this instanceof Duplex)) return new Duplex(options); + + Readable.call(this, options); + Writable.call(this, options); + + if (options && options.readable === false) this.readable = false; + + if (options && options.writable === false) this.writable = false; + + this.allowHalfOpen = true; + if (options && options.allowHalfOpen === false) this.allowHalfOpen = false; + + this.once('end', onend); +} + +Object.defineProperty(Duplex.prototype, 'writableHighWaterMark', { + // making it explicit this property is not enumerable + // because otherwise some prototype manipulation in + // userland will fail + enumerable: false, + get: function () { + return this._writableState.highWaterMark; + } +}); + +// the no-half-open enforcer +function onend() { + // if we allow half-open state, or if the writable side ended, + // then we're ok. + if (this.allowHalfOpen || this._writableState.ended) return; + + // no more data can be written. + // But allow more writes to happen in this tick. + pna.nextTick(onEndNT, this); +} + +function onEndNT(self) { + self.end(); +} + +Object.defineProperty(Duplex.prototype, 'destroyed', { + get: function () { + if (this._readableState === undefined || this._writableState === undefined) { + return false; + } + return this._readableState.destroyed && this._writableState.destroyed; + }, + set: function (value) { + // we ignore the value if the stream + // has not been initialized yet + if (this._readableState === undefined || this._writableState === undefined) { + return; + } + + // backward compatibility, the user is explicitly + // managing destroyed + this._readableState.destroyed = value; + this._writableState.destroyed = value; + } +}); + +Duplex.prototype._destroy = function (err, cb) { + this.push(null); + this.end(); + + pna.nextTick(cb, err); +}; +},{"./_stream_readable":362,"./_stream_writable":364,"core-util-is":125,"inherits":200,"process-nextick-args":349}],361:[function(require,module,exports){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +// a passthrough stream. +// basically just the most minimal sort of Transform stream. +// Every written chunk gets output as-is. + +'use strict'; + +module.exports = PassThrough; + +var Transform = require('./_stream_transform'); + +/**/ +var util = Object.create(require('core-util-is')); +util.inherits = require('inherits'); +/**/ + +util.inherits(PassThrough, Transform); + +function PassThrough(options) { + if (!(this instanceof PassThrough)) return new PassThrough(options); + + Transform.call(this, options); +} + +PassThrough.prototype._transform = function (chunk, encoding, cb) { + cb(null, chunk); +}; +},{"./_stream_transform":363,"core-util-is":125,"inherits":200}],362:[function(require,module,exports){ +(function (process,global){(function (){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +'use strict'; + +/**/ + +var pna = require('process-nextick-args'); +/**/ + +module.exports = Readable; + +/**/ +var isArray = require('isarray'); +/**/ + +/**/ +var Duplex; +/**/ + +Readable.ReadableState = ReadableState; + +/**/ +var EE = require('events').EventEmitter; + +var EElistenerCount = function (emitter, type) { + return emitter.listeners(type).length; +}; +/**/ + +/**/ +var Stream = require('./internal/streams/stream'); +/**/ + +/**/ + +var Buffer = require('safe-buffer').Buffer; +var OurUint8Array = (typeof global !== 'undefined' ? global : typeof window !== 'undefined' ? window : typeof self !== 'undefined' ? self : {}).Uint8Array || function () {}; +function _uint8ArrayToBuffer(chunk) { + return Buffer.from(chunk); +} +function _isUint8Array(obj) { + return Buffer.isBuffer(obj) || obj instanceof OurUint8Array; +} + +/**/ + +/**/ +var util = Object.create(require('core-util-is')); +util.inherits = require('inherits'); +/**/ + +/**/ +var debugUtil = require('util'); +var debug = void 0; +if (debugUtil && debugUtil.debuglog) { + debug = debugUtil.debuglog('stream'); +} else { + debug = function () {}; +} +/**/ + +var BufferList = require('./internal/streams/BufferList'); +var destroyImpl = require('./internal/streams/destroy'); +var StringDecoder; + +util.inherits(Readable, Stream); + +var kProxyEvents = ['error', 'close', 'destroy', 'pause', 'resume']; + +function prependListener(emitter, event, fn) { + // Sadly this is not cacheable as some libraries bundle their own + // event emitter implementation with them. + if (typeof emitter.prependListener === 'function') return emitter.prependListener(event, fn); + + // This is a hack to make sure that our error handler is attached before any + // userland ones. NEVER DO THIS. This is here only because this code needs + // to continue to work with older versions of Node.js that do not include + // the prependListener() method. The goal is to eventually remove this hack. + if (!emitter._events || !emitter._events[event]) emitter.on(event, fn);else if (isArray(emitter._events[event])) emitter._events[event].unshift(fn);else emitter._events[event] = [fn, emitter._events[event]]; +} + +function ReadableState(options, stream) { + Duplex = Duplex || require('./_stream_duplex'); + + options = options || {}; + + // Duplex streams are both readable and writable, but share + // the same options object. + // However, some cases require setting options to different + // values for the readable and the writable sides of the duplex stream. + // These options can be provided separately as readableXXX and writableXXX. + var isDuplex = stream instanceof Duplex; + + // object stream flag. Used to make read(n) ignore n and to + // make all the buffer merging and length checks go away + this.objectMode = !!options.objectMode; + + if (isDuplex) this.objectMode = this.objectMode || !!options.readableObjectMode; + + // the point at which it stops calling _read() to fill the buffer + // Note: 0 is a valid value, means "don't call _read preemptively ever" + var hwm = options.highWaterMark; + var readableHwm = options.readableHighWaterMark; + var defaultHwm = this.objectMode ? 16 : 16 * 1024; + + if (hwm || hwm === 0) this.highWaterMark = hwm;else if (isDuplex && (readableHwm || readableHwm === 0)) this.highWaterMark = readableHwm;else this.highWaterMark = defaultHwm; + + // cast to ints. + this.highWaterMark = Math.floor(this.highWaterMark); + + // A linked list is used to store data chunks instead of an array because the + // linked list can remove elements from the beginning faster than + // array.shift() + this.buffer = new BufferList(); + this.length = 0; + this.pipes = null; + this.pipesCount = 0; + this.flowing = null; + this.ended = false; + this.endEmitted = false; + this.reading = false; + + // a flag to be able to tell if the event 'readable'/'data' is emitted + // immediately, or on a later tick. We set this to true at first, because + // any actions that shouldn't happen until "later" should generally also + // not happen before the first read call. + this.sync = true; + + // whenever we return null, then we set a flag to say + // that we're awaiting a 'readable' event emission. + this.needReadable = false; + this.emittedReadable = false; + this.readableListening = false; + this.resumeScheduled = false; + + // has it been destroyed + this.destroyed = false; + + // Crypto is kind of old and crusty. Historically, its default string + // encoding is 'binary' so we have to make this configurable. + // Everything else in the universe uses 'utf8', though. + this.defaultEncoding = options.defaultEncoding || 'utf8'; + + // the number of writers that are awaiting a drain event in .pipe()s + this.awaitDrain = 0; + + // if true, a maybeReadMore has been scheduled + this.readingMore = false; + + this.decoder = null; + this.encoding = null; + if (options.encoding) { + if (!StringDecoder) StringDecoder = require('string_decoder/').StringDecoder; + this.decoder = new StringDecoder(options.encoding); + this.encoding = options.encoding; + } +} + +function Readable(options) { + Duplex = Duplex || require('./_stream_duplex'); + + if (!(this instanceof Readable)) return new Readable(options); + + this._readableState = new ReadableState(options, this); + + // legacy + this.readable = true; + + if (options) { + if (typeof options.read === 'function') this._read = options.read; + + if (typeof options.destroy === 'function') this._destroy = options.destroy; + } + + Stream.call(this); +} + +Object.defineProperty(Readable.prototype, 'destroyed', { + get: function () { + if (this._readableState === undefined) { + return false; + } + return this._readableState.destroyed; + }, + set: function (value) { + // we ignore the value if the stream + // has not been initialized yet + if (!this._readableState) { + return; + } + + // backward compatibility, the user is explicitly + // managing destroyed + this._readableState.destroyed = value; + } +}); + +Readable.prototype.destroy = destroyImpl.destroy; +Readable.prototype._undestroy = destroyImpl.undestroy; +Readable.prototype._destroy = function (err, cb) { + this.push(null); + cb(err); +}; + +// Manually shove something into the read() buffer. +// This returns true if the highWaterMark has not been hit yet, +// similar to how Writable.write() returns true if you should +// write() some more. +Readable.prototype.push = function (chunk, encoding) { + var state = this._readableState; + var skipChunkCheck; + + if (!state.objectMode) { + if (typeof chunk === 'string') { + encoding = encoding || state.defaultEncoding; + if (encoding !== state.encoding) { + chunk = Buffer.from(chunk, encoding); + encoding = ''; + } + skipChunkCheck = true; + } + } else { + skipChunkCheck = true; + } + + return readableAddChunk(this, chunk, encoding, false, skipChunkCheck); +}; + +// Unshift should *always* be something directly out of read() +Readable.prototype.unshift = function (chunk) { + return readableAddChunk(this, chunk, null, true, false); +}; + +function readableAddChunk(stream, chunk, encoding, addToFront, skipChunkCheck) { + var state = stream._readableState; + if (chunk === null) { + state.reading = false; + onEofChunk(stream, state); + } else { + var er; + if (!skipChunkCheck) er = chunkInvalid(state, chunk); + if (er) { + stream.emit('error', er); + } else if (state.objectMode || chunk && chunk.length > 0) { + if (typeof chunk !== 'string' && !state.objectMode && Object.getPrototypeOf(chunk) !== Buffer.prototype) { + chunk = _uint8ArrayToBuffer(chunk); + } + + if (addToFront) { + if (state.endEmitted) stream.emit('error', new Error('stream.unshift() after end event'));else addChunk(stream, state, chunk, true); + } else if (state.ended) { + stream.emit('error', new Error('stream.push() after EOF')); + } else { + state.reading = false; + if (state.decoder && !encoding) { + chunk = state.decoder.write(chunk); + if (state.objectMode || chunk.length !== 0) addChunk(stream, state, chunk, false);else maybeReadMore(stream, state); + } else { + addChunk(stream, state, chunk, false); + } + } + } else if (!addToFront) { + state.reading = false; + } + } + + return needMoreData(state); +} + +function addChunk(stream, state, chunk, addToFront) { + if (state.flowing && state.length === 0 && !state.sync) { + stream.emit('data', chunk); + stream.read(0); + } else { + // update the buffer info. + state.length += state.objectMode ? 1 : chunk.length; + if (addToFront) state.buffer.unshift(chunk);else state.buffer.push(chunk); + + if (state.needReadable) emitReadable(stream); + } + maybeReadMore(stream, state); +} + +function chunkInvalid(state, chunk) { + var er; + if (!_isUint8Array(chunk) && typeof chunk !== 'string' && chunk !== undefined && !state.objectMode) { + er = new TypeError('Invalid non-string/buffer chunk'); + } + return er; +} + +// if it's past the high water mark, we can push in some more. +// Also, if we have no data yet, we can stand some +// more bytes. This is to work around cases where hwm=0, +// such as the repl. Also, if the push() triggered a +// readable event, and the user called read(largeNumber) such that +// needReadable was set, then we ought to push more, so that another +// 'readable' event will be triggered. +function needMoreData(state) { + return !state.ended && (state.needReadable || state.length < state.highWaterMark || state.length === 0); +} + +Readable.prototype.isPaused = function () { + return this._readableState.flowing === false; +}; + +// backwards compatibility. +Readable.prototype.setEncoding = function (enc) { + if (!StringDecoder) StringDecoder = require('string_decoder/').StringDecoder; + this._readableState.decoder = new StringDecoder(enc); + this._readableState.encoding = enc; + return this; +}; + +// Don't raise the hwm > 8MB +var MAX_HWM = 0x800000; +function computeNewHighWaterMark(n) { + if (n >= MAX_HWM) { + n = MAX_HWM; + } else { + // Get the next highest power of 2 to prevent increasing hwm excessively in + // tiny amounts + n--; + n |= n >>> 1; + n |= n >>> 2; + n |= n >>> 4; + n |= n >>> 8; + n |= n >>> 16; + n++; + } + return n; +} + +// This function is designed to be inlinable, so please take care when making +// changes to the function body. +function howMuchToRead(n, state) { + if (n <= 0 || state.length === 0 && state.ended) return 0; + if (state.objectMode) return 1; + if (n !== n) { + // Only flow one buffer at a time + if (state.flowing && state.length) return state.buffer.head.data.length;else return state.length; + } + // If we're asking for more than the current hwm, then raise the hwm. + if (n > state.highWaterMark) state.highWaterMark = computeNewHighWaterMark(n); + if (n <= state.length) return n; + // Don't have enough + if (!state.ended) { + state.needReadable = true; + return 0; + } + return state.length; +} + +// you can override either this method, or the async _read(n) below. +Readable.prototype.read = function (n) { + debug('read', n); + n = parseInt(n, 10); + var state = this._readableState; + var nOrig = n; + + if (n !== 0) state.emittedReadable = false; + + // if we're doing read(0) to trigger a readable event, but we + // already have a bunch of data in the buffer, then just trigger + // the 'readable' event and move on. + if (n === 0 && state.needReadable && (state.length >= state.highWaterMark || state.ended)) { + debug('read: emitReadable', state.length, state.ended); + if (state.length === 0 && state.ended) endReadable(this);else emitReadable(this); + return null; + } + + n = howMuchToRead(n, state); + + // if we've ended, and we're now clear, then finish it up. + if (n === 0 && state.ended) { + if (state.length === 0) endReadable(this); + return null; + } + + // All the actual chunk generation logic needs to be + // *below* the call to _read. The reason is that in certain + // synthetic stream cases, such as passthrough streams, _read + // may be a completely synchronous operation which may change + // the state of the read buffer, providing enough data when + // before there was *not* enough. + // + // So, the steps are: + // 1. Figure out what the state of things will be after we do + // a read from the buffer. + // + // 2. If that resulting state will trigger a _read, then call _read. + // Note that this may be asynchronous, or synchronous. Yes, it is + // deeply ugly to write APIs this way, but that still doesn't mean + // that the Readable class should behave improperly, as streams are + // designed to be sync/async agnostic. + // Take note if the _read call is sync or async (ie, if the read call + // has returned yet), so that we know whether or not it's safe to emit + // 'readable' etc. + // + // 3. Actually pull the requested chunks out of the buffer and return. + + // if we need a readable event, then we need to do some reading. + var doRead = state.needReadable; + debug('need readable', doRead); + + // if we currently have less than the highWaterMark, then also read some + if (state.length === 0 || state.length - n < state.highWaterMark) { + doRead = true; + debug('length less than watermark', doRead); + } + + // however, if we've ended, then there's no point, and if we're already + // reading, then it's unnecessary. + if (state.ended || state.reading) { + doRead = false; + debug('reading or ended', doRead); + } else if (doRead) { + debug('do read'); + state.reading = true; + state.sync = true; + // if the length is currently zero, then we *need* a readable event. + if (state.length === 0) state.needReadable = true; + // call internal read method + this._read(state.highWaterMark); + state.sync = false; + // If _read pushed data synchronously, then `reading` will be false, + // and we need to re-evaluate how much data we can return to the user. + if (!state.reading) n = howMuchToRead(nOrig, state); + } + + var ret; + if (n > 0) ret = fromList(n, state);else ret = null; + + if (ret === null) { + state.needReadable = true; + n = 0; + } else { + state.length -= n; + } + + if (state.length === 0) { + // If we have nothing in the buffer, then we want to know + // as soon as we *do* get something into the buffer. + if (!state.ended) state.needReadable = true; + + // If we tried to read() past the EOF, then emit end on the next tick. + if (nOrig !== n && state.ended) endReadable(this); + } + + if (ret !== null) this.emit('data', ret); + + return ret; +}; + +function onEofChunk(stream, state) { + if (state.ended) return; + if (state.decoder) { + var chunk = state.decoder.end(); + if (chunk && chunk.length) { + state.buffer.push(chunk); + state.length += state.objectMode ? 1 : chunk.length; + } + } + state.ended = true; + + // emit 'readable' now to make sure it gets picked up. + emitReadable(stream); +} + +// Don't emit readable right away in sync mode, because this can trigger +// another read() call => stack overflow. This way, it might trigger +// a nextTick recursion warning, but that's not so bad. +function emitReadable(stream) { + var state = stream._readableState; + state.needReadable = false; + if (!state.emittedReadable) { + debug('emitReadable', state.flowing); + state.emittedReadable = true; + if (state.sync) pna.nextTick(emitReadable_, stream);else emitReadable_(stream); + } +} + +function emitReadable_(stream) { + debug('emit readable'); + stream.emit('readable'); + flow(stream); +} + +// at this point, the user has presumably seen the 'readable' event, +// and called read() to consume some data. that may have triggered +// in turn another _read(n) call, in which case reading = true if +// it's in progress. +// However, if we're not ended, or reading, and the length < hwm, +// then go ahead and try to read some more preemptively. +function maybeReadMore(stream, state) { + if (!state.readingMore) { + state.readingMore = true; + pna.nextTick(maybeReadMore_, stream, state); + } +} + +function maybeReadMore_(stream, state) { + var len = state.length; + while (!state.reading && !state.flowing && !state.ended && state.length < state.highWaterMark) { + debug('maybeReadMore read 0'); + stream.read(0); + if (len === state.length) + // didn't get any data, stop spinning. + break;else len = state.length; + } + state.readingMore = false; +} + +// abstract method. to be overridden in specific implementation classes. +// call cb(er, data) where data is <= n in length. +// for virtual (non-string, non-buffer) streams, "length" is somewhat +// arbitrary, and perhaps not very meaningful. +Readable.prototype._read = function (n) { + this.emit('error', new Error('_read() is not implemented')); +}; + +Readable.prototype.pipe = function (dest, pipeOpts) { + var src = this; + var state = this._readableState; + + switch (state.pipesCount) { + case 0: + state.pipes = dest; + break; + case 1: + state.pipes = [state.pipes, dest]; + break; + default: + state.pipes.push(dest); + break; + } + state.pipesCount += 1; + debug('pipe count=%d opts=%j', state.pipesCount, pipeOpts); + + var doEnd = (!pipeOpts || pipeOpts.end !== false) && dest !== process.stdout && dest !== process.stderr; + + var endFn = doEnd ? onend : unpipe; + if (state.endEmitted) pna.nextTick(endFn);else src.once('end', endFn); + + dest.on('unpipe', onunpipe); + function onunpipe(readable, unpipeInfo) { + debug('onunpipe'); + if (readable === src) { + if (unpipeInfo && unpipeInfo.hasUnpiped === false) { + unpipeInfo.hasUnpiped = true; + cleanup(); + } + } + } + + function onend() { + debug('onend'); + dest.end(); + } + + // when the dest drains, it reduces the awaitDrain counter + // on the source. This would be more elegant with a .once() + // handler in flow(), but adding and removing repeatedly is + // too slow. + var ondrain = pipeOnDrain(src); + dest.on('drain', ondrain); + + var cleanedUp = false; + function cleanup() { + debug('cleanup'); + // cleanup event handlers once the pipe is broken + dest.removeListener('close', onclose); + dest.removeListener('finish', onfinish); + dest.removeListener('drain', ondrain); + dest.removeListener('error', onerror); + dest.removeListener('unpipe', onunpipe); + src.removeListener('end', onend); + src.removeListener('end', unpipe); + src.removeListener('data', ondata); + + cleanedUp = true; + + // if the reader is waiting for a drain event from this + // specific writer, then it would cause it to never start + // flowing again. + // So, if this is awaiting a drain, then we just call it now. + // If we don't know, then assume that we are waiting for one. + if (state.awaitDrain && (!dest._writableState || dest._writableState.needDrain)) ondrain(); + } + + // If the user pushes more data while we're writing to dest then we'll end up + // in ondata again. However, we only want to increase awaitDrain once because + // dest will only emit one 'drain' event for the multiple writes. + // => Introduce a guard on increasing awaitDrain. + var increasedAwaitDrain = false; + src.on('data', ondata); + function ondata(chunk) { + debug('ondata'); + increasedAwaitDrain = false; + var ret = dest.write(chunk); + if (false === ret && !increasedAwaitDrain) { + // If the user unpiped during `dest.write()`, it is possible + // to get stuck in a permanently paused state if that write + // also returned false. + // => Check whether `dest` is still a piping destination. + if ((state.pipesCount === 1 && state.pipes === dest || state.pipesCount > 1 && indexOf(state.pipes, dest) !== -1) && !cleanedUp) { + debug('false write response, pause', state.awaitDrain); + state.awaitDrain++; + increasedAwaitDrain = true; + } + src.pause(); + } + } + + // if the dest has an error, then stop piping into it. + // however, don't suppress the throwing behavior for this. + function onerror(er) { + debug('onerror', er); + unpipe(); + dest.removeListener('error', onerror); + if (EElistenerCount(dest, 'error') === 0) dest.emit('error', er); + } + + // Make sure our error handler is attached before userland ones. + prependListener(dest, 'error', onerror); + + // Both close and finish should trigger unpipe, but only once. + function onclose() { + dest.removeListener('finish', onfinish); + unpipe(); + } + dest.once('close', onclose); + function onfinish() { + debug('onfinish'); + dest.removeListener('close', onclose); + unpipe(); + } + dest.once('finish', onfinish); + + function unpipe() { + debug('unpipe'); + src.unpipe(dest); + } + + // tell the dest that it's being piped to + dest.emit('pipe', src); + + // start the flow if it hasn't been started already. + if (!state.flowing) { + debug('pipe resume'); + src.resume(); + } + + return dest; +}; + +function pipeOnDrain(src) { + return function () { + var state = src._readableState; + debug('pipeOnDrain', state.awaitDrain); + if (state.awaitDrain) state.awaitDrain--; + if (state.awaitDrain === 0 && EElistenerCount(src, 'data')) { + state.flowing = true; + flow(src); + } + }; +} + +Readable.prototype.unpipe = function (dest) { + var state = this._readableState; + var unpipeInfo = { hasUnpiped: false }; + + // if we're not piping anywhere, then do nothing. + if (state.pipesCount === 0) return this; + + // just one destination. most common case. + if (state.pipesCount === 1) { + // passed in one, but it's not the right one. + if (dest && dest !== state.pipes) return this; + + if (!dest) dest = state.pipes; + + // got a match. + state.pipes = null; + state.pipesCount = 0; + state.flowing = false; + if (dest) dest.emit('unpipe', this, unpipeInfo); + return this; + } + + // slow case. multiple pipe destinations. + + if (!dest) { + // remove all. + var dests = state.pipes; + var len = state.pipesCount; + state.pipes = null; + state.pipesCount = 0; + state.flowing = false; + + for (var i = 0; i < len; i++) { + dests[i].emit('unpipe', this, { hasUnpiped: false }); + }return this; + } + + // try to find the right one. + var index = indexOf(state.pipes, dest); + if (index === -1) return this; + + state.pipes.splice(index, 1); + state.pipesCount -= 1; + if (state.pipesCount === 1) state.pipes = state.pipes[0]; + + dest.emit('unpipe', this, unpipeInfo); + + return this; +}; + +// set up data events if they are asked for +// Ensure readable listeners eventually get something +Readable.prototype.on = function (ev, fn) { + var res = Stream.prototype.on.call(this, ev, fn); + + if (ev === 'data') { + // Start flowing on next tick if stream isn't explicitly paused + if (this._readableState.flowing !== false) this.resume(); + } else if (ev === 'readable') { + var state = this._readableState; + if (!state.endEmitted && !state.readableListening) { + state.readableListening = state.needReadable = true; + state.emittedReadable = false; + if (!state.reading) { + pna.nextTick(nReadingNextTick, this); + } else if (state.length) { + emitReadable(this); + } + } + } + + return res; +}; +Readable.prototype.addListener = Readable.prototype.on; + +function nReadingNextTick(self) { + debug('readable nexttick read 0'); + self.read(0); +} + +// pause() and resume() are remnants of the legacy readable stream API +// If the user uses them, then switch into old mode. +Readable.prototype.resume = function () { + var state = this._readableState; + if (!state.flowing) { + debug('resume'); + state.flowing = true; + resume(this, state); + } + return this; +}; + +function resume(stream, state) { + if (!state.resumeScheduled) { + state.resumeScheduled = true; + pna.nextTick(resume_, stream, state); + } +} + +function resume_(stream, state) { + if (!state.reading) { + debug('resume read 0'); + stream.read(0); + } + + state.resumeScheduled = false; + state.awaitDrain = 0; + stream.emit('resume'); + flow(stream); + if (state.flowing && !state.reading) stream.read(0); +} + +Readable.prototype.pause = function () { + debug('call pause flowing=%j', this._readableState.flowing); + if (false !== this._readableState.flowing) { + debug('pause'); + this._readableState.flowing = false; + this.emit('pause'); + } + return this; +}; + +function flow(stream) { + var state = stream._readableState; + debug('flow', state.flowing); + while (state.flowing && stream.read() !== null) {} +} + +// wrap an old-style stream as the async data source. +// This is *not* part of the readable stream interface. +// It is an ugly unfortunate mess of history. +Readable.prototype.wrap = function (stream) { + var _this = this; + + var state = this._readableState; + var paused = false; + + stream.on('end', function () { + debug('wrapped end'); + if (state.decoder && !state.ended) { + var chunk = state.decoder.end(); + if (chunk && chunk.length) _this.push(chunk); + } + + _this.push(null); + }); + + stream.on('data', function (chunk) { + debug('wrapped data'); + if (state.decoder) chunk = state.decoder.write(chunk); + + // don't skip over falsy values in objectMode + if (state.objectMode && (chunk === null || chunk === undefined)) return;else if (!state.objectMode && (!chunk || !chunk.length)) return; + + var ret = _this.push(chunk); + if (!ret) { + paused = true; + stream.pause(); + } + }); + + // proxy all the other methods. + // important when wrapping filters and duplexes. + for (var i in stream) { + if (this[i] === undefined && typeof stream[i] === 'function') { + this[i] = function (method) { + return function () { + return stream[method].apply(stream, arguments); + }; + }(i); + } + } + + // proxy certain important events. + for (var n = 0; n < kProxyEvents.length; n++) { + stream.on(kProxyEvents[n], this.emit.bind(this, kProxyEvents[n])); + } + + // when we try to consume some more bytes, simply unpause the + // underlying stream. + this._read = function (n) { + debug('wrapped _read', n); + if (paused) { + paused = false; + stream.resume(); + } + }; + + return this; +}; + +Object.defineProperty(Readable.prototype, 'readableHighWaterMark', { + // making it explicit this property is not enumerable + // because otherwise some prototype manipulation in + // userland will fail + enumerable: false, + get: function () { + return this._readableState.highWaterMark; + } +}); + +// exposed for testing purposes only. +Readable._fromList = fromList; + +// Pluck off n bytes from an array of buffers. +// Length is the combined lengths of all the buffers in the list. +// This function is designed to be inlinable, so please take care when making +// changes to the function body. +function fromList(n, state) { + // nothing buffered + if (state.length === 0) return null; + + var ret; + if (state.objectMode) ret = state.buffer.shift();else if (!n || n >= state.length) { + // read it all, truncate the list + if (state.decoder) ret = state.buffer.join('');else if (state.buffer.length === 1) ret = state.buffer.head.data;else ret = state.buffer.concat(state.length); + state.buffer.clear(); + } else { + // read part of list + ret = fromListPartial(n, state.buffer, state.decoder); + } + + return ret; +} + +// Extracts only enough buffered data to satisfy the amount requested. +// This function is designed to be inlinable, so please take care when making +// changes to the function body. +function fromListPartial(n, list, hasStrings) { + var ret; + if (n < list.head.data.length) { + // slice is the same for buffers and strings + ret = list.head.data.slice(0, n); + list.head.data = list.head.data.slice(n); + } else if (n === list.head.data.length) { + // first chunk is a perfect match + ret = list.shift(); + } else { + // result spans more than one buffer + ret = hasStrings ? copyFromBufferString(n, list) : copyFromBuffer(n, list); + } + return ret; +} + +// Copies a specified amount of characters from the list of buffered data +// chunks. +// This function is designed to be inlinable, so please take care when making +// changes to the function body. +function copyFromBufferString(n, list) { + var p = list.head; + var c = 1; + var ret = p.data; + n -= ret.length; + while (p = p.next) { + var str = p.data; + var nb = n > str.length ? str.length : n; + if (nb === str.length) ret += str;else ret += str.slice(0, n); + n -= nb; + if (n === 0) { + if (nb === str.length) { + ++c; + if (p.next) list.head = p.next;else list.head = list.tail = null; + } else { + list.head = p; + p.data = str.slice(nb); + } + break; + } + ++c; + } + list.length -= c; + return ret; +} + +// Copies a specified amount of bytes from the list of buffered data chunks. +// This function is designed to be inlinable, so please take care when making +// changes to the function body. +function copyFromBuffer(n, list) { + var ret = Buffer.allocUnsafe(n); + var p = list.head; + var c = 1; + p.data.copy(ret); + n -= p.data.length; + while (p = p.next) { + var buf = p.data; + var nb = n > buf.length ? buf.length : n; + buf.copy(ret, ret.length - n, 0, nb); + n -= nb; + if (n === 0) { + if (nb === buf.length) { + ++c; + if (p.next) list.head = p.next;else list.head = list.tail = null; + } else { + list.head = p; + p.data = buf.slice(nb); + } + break; + } + ++c; + } + list.length -= c; + return ret; +} + +function endReadable(stream) { + var state = stream._readableState; + + // If we get here before consuming all the bytes, then that is a + // bug in node. Should never happen. + if (state.length > 0) throw new Error('"endReadable()" called on non-empty stream'); + + if (!state.endEmitted) { + state.ended = true; + pna.nextTick(endReadableNT, state, stream); + } +} + +function endReadableNT(state, stream) { + // Check that we didn't get one last unshift. + if (!state.endEmitted && state.length === 0) { + state.endEmitted = true; + stream.readable = false; + stream.emit('end'); + } +} + +function indexOf(xs, x) { + for (var i = 0, l = xs.length; i < l; i++) { + if (xs[i] === x) return i; + } + return -1; +} +}).call(this)}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"./_stream_duplex":360,"./internal/streams/BufferList":365,"./internal/streams/destroy":366,"./internal/streams/stream":367,"_process":350,"core-util-is":125,"events":172,"inherits":200,"isarray":368,"process-nextick-args":349,"safe-buffer":369,"string_decoder/":370,"util":88}],363:[function(require,module,exports){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +// a transform stream is a readable/writable stream where you do +// something with the data. Sometimes it's called a "filter", +// but that's not a great name for it, since that implies a thing where +// some bits pass through, and others are simply ignored. (That would +// be a valid example of a transform, of course.) +// +// While the output is causally related to the input, it's not a +// necessarily symmetric or synchronous transformation. For example, +// a zlib stream might take multiple plain-text writes(), and then +// emit a single compressed chunk some time in the future. +// +// Here's how this works: +// +// The Transform stream has all the aspects of the readable and writable +// stream classes. When you write(chunk), that calls _write(chunk,cb) +// internally, and returns false if there's a lot of pending writes +// buffered up. When you call read(), that calls _read(n) until +// there's enough pending readable data buffered up. +// +// In a transform stream, the written data is placed in a buffer. When +// _read(n) is called, it transforms the queued up data, calling the +// buffered _write cb's as it consumes chunks. If consuming a single +// written chunk would result in multiple output chunks, then the first +// outputted bit calls the readcb, and subsequent chunks just go into +// the read buffer, and will cause it to emit 'readable' if necessary. +// +// This way, back-pressure is actually determined by the reading side, +// since _read has to be called to start processing a new chunk. However, +// a pathological inflate type of transform can cause excessive buffering +// here. For example, imagine a stream where every byte of input is +// interpreted as an integer from 0-255, and then results in that many +// bytes of output. Writing the 4 bytes {ff,ff,ff,ff} would result in +// 1kb of data being output. In this case, you could write a very small +// amount of input, and end up with a very large amount of output. In +// such a pathological inflating mechanism, there'd be no way to tell +// the system to stop doing the transform. A single 4MB write could +// cause the system to run out of memory. +// +// However, even in such a pathological case, only a single written chunk +// would be consumed, and then the rest would wait (un-transformed) until +// the results of the previous transformed chunk were consumed. + +'use strict'; + +module.exports = Transform; + +var Duplex = require('./_stream_duplex'); + +/**/ +var util = Object.create(require('core-util-is')); +util.inherits = require('inherits'); +/**/ + +util.inherits(Transform, Duplex); + +function afterTransform(er, data) { + var ts = this._transformState; + ts.transforming = false; + + var cb = ts.writecb; + + if (!cb) { + return this.emit('error', new Error('write callback called multiple times')); + } + + ts.writechunk = null; + ts.writecb = null; + + if (data != null) // single equals check for both `null` and `undefined` + this.push(data); + + cb(er); + + var rs = this._readableState; + rs.reading = false; + if (rs.needReadable || rs.length < rs.highWaterMark) { + this._read(rs.highWaterMark); + } +} + +function Transform(options) { + if (!(this instanceof Transform)) return new Transform(options); + + Duplex.call(this, options); + + this._transformState = { + afterTransform: afterTransform.bind(this), + needTransform: false, + transforming: false, + writecb: null, + writechunk: null, + writeencoding: null + }; + + // start out asking for a readable event once data is transformed. + this._readableState.needReadable = true; + + // we have implemented the _read method, and done the other things + // that Readable wants before the first _read call, so unset the + // sync guard flag. + this._readableState.sync = false; + + if (options) { + if (typeof options.transform === 'function') this._transform = options.transform; + + if (typeof options.flush === 'function') this._flush = options.flush; + } + + // When the writable side finishes, then flush out anything remaining. + this.on('prefinish', prefinish); +} + +function prefinish() { + var _this = this; + + if (typeof this._flush === 'function') { + this._flush(function (er, data) { + done(_this, er, data); + }); + } else { + done(this, null, null); + } +} + +Transform.prototype.push = function (chunk, encoding) { + this._transformState.needTransform = false; + return Duplex.prototype.push.call(this, chunk, encoding); +}; + +// This is the part where you do stuff! +// override this function in implementation classes. +// 'chunk' is an input chunk. +// +// Call `push(newChunk)` to pass along transformed output +// to the readable side. You may call 'push' zero or more times. +// +// Call `cb(err)` when you are done with this chunk. If you pass +// an error, then that'll put the hurt on the whole operation. If you +// never call cb(), then you'll never get another chunk. +Transform.prototype._transform = function (chunk, encoding, cb) { + throw new Error('_transform() is not implemented'); +}; + +Transform.prototype._write = function (chunk, encoding, cb) { + var ts = this._transformState; + ts.writecb = cb; + ts.writechunk = chunk; + ts.writeencoding = encoding; + if (!ts.transforming) { + var rs = this._readableState; + if (ts.needTransform || rs.needReadable || rs.length < rs.highWaterMark) this._read(rs.highWaterMark); + } +}; + +// Doesn't matter what the args are here. +// _transform does all the work. +// That we got here means that the readable side wants more data. +Transform.prototype._read = function (n) { + var ts = this._transformState; + + if (ts.writechunk !== null && ts.writecb && !ts.transforming) { + ts.transforming = true; + this._transform(ts.writechunk, ts.writeencoding, ts.afterTransform); + } else { + // mark that we need a transform, so that any data that comes in + // will get processed, now that we've asked for it. + ts.needTransform = true; + } +}; + +Transform.prototype._destroy = function (err, cb) { + var _this2 = this; + + Duplex.prototype._destroy.call(this, err, function (err2) { + cb(err2); + _this2.emit('close'); + }); +}; + +function done(stream, er, data) { + if (er) return stream.emit('error', er); + + if (data != null) // single equals check for both `null` and `undefined` + stream.push(data); + + // if there's nothing in the write buffer, then that means + // that nothing more will ever be provided + if (stream._writableState.length) throw new Error('Calling transform done when ws.length != 0'); + + if (stream._transformState.transforming) throw new Error('Calling transform done when still transforming'); + + return stream.push(null); +} +},{"./_stream_duplex":360,"core-util-is":125,"inherits":200}],364:[function(require,module,exports){ +(function (process,global,setImmediate){(function (){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +// A bit simpler than readable streams. +// Implement an async ._write(chunk, encoding, cb), and it'll handle all +// the drain event emission and buffering. + +'use strict'; + +/**/ + +var pna = require('process-nextick-args'); +/**/ + +module.exports = Writable; + +/* */ +function WriteReq(chunk, encoding, cb) { + this.chunk = chunk; + this.encoding = encoding; + this.callback = cb; + this.next = null; +} + +// It seems a linked list but it is not +// there will be only 2 of these for each stream +function CorkedRequest(state) { + var _this = this; + + this.next = null; + this.entry = null; + this.finish = function () { + onCorkedFinish(_this, state); + }; +} +/* */ + +/**/ +var asyncWrite = !process.browser && ['v0.10', 'v0.9.'].indexOf(process.version.slice(0, 5)) > -1 ? setImmediate : pna.nextTick; +/**/ + +/**/ +var Duplex; +/**/ + +Writable.WritableState = WritableState; + +/**/ +var util = Object.create(require('core-util-is')); +util.inherits = require('inherits'); +/**/ + +/**/ +var internalUtil = { + deprecate: require('util-deprecate') +}; +/**/ + +/**/ +var Stream = require('./internal/streams/stream'); +/**/ + +/**/ + +var Buffer = require('safe-buffer').Buffer; +var OurUint8Array = (typeof global !== 'undefined' ? global : typeof window !== 'undefined' ? window : typeof self !== 'undefined' ? self : {}).Uint8Array || function () {}; +function _uint8ArrayToBuffer(chunk) { + return Buffer.from(chunk); +} +function _isUint8Array(obj) { + return Buffer.isBuffer(obj) || obj instanceof OurUint8Array; +} + +/**/ + +var destroyImpl = require('./internal/streams/destroy'); + +util.inherits(Writable, Stream); + +function nop() {} + +function WritableState(options, stream) { + Duplex = Duplex || require('./_stream_duplex'); + + options = options || {}; + + // Duplex streams are both readable and writable, but share + // the same options object. + // However, some cases require setting options to different + // values for the readable and the writable sides of the duplex stream. + // These options can be provided separately as readableXXX and writableXXX. + var isDuplex = stream instanceof Duplex; + + // object stream flag to indicate whether or not this stream + // contains buffers or objects. + this.objectMode = !!options.objectMode; + + if (isDuplex) this.objectMode = this.objectMode || !!options.writableObjectMode; + + // the point at which write() starts returning false + // Note: 0 is a valid value, means that we always return false if + // the entire buffer is not flushed immediately on write() + var hwm = options.highWaterMark; + var writableHwm = options.writableHighWaterMark; + var defaultHwm = this.objectMode ? 16 : 16 * 1024; + + if (hwm || hwm === 0) this.highWaterMark = hwm;else if (isDuplex && (writableHwm || writableHwm === 0)) this.highWaterMark = writableHwm;else this.highWaterMark = defaultHwm; + + // cast to ints. + this.highWaterMark = Math.floor(this.highWaterMark); + + // if _final has been called + this.finalCalled = false; + + // drain event flag. + this.needDrain = false; + // at the start of calling end() + this.ending = false; + // when end() has been called, and returned + this.ended = false; + // when 'finish' is emitted + this.finished = false; + + // has it been destroyed + this.destroyed = false; + + // should we decode strings into buffers before passing to _write? + // this is here so that some node-core streams can optimize string + // handling at a lower level. + var noDecode = options.decodeStrings === false; + this.decodeStrings = !noDecode; + + // Crypto is kind of old and crusty. Historically, its default string + // encoding is 'binary' so we have to make this configurable. + // Everything else in the universe uses 'utf8', though. + this.defaultEncoding = options.defaultEncoding || 'utf8'; + + // not an actual buffer we keep track of, but a measurement + // of how much we're waiting to get pushed to some underlying + // socket or file. + this.length = 0; + + // a flag to see when we're in the middle of a write. + this.writing = false; + + // when true all writes will be buffered until .uncork() call + this.corked = 0; + + // a flag to be able to tell if the onwrite cb is called immediately, + // or on a later tick. We set this to true at first, because any + // actions that shouldn't happen until "later" should generally also + // not happen before the first write call. + this.sync = true; + + // a flag to know if we're processing previously buffered items, which + // may call the _write() callback in the same tick, so that we don't + // end up in an overlapped onwrite situation. + this.bufferProcessing = false; + + // the callback that's passed to _write(chunk,cb) + this.onwrite = function (er) { + onwrite(stream, er); + }; + + // the callback that the user supplies to write(chunk,encoding,cb) + this.writecb = null; + + // the amount that is being written when _write is called. + this.writelen = 0; + + this.bufferedRequest = null; + this.lastBufferedRequest = null; + + // number of pending user-supplied write callbacks + // this must be 0 before 'finish' can be emitted + this.pendingcb = 0; + + // emit prefinish if the only thing we're waiting for is _write cbs + // This is relevant for synchronous Transform streams + this.prefinished = false; + + // True if the error was already emitted and should not be thrown again + this.errorEmitted = false; + + // count buffered requests + this.bufferedRequestCount = 0; + + // allocate the first CorkedRequest, there is always + // one allocated and free to use, and we maintain at most two + this.corkedRequestsFree = new CorkedRequest(this); +} + +WritableState.prototype.getBuffer = function getBuffer() { + var current = this.bufferedRequest; + var out = []; + while (current) { + out.push(current); + current = current.next; + } + return out; +}; + +(function () { + try { + Object.defineProperty(WritableState.prototype, 'buffer', { + get: internalUtil.deprecate(function () { + return this.getBuffer(); + }, '_writableState.buffer is deprecated. Use _writableState.getBuffer ' + 'instead.', 'DEP0003') + }); + } catch (_) {} +})(); + +// Test _writableState for inheritance to account for Duplex streams, +// whose prototype chain only points to Readable. +var realHasInstance; +if (typeof Symbol === 'function' && Symbol.hasInstance && typeof Function.prototype[Symbol.hasInstance] === 'function') { + realHasInstance = Function.prototype[Symbol.hasInstance]; + Object.defineProperty(Writable, Symbol.hasInstance, { + value: function (object) { + if (realHasInstance.call(this, object)) return true; + if (this !== Writable) return false; + + return object && object._writableState instanceof WritableState; + } + }); +} else { + realHasInstance = function (object) { + return object instanceof this; + }; +} + +function Writable(options) { + Duplex = Duplex || require('./_stream_duplex'); + + // Writable ctor is applied to Duplexes, too. + // `realHasInstance` is necessary because using plain `instanceof` + // would return false, as no `_writableState` property is attached. + + // Trying to use the custom `instanceof` for Writable here will also break the + // Node.js LazyTransform implementation, which has a non-trivial getter for + // `_writableState` that would lead to infinite recursion. + if (!realHasInstance.call(Writable, this) && !(this instanceof Duplex)) { + return new Writable(options); + } + + this._writableState = new WritableState(options, this); + + // legacy. + this.writable = true; + + if (options) { + if (typeof options.write === 'function') this._write = options.write; + + if (typeof options.writev === 'function') this._writev = options.writev; + + if (typeof options.destroy === 'function') this._destroy = options.destroy; + + if (typeof options.final === 'function') this._final = options.final; + } + + Stream.call(this); +} + +// Otherwise people can pipe Writable streams, which is just wrong. +Writable.prototype.pipe = function () { + this.emit('error', new Error('Cannot pipe, not readable')); +}; + +function writeAfterEnd(stream, cb) { + var er = new Error('write after end'); + // TODO: defer error events consistently everywhere, not just the cb + stream.emit('error', er); + pna.nextTick(cb, er); +} + +// Checks that a user-supplied chunk is valid, especially for the particular +// mode the stream is in. Currently this means that `null` is never accepted +// and undefined/non-string values are only allowed in object mode. +function validChunk(stream, state, chunk, cb) { + var valid = true; + var er = false; + + if (chunk === null) { + er = new TypeError('May not write null values to stream'); + } else if (typeof chunk !== 'string' && chunk !== undefined && !state.objectMode) { + er = new TypeError('Invalid non-string/buffer chunk'); + } + if (er) { + stream.emit('error', er); + pna.nextTick(cb, er); + valid = false; + } + return valid; +} + +Writable.prototype.write = function (chunk, encoding, cb) { + var state = this._writableState; + var ret = false; + var isBuf = !state.objectMode && _isUint8Array(chunk); + + if (isBuf && !Buffer.isBuffer(chunk)) { + chunk = _uint8ArrayToBuffer(chunk); + } + + if (typeof encoding === 'function') { + cb = encoding; + encoding = null; + } + + if (isBuf) encoding = 'buffer';else if (!encoding) encoding = state.defaultEncoding; + + if (typeof cb !== 'function') cb = nop; + + if (state.ended) writeAfterEnd(this, cb);else if (isBuf || validChunk(this, state, chunk, cb)) { + state.pendingcb++; + ret = writeOrBuffer(this, state, isBuf, chunk, encoding, cb); + } + + return ret; +}; + +Writable.prototype.cork = function () { + var state = this._writableState; + + state.corked++; +}; + +Writable.prototype.uncork = function () { + var state = this._writableState; + + if (state.corked) { + state.corked--; + + if (!state.writing && !state.corked && !state.bufferProcessing && state.bufferedRequest) clearBuffer(this, state); + } +}; + +Writable.prototype.setDefaultEncoding = function setDefaultEncoding(encoding) { + // node::ParseEncoding() requires lower case. + if (typeof encoding === 'string') encoding = encoding.toLowerCase(); + if (!(['hex', 'utf8', 'utf-8', 'ascii', 'binary', 'base64', 'ucs2', 'ucs-2', 'utf16le', 'utf-16le', 'raw'].indexOf((encoding + '').toLowerCase()) > -1)) throw new TypeError('Unknown encoding: ' + encoding); + this._writableState.defaultEncoding = encoding; + return this; +}; + +function decodeChunk(state, chunk, encoding) { + if (!state.objectMode && state.decodeStrings !== false && typeof chunk === 'string') { + chunk = Buffer.from(chunk, encoding); + } + return chunk; +} + +Object.defineProperty(Writable.prototype, 'writableHighWaterMark', { + // making it explicit this property is not enumerable + // because otherwise some prototype manipulation in + // userland will fail + enumerable: false, + get: function () { + return this._writableState.highWaterMark; + } +}); + +// if we're already writing something, then just put this +// in the queue, and wait our turn. Otherwise, call _write +// If we return false, then we need a drain event, so set that flag. +function writeOrBuffer(stream, state, isBuf, chunk, encoding, cb) { + if (!isBuf) { + var newChunk = decodeChunk(state, chunk, encoding); + if (chunk !== newChunk) { + isBuf = true; + encoding = 'buffer'; + chunk = newChunk; + } + } + var len = state.objectMode ? 1 : chunk.length; + + state.length += len; + + var ret = state.length < state.highWaterMark; + // we must ensure that previous needDrain will not be reset to false. + if (!ret) state.needDrain = true; + + if (state.writing || state.corked) { + var last = state.lastBufferedRequest; + state.lastBufferedRequest = { + chunk: chunk, + encoding: encoding, + isBuf: isBuf, + callback: cb, + next: null + }; + if (last) { + last.next = state.lastBufferedRequest; + } else { + state.bufferedRequest = state.lastBufferedRequest; + } + state.bufferedRequestCount += 1; + } else { + doWrite(stream, state, false, len, chunk, encoding, cb); + } + + return ret; +} + +function doWrite(stream, state, writev, len, chunk, encoding, cb) { + state.writelen = len; + state.writecb = cb; + state.writing = true; + state.sync = true; + if (writev) stream._writev(chunk, state.onwrite);else stream._write(chunk, encoding, state.onwrite); + state.sync = false; +} + +function onwriteError(stream, state, sync, er, cb) { + --state.pendingcb; + + if (sync) { + // defer the callback if we are being called synchronously + // to avoid piling up things on the stack + pna.nextTick(cb, er); + // this can emit finish, and it will always happen + // after error + pna.nextTick(finishMaybe, stream, state); + stream._writableState.errorEmitted = true; + stream.emit('error', er); + } else { + // the caller expect this to happen before if + // it is async + cb(er); + stream._writableState.errorEmitted = true; + stream.emit('error', er); + // this can emit finish, but finish must + // always follow error + finishMaybe(stream, state); + } +} + +function onwriteStateUpdate(state) { + state.writing = false; + state.writecb = null; + state.length -= state.writelen; + state.writelen = 0; +} + +function onwrite(stream, er) { + var state = stream._writableState; + var sync = state.sync; + var cb = state.writecb; + + onwriteStateUpdate(state); -},{".":304,"./utils/arrayBufferToHex":338,"./utils/waitFor":378,"ws":418}],327:[function(require,module,exports){ -"use strict"; -var __assign = (this && this.__assign) || function () { - __assign = Object.assign || function(t) { - for (var s, i = 1, n = arguments.length; i < n; i++) { - s = arguments[i]; - for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) - t[p] = s[p]; - } - return t; - }; - return __assign.apply(this, arguments); -}; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __generator = (this && this.__generator) || function (thisArg, body) { - var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; - return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; - function verb(n) { return function (v) { return step([n, v]); }; } - function step(op) { - if (f) throw new TypeError("Generator is already executing."); - while (_) try { - if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; - if (y = 0, t) op = [op[0] & 2, t.value]; - switch (op[0]) { - case 0: case 1: t = op; break; - case 4: _.label++; return { value: op[1], done: false }; - case 5: _.label++; y = op[1]; op = [0]; continue; - case 7: op = _.ops.pop(); _.trys.pop(); continue; - default: - if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } - if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } - if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } - if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } - if (t[2]) _.ops.pop(); - _.trys.pop(); continue; - } - op = body.call(thisArg, _); - } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } - if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; - } -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -var _1 = require("."); -var proofOfWork_1 = __importDefault(require("./utils/proofOfWork")); -var signData_1 = __importDefault(require("./utils/signData")); -/** - * Triggers a PUT request to other peers. - * @param key key where we want to put the data at. - * @param value Data we want to any (any type) - * @param userNamespaced If this key bolongs to a user or its public. Making it private will enforce validation for our public key and signatures. - * @returns Promise - */ -function toolDbPut(key, value, userNamespaced) { - var _this = this; - if (userNamespaced === void 0) { userNamespaced = false; } - return new Promise(function (resolve, reject) { - if (key.includes(".")) { - // Dots are used as a delimitator character between bublic keys and the key of the user's data - reject(new Error("Key cannot include dots!; " + key)); - return; - } - if (!_this.user) { - reject(new Error("You need to log in before you can PUT.")); - return; - } - var timestamp = new Date().getTime(); - var dataString = "" + JSON.stringify(value) + _this.user.pubKey + timestamp; - // WORK - (0, proofOfWork_1.default)(dataString, _this.options.pow) - .then(function (_a) { - var _b; - var hash = _a.hash, nonce = _a.nonce; - if ((_b = _this.user) === null || _b === void 0 ? void 0 : _b.keys) { - // Sign our value - (0, signData_1.default)(hash, _this.user.keys.signKeys.privateKey) - .then(function (signature) { return __awaiter(_this, void 0, void 0, function () { - var finalKey, data, finalMessage; - var _a, _b; - return __generator(this, function (_c) { - finalKey = userNamespaced - ? ":" + ((_a = this.user) === null || _a === void 0 ? void 0 : _a.pubKey) + "." + key - : key; - data = { - k: finalKey, - p: ((_b = this.user) === null || _b === void 0 ? void 0 : _b.pubKey) || "", - n: nonce, - t: timestamp, - h: hash, - s: (0, _1.arrayBufferToBase64)(signature), - v: value, - }; - this.store.put(finalKey, JSON.stringify(data), function (err, data) { - // - }); - this.logger("PUT > " + key, data); - finalMessage = __assign({ type: "put", id: (0, _1.textRandom)(10), to: [] }, data); - this.network.sendToAll(finalMessage); - resolve(finalMessage); - return [2 /*return*/]; - }); - }); }) - .catch(reject); - } - }) - .catch(reject); - }); -} -exports.default = toolDbPut; + if (er) onwriteError(stream, state, sync, er, cb);else { + // Check if we're actually ready to finish, but don't emit yet + var finished = needFinish(state); + + if (!finished && !state.corked && !state.bufferProcessing && state.bufferedRequest) { + clearBuffer(stream, state); + } + + if (sync) { + /**/ + asyncWrite(afterWrite, stream, state, finished, cb); + /**/ + } else { + afterWrite(stream, state, finished, cb); + } + } +} + +function afterWrite(stream, state, finished, cb) { + if (!finished) onwriteDrain(stream, state); + state.pendingcb--; + cb(); + finishMaybe(stream, state); +} + +// Must force callback to be called on nextTick, so that we don't +// emit 'drain' before the write() consumer gets the 'false' return +// value, and has a chance to attach a 'drain' listener. +function onwriteDrain(stream, state) { + if (state.length === 0 && state.needDrain) { + state.needDrain = false; + stream.emit('drain'); + } +} + +// if there's something in the buffer waiting, then process it +function clearBuffer(stream, state) { + state.bufferProcessing = true; + var entry = state.bufferedRequest; + + if (stream._writev && entry && entry.next) { + // Fast case, write everything using _writev() + var l = state.bufferedRequestCount; + var buffer = new Array(l); + var holder = state.corkedRequestsFree; + holder.entry = entry; + + var count = 0; + var allBuffers = true; + while (entry) { + buffer[count] = entry; + if (!entry.isBuf) allBuffers = false; + entry = entry.next; + count += 1; + } + buffer.allBuffers = allBuffers; + + doWrite(stream, state, true, state.length, buffer, '', holder.finish); + + // doWrite is almost always async, defer these to save a bit of time + // as the hot path ends with doWrite + state.pendingcb++; + state.lastBufferedRequest = null; + if (holder.next) { + state.corkedRequestsFree = holder.next; + holder.next = null; + } else { + state.corkedRequestsFree = new CorkedRequest(state); + } + state.bufferedRequestCount = 0; + } else { + // Slow case, write chunks one-by-one + while (entry) { + var chunk = entry.chunk; + var encoding = entry.encoding; + var cb = entry.callback; + var len = state.objectMode ? 1 : chunk.length; + + doWrite(stream, state, false, len, chunk, encoding, cb); + entry = entry.next; + state.bufferedRequestCount--; + // if we didn't call the onwrite immediately, then + // it means that we need to wait until it does. + // also, that means that the chunk and cb are currently + // being processed, so move the buffer counter past them. + if (state.writing) { + break; + } + } + + if (entry === null) state.lastBufferedRequest = null; + } + + state.bufferedRequest = entry; + state.bufferProcessing = false; +} + +Writable.prototype._write = function (chunk, encoding, cb) { + cb(new Error('_write() is not implemented')); +}; + +Writable.prototype._writev = null; + +Writable.prototype.end = function (chunk, encoding, cb) { + var state = this._writableState; + + if (typeof chunk === 'function') { + cb = chunk; + chunk = null; + encoding = null; + } else if (typeof encoding === 'function') { + cb = encoding; + encoding = null; + } + + if (chunk !== null && chunk !== undefined) this.write(chunk, encoding); + + // .end() fully uncorks + if (state.corked) { + state.corked = 1; + this.uncork(); + } + + // ignore unnecessary end() calls. + if (!state.ending) endWritable(this, state, cb); +}; + +function needFinish(state) { + return state.ending && state.length === 0 && state.bufferedRequest === null && !state.finished && !state.writing; +} +function callFinal(stream, state) { + stream._final(function (err) { + state.pendingcb--; + if (err) { + stream.emit('error', err); + } + state.prefinished = true; + stream.emit('prefinish'); + finishMaybe(stream, state); + }); +} +function prefinish(stream, state) { + if (!state.prefinished && !state.finalCalled) { + if (typeof stream._final === 'function') { + state.pendingcb++; + state.finalCalled = true; + pna.nextTick(callFinal, stream, state); + } else { + state.prefinished = true; + stream.emit('prefinish'); + } + } +} + +function finishMaybe(stream, state) { + var need = needFinish(state); + if (need) { + prefinish(stream, state); + if (state.pendingcb === 0) { + state.finished = true; + stream.emit('finish'); + } + } + return need; +} + +function endWritable(stream, state, cb) { + state.ending = true; + finishMaybe(stream, state); + if (cb) { + if (state.finished) pna.nextTick(cb);else stream.once('finish', cb); + } + state.ended = true; + stream.writable = false; +} + +function onCorkedFinish(corkReq, state, err) { + var entry = corkReq.entry; + corkReq.entry = null; + while (entry) { + var cb = entry.callback; + state.pendingcb--; + cb(err); + entry = entry.next; + } + + // reuse the free corkReq. + state.corkedRequestsFree.next = corkReq; +} + +Object.defineProperty(Writable.prototype, 'destroyed', { + get: function () { + if (this._writableState === undefined) { + return false; + } + return this._writableState.destroyed; + }, + set: function (value) { + // we ignore the value if the stream + // has not been initialized yet + if (!this._writableState) { + return; + } + + // backward compatibility, the user is explicitly + // managing destroyed + this._writableState.destroyed = value; + } +}); + +Writable.prototype.destroy = destroyImpl.destroy; +Writable.prototype._undestroy = destroyImpl.undestroy; +Writable.prototype._destroy = function (err, cb) { + this.end(); + cb(err); +}; +}).call(this)}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {},require("timers").setImmediate) +},{"./_stream_duplex":360,"./internal/streams/destroy":366,"./internal/streams/stream":367,"_process":350,"core-util-is":125,"inherits":200,"process-nextick-args":349,"safe-buffer":369,"timers":416,"util-deprecate":417}],365:[function(require,module,exports){ +'use strict'; + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +var Buffer = require('safe-buffer').Buffer; +var util = require('util'); + +function copyBuffer(src, target, offset) { + src.copy(target, offset); +} + +module.exports = function () { + function BufferList() { + _classCallCheck(this, BufferList); + + this.head = null; + this.tail = null; + this.length = 0; + } + + BufferList.prototype.push = function push(v) { + var entry = { data: v, next: null }; + if (this.length > 0) this.tail.next = entry;else this.head = entry; + this.tail = entry; + ++this.length; + }; + + BufferList.prototype.unshift = function unshift(v) { + var entry = { data: v, next: this.head }; + if (this.length === 0) this.tail = entry; + this.head = entry; + ++this.length; + }; + + BufferList.prototype.shift = function shift() { + if (this.length === 0) return; + var ret = this.head.data; + if (this.length === 1) this.head = this.tail = null;else this.head = this.head.next; + --this.length; + return ret; + }; + + BufferList.prototype.clear = function clear() { + this.head = this.tail = null; + this.length = 0; + }; + + BufferList.prototype.join = function join(s) { + if (this.length === 0) return ''; + var p = this.head; + var ret = '' + p.data; + while (p = p.next) { + ret += s + p.data; + }return ret; + }; + + BufferList.prototype.concat = function concat(n) { + if (this.length === 0) return Buffer.alloc(0); + var ret = Buffer.allocUnsafe(n >>> 0); + var p = this.head; + var i = 0; + while (p) { + copyBuffer(p.data, ret, i); + i += p.data.length; + p = p.next; + } + return ret; + }; + + return BufferList; +}(); + +if (util && util.inspect && util.inspect.custom) { + module.exports.prototype[util.inspect.custom] = function () { + var obj = util.inspect({ length: this.length }); + return this.constructor.name + ' ' + obj; + }; +} +},{"safe-buffer":369,"util":88}],366:[function(require,module,exports){ +'use strict'; + +/**/ + +var pna = require('process-nextick-args'); +/**/ + +// undocumented cb() API, needed for core, not for public API +function destroy(err, cb) { + var _this = this; + + var readableDestroyed = this._readableState && this._readableState.destroyed; + var writableDestroyed = this._writableState && this._writableState.destroyed; + + if (readableDestroyed || writableDestroyed) { + if (cb) { + cb(err); + } else if (err) { + if (!this._writableState) { + pna.nextTick(emitErrorNT, this, err); + } else if (!this._writableState.errorEmitted) { + this._writableState.errorEmitted = true; + pna.nextTick(emitErrorNT, this, err); + } + } + + return this; + } + + // we set destroyed to true before firing error callbacks in order + // to make it re-entrance safe in case destroy() is called within callbacks + + if (this._readableState) { + this._readableState.destroyed = true; + } + + // if this is a duplex stream mark the writable part as destroyed as well + if (this._writableState) { + this._writableState.destroyed = true; + } + + this._destroy(err || null, function (err) { + if (!cb && err) { + if (!_this._writableState) { + pna.nextTick(emitErrorNT, _this, err); + } else if (!_this._writableState.errorEmitted) { + _this._writableState.errorEmitted = true; + pna.nextTick(emitErrorNT, _this, err); + } + } else if (cb) { + cb(err); + } + }); + + return this; +} + +function undestroy() { + if (this._readableState) { + this._readableState.destroyed = false; + this._readableState.reading = false; + this._readableState.ended = false; + this._readableState.endEmitted = false; + } + + if (this._writableState) { + this._writableState.destroyed = false; + this._writableState.ended = false; + this._writableState.ending = false; + this._writableState.finalCalled = false; + this._writableState.prefinished = false; + this._writableState.finished = false; + this._writableState.errorEmitted = false; + } +} + +function emitErrorNT(self, err) { + self.emit('error', err); +} + +module.exports = { + destroy: destroy, + undestroy: undestroy +}; +},{"process-nextick-args":349}],367:[function(require,module,exports){ +arguments[4][223][0].apply(exports,arguments) +},{"dup":223,"events":172}],368:[function(require,module,exports){ +var toString = {}.toString; + +module.exports = Array.isArray || function (arr) { + return toString.call(arr) == '[object Array]'; +}; + +},{}],369:[function(require,module,exports){ +/* eslint-disable node/no-deprecated-api */ +var buffer = require('buffer') +var Buffer = buffer.Buffer + +// alternative to using Object.keys for old browsers +function copyProps (src, dst) { + for (var key in src) { + dst[key] = src[key] + } +} +if (Buffer.from && Buffer.alloc && Buffer.allocUnsafe && Buffer.allocUnsafeSlow) { + module.exports = buffer +} else { + // Copy properties from require('buffer') + copyProps(buffer, exports) + exports.Buffer = SafeBuffer +} + +function SafeBuffer (arg, encodingOrOffset, length) { + return Buffer(arg, encodingOrOffset, length) +} + +// Copy static methods from Buffer +copyProps(Buffer, SafeBuffer) + +SafeBuffer.from = function (arg, encodingOrOffset, length) { + if (typeof arg === 'number') { + throw new TypeError('Argument must not be a number') + } + return Buffer(arg, encodingOrOffset, length) +} + +SafeBuffer.alloc = function (size, fill, encoding) { + if (typeof size !== 'number') { + throw new TypeError('Argument must be a number') + } + var buf = Buffer(size) + if (fill !== undefined) { + if (typeof encoding === 'string') { + buf.fill(fill, encoding) + } else { + buf.fill(fill) + } + } else { + buf.fill(0) + } + return buf +} + +SafeBuffer.allocUnsafe = function (size) { + if (typeof size !== 'number') { + throw new TypeError('Argument must be a number') + } + return Buffer(size) +} + +SafeBuffer.allocUnsafeSlow = function (size) { + if (typeof size !== 'number') { + throw new TypeError('Argument must be a number') + } + return buffer.SlowBuffer(size) +} + +},{"buffer":118}],370:[function(require,module,exports){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. -},{".":304,"./utils/proofOfWork":366,"./utils/signData":370}],328:[function(require,module,exports){ -"use strict"; -var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { - if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { - if (ar || !(i in from)) { - if (!ar) ar = Array.prototype.slice.call(from, 0, i); - ar[i] = from[i]; - } - } - return to.concat(ar || Array.prototype.slice.call(from)); -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -var lodash_1 = __importDefault(require("lodash")); -var _1 = require("."); -/** - * Triggers a QUERY request to other peers. - * @param key start of the key - * @param userNamespaced If this key bolongs to a user or its public. - * @param timeout Max time to wait for remote. - * @param remoteOnly Only query remote peers, do not query local store. - * @returns Promise - */ -function toolDbQueryKeys(key, userNamespaced, timeoutMs, remoteOnly) { - var _this = this; - if (userNamespaced === void 0) { userNamespaced = false; } - if (timeoutMs === void 0) { timeoutMs = 1000; } - if (remoteOnly === void 0) { remoteOnly = false; } - return new Promise(function (resolve, reject) { - var _a, _b; - if (userNamespaced && ((_a = _this.user) === null || _a === void 0 ? void 0 : _a.pubKey) === undefined) { - reject(new Error("You are not authorized yet!")); - return; - } - if (!userNamespaced && key.length < 3) { - reject(new Error("Query key is too short")); - return; - } - // if (!userNamespaced && key.startsWith(":")) { - // reject( - // new Error( - // "User namespace queries should use the userNamespaced argument" - // ) - // ); - // return; - // } - var finalKey = userNamespaced ? ":" + ((_b = _this.user) === null || _b === void 0 ? void 0 : _b.pubKey) + "." + key : key; - _this.logger("QUERY > " + finalKey); - var msgId = (0, _1.textRandom)(10); - var foundKeys = []; - var timeout; - var gotLocalKeys = remoteOnly; - if (remoteOnly === false) { - _this.store.query(finalKey).then(function (localKeys) { - gotLocalKeys = true; - foundKeys = __spreadArray(__spreadArray([], foundKeys, true), localKeys, true); - timeout = setTimeout(finishListening, timeoutMs); - }); - } - var finishListening = function () { - resolve(lodash_1.default.uniq(foundKeys)); - }; - _this.addIdListener(msgId, function (msg) { - _this.logger("QUERY RECV > " + finalKey, msg); - if (msg.type === "queryAck") { - foundKeys = __spreadArray(__spreadArray([], foundKeys, true), msg.keys, true); - if (timeout) { - clearTimeout(timeout); - } - if (gotLocalKeys === true) { - timeout = setTimeout(finishListening, timeoutMs); - } - } - }); - // Do get - _this.network.sendToAll({ - type: "query", - to: [], - key: finalKey, - id: msgId, - }); - }); -} -exports.default = toolDbQueryKeys; +'use strict'; -},{".":304,"lodash":296}],329:[function(require,module,exports){ -"use strict"; -var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { - if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { - if (ar || !(i in from)) { - if (!ar) ar = Array.prototype.slice.call(from, 0, i); - ar[i] = from[i]; - } - } - return to.concat(ar || Array.prototype.slice.call(from)); -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -var lodash_1 = __importDefault(require("lodash")); -var textRandom_1 = __importDefault(require("./utils/textRandom")); -/** - * Queries the given server peer for all documents that arent present - * if our local database. - * Returns the number of documents that were synced. - * @param pubKey server public key - * @returns Promise - */ -function toolDbServerSync(pubKey) { - var _this = this; - return new Promise(function (resolve, reject) { - var localKeys = []; - _this.store.query("").then(function (keys) { - localKeys = keys; - queryAllKeys(_this, pubKey).then(function (remoteKeys) { - if (remoteKeys) { - var missingKeys_1 = lodash_1.default.difference(remoteKeys, localKeys); - if (missingKeys_1.length > 0) { - _this.logger("MISSING KEYS > ", missingKeys_1.length); - var msgId = (0, textRandom_1.default)(10); - var synced_1 = 0; - _this.addIdListener(msgId, function (msg) { - _this.logger("SERVER SYNC RECV > ", msg); - if (msg.type === "put") { - synced_1++; - } - if (synced_1 === missingKeys_1.length) { - resolve(synced_1); - } - }); - // Do get - _this.network.sendToClientId(pubKey, { - type: "get", - to: [], - key: missingKeys_1[0], - id: msgId, - }); - } - } - }); - }); - }); -} -exports.default = toolDbServerSync; -function queryAllKeys(tooldb, serverPubKey, timeoutMs) { - if (timeoutMs === void 0) { timeoutMs = 1000; } - return new Promise(function (resolve, reject) { - var _a; - if (((_a = tooldb.user) === null || _a === void 0 ? void 0 : _a.pubKey) === undefined) { - reject(new Error("You are not authorized yet!")); - return; - } - tooldb.logger("QUERY ALL > " + serverPubKey); - var msgId = (0, textRandom_1.default)(10); - var foundKeys = []; - var timeout; - var finishListening = function () { - resolve(lodash_1.default.uniq(foundKeys)); - }; - tooldb.addIdListener(msgId, function (msg) { - tooldb.logger("QUERY ALL RECV > ", msg); - if (msg.type === "queryAck") { - foundKeys = __spreadArray(__spreadArray([], foundKeys, true), msg.keys, true); - if (timeout) { - clearTimeout(timeout); - } - timeout = setTimeout(finishListening, timeoutMs); - } - }); - // Do get - tooldb.network.sendToClientId(serverPubKey, { - type: "query", - to: [], - key: "", - id: msgId, - }); - }); -} +/**/ -},{"./utils/textRandom":372,"lodash":296}],330:[function(require,module,exports){ -"use strict"; -var __assign = (this && this.__assign) || function () { - __assign = Object.assign || function(t) { - for (var s, i = 1, n = arguments.length; i < n; i++) { - s = arguments[i]; - for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) - t[p] = s[p]; - } - return t; - }; - return __assign.apply(this, arguments); -}; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __generator = (this && this.__generator) || function (thisArg, body) { - var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; - return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; - function verb(n) { return function (v) { return step([n, v]); }; } - function step(op) { - if (f) throw new TypeError("Generator is already executing."); - while (_) try { - if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; - if (y = 0, t) op = [op[0] & 2, t.value]; - switch (op[0]) { - case 0: case 1: t = op; break; - case 4: _.label++; return { value: op[1], done: false }; - case 5: _.label++; y = op[1]; op = [0]; continue; - case 7: op = _.ops.pop(); _.trys.pop(); continue; - default: - if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } - if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } - if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } - if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } - if (t[2]) _.ops.pop(); - _.trys.pop(); continue; - } - op = body.call(thisArg, _); - } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } - if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; - } -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -var decodeKeyString_1 = __importDefault(require("./utils/crypto/decodeKeyString")); -var decryptWithPass_1 = __importDefault(require("./utils/crypto/decryptWithPass")); -var importKey_1 = __importDefault(require("./utils/crypto/importKey")); -var base64ToUint8_1 = __importDefault(require("./utils/base64ToUint8")); -var catchReturn_1 = __importDefault(require("./utils/catchReturn")); -var fromBase64_1 = __importDefault(require("./utils/fromBase64")); -var sha256_1 = __importDefault(require("./utils/sha256")); -function toolDbSignIn(user, password) { - var _this = this; - return new Promise(function (resolve, reject) { - _this.getData("==" + user, false, 5000) - .then(function (_user) { - if (!_user) { - reject("Could not find user"); - return; - } - if ((0, sha256_1.default)(password) !== _user.pass) { - reject("Invalid password"); - return; - } - (0, decryptWithPass_1.default)((0, fromBase64_1.default)(_user.keys.skpriv), password, (0, base64ToUint8_1.default)(_user.iv)).then(function (decryptedskpriv) { - (0, decryptWithPass_1.default)((0, fromBase64_1.default)(_user.keys.ekpriv), password, (0, base64ToUint8_1.default)(_user.iv)) - .then(function (decryptedekpriv) { - var parsedKeys = __assign(__assign({}, _user.keys), { skpriv: decryptedskpriv || "", ekpriv: decryptedekpriv || "" }); - // const jsonKeys = { - // skpub: parsedKeys.skpub, - // skpriv: parsedKeys.skpriv, - // ekpub: parsedKeys.ekpub, - // ekpriv: parsedKeys.ekpriv, - // }; - // localStorage.setItem("keys", JSON.stringify(jsonKeys)); - function importKeys() { - return __awaiter(this, void 0, void 0, function () { - var skpub, skpriv, ekpub, ekpriv; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: return [4 /*yield*/, (0, importKey_1.default)((0, decodeKeyString_1.default)(parsedKeys.skpub), "spki", "ECDSA", ["verify"]).catch(catchReturn_1.default)]; - case 1: - skpub = _a.sent(); - return [4 /*yield*/, (0, importKey_1.default)((0, decodeKeyString_1.default)(parsedKeys.skpriv), "pkcs8", "ECDSA", ["sign"]).catch(catchReturn_1.default)]; - case 2: - skpriv = _a.sent(); - return [4 /*yield*/, (0, importKey_1.default)((0, decodeKeyString_1.default)(parsedKeys.ekpub), "spki", "ECDH", []).catch(catchReturn_1.default)]; - case 3: - ekpub = _a.sent(); - return [4 /*yield*/, (0, importKey_1.default)((0, decodeKeyString_1.default)(parsedKeys.ekpriv), "pkcs8", "ECDH", ["deriveKey", "deriveBits"]).catch(catchReturn_1.default)]; - case 4: - ekpriv = _a.sent(); - return [2 /*return*/, { skpub: skpub, skpriv: skpriv, ekpub: ekpub, ekpriv: ekpriv }]; - } - }); - }); - } - importKeys() - .then(function (_a) { - var skpub = _a.skpub, skpriv = _a.skpriv, ekpub = _a.ekpub, ekpriv = _a.ekpriv; - if (!skpub || !skpriv || !ekpub || !ekpriv) { - reject(new Error("Could not import keys")); - } - else { - var newKeys = { - signKeys: { - publicKey: skpub, - privateKey: skpriv, - }, - encryptionKeys: { - publicKey: ekpub, - privateKey: ekpriv, - }, - }; - _this.user = { - keys: newKeys, - name: user, - pubKey: _user.keys.skpub, - }; - resolve(newKeys); - } - }) - .catch(catchReturn_1.default); - }) - .catch(catchReturn_1.default); - }); - }) - .catch(console.warn); - }); -} -exports.default = toolDbSignIn; +var Buffer = require('safe-buffer').Buffer; +/**/ -},{"./utils/base64ToUint8":343,"./utils/catchReturn":344,"./utils/crypto/decodeKeyString":345,"./utils/crypto/decryptWithPass":347,"./utils/crypto/importKey":356,"./utils/fromBase64":360,"./utils/sha256":369}],331:[function(require,module,exports){ -"use strict"; -var __assign = (this && this.__assign) || function () { - __assign = Object.assign || function(t) { - for (var s, i = 1, n = arguments.length; i < n; i++) { - s = arguments[i]; - for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) - t[p] = s[p]; - } - return t; - }; - return __assign.apply(this, arguments); -}; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __generator = (this && this.__generator) || function (thisArg, body) { - var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; - return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; - function verb(n) { return function (v) { return step([n, v]); }; } - function step(op) { - if (f) throw new TypeError("Generator is already executing."); - while (_) try { - if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; - if (y = 0, t) op = [op[0] & 2, t.value]; - switch (op[0]) { - case 0: case 1: t = op; break; - case 4: _.label++; return { value: op[1], done: false }; - case 5: _.label++; y = op[1]; op = [0]; continue; - case 7: op = _.ops.pop(); _.trys.pop(); continue; - default: - if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } - if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } - if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } - if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } - if (t[2]) _.ops.pop(); - _.trys.pop(); continue; - } - op = body.call(thisArg, _); - } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } - if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; - } -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -var _1 = require("."); -var encryptWithPass_1 = __importDefault(require("./utils/crypto/encryptWithPass")); -var generateKeysComb_1 = __importDefault(require("./utils/crypto/generateKeysComb")); -var saveKeysComb_1 = __importDefault(require("./utils/crypto/saveKeysComb")); -var generateIv_1 = __importDefault(require("./utils/generateIv")); -var proofOfWork_1 = __importDefault(require("./utils/proofOfWork")); -var sha256_1 = __importDefault(require("./utils/sha256")); -var signData_1 = __importDefault(require("./utils/signData")); -var toBase64_1 = __importDefault(require("./utils/toBase64")); -var uint8ToBase64_1 = __importDefault(require("./utils/uint8ToBase64")); -function toolDbSignUp(user, password) { - return __awaiter(this, void 0, void 0, function () { - var userRoot; - var _this = this; - return __generator(this, function (_a) { - userRoot = "==" + user; - return [2 /*return*/, new Promise(function (resolve, reject) { - _this.getData(userRoot, false, 3000) - .then(function (data) { - if (data === null) { - (0, generateKeysComb_1.default)() - .then(function (keys) { - if (keys) { - (0, saveKeysComb_1.default)(keys.signKeys, keys.encryptionKeys) - .then(function (savedKeys) { - var iv = (0, generateIv_1.default)(); - var encskpriv = ""; - var encekpriv = ""; - // Encrypt sign key - (0, encryptWithPass_1.default)(savedKeys.skpriv, password, iv) - .then(function (skenc) { - (0, encryptWithPass_1.default)(savedKeys.ekpriv, password, iv) - .then(function (ekenc) { - if (skenc) - encskpriv = skenc; - if (ekenc) - encekpriv = ekenc; - var userData = { - keys: { - skpub: savedKeys.skpub, - skpriv: (0, toBase64_1.default)(encskpriv), - ekpub: savedKeys.ekpub, - ekpriv: (0, toBase64_1.default)(encekpriv), - }, - iv: (0, uint8ToBase64_1.default)(iv), - pass: (0, sha256_1.default)(password), - }; - var timestamp = new Date().getTime(); - var userDataString = "" + JSON.stringify(userData) + savedKeys.skpub + timestamp; - (0, proofOfWork_1.default)(userDataString, 0) - .then(function (_a) { - var hash = _a.hash, nonce = _a.nonce; - (0, signData_1.default)(hash, keys.signKeys.privateKey).then(function (signature) { - var signupMessage = { - k: userRoot, - p: savedKeys.skpub, - n: nonce, - t: timestamp, - h: hash, - s: (0, _1.arrayBufferToBase64)(signature), - v: userData, - }; - _this.logger("SIGNUP PUT > " + userRoot, signupMessage); - var finalMsg = __assign({ type: "put", id: (0, _1.textRandom)(10), to: [] }, signupMessage); - _this.network.sendToAll(finalMsg); - resolve(finalMsg); - }); - }) - .catch(reject); - }) - .catch(reject); - }) - .catch(reject); - }) - .catch(function () { return reject(new Error("")); }); - } - else { - reject(new Error("Could not generate keys")); - } - }) - .catch(function () { return reject(new Error("Could not generate keys")); }); - } - else { - reject(new Error("User already exists!")); - } - }) - .catch(function () { - reject(new Error("Could not fetch user")); - }); - })]; - }); - }); -} -exports.default = toolDbSignUp; +var isEncoding = Buffer.isEncoding || function (encoding) { + encoding = '' + encoding; + switch (encoding && encoding.toLowerCase()) { + case 'hex':case 'utf8':case 'utf-8':case 'ascii':case 'binary':case 'base64':case 'ucs2':case 'ucs-2':case 'utf16le':case 'utf-16le':case 'raw': + return true; + default: + return false; + } +}; + +function _normalizeEncoding(enc) { + if (!enc) return 'utf8'; + var retried; + while (true) { + switch (enc) { + case 'utf8': + case 'utf-8': + return 'utf8'; + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return 'utf16le'; + case 'latin1': + case 'binary': + return 'latin1'; + case 'base64': + case 'ascii': + case 'hex': + return enc; + default: + if (retried) return; // undefined + enc = ('' + enc).toLowerCase(); + retried = true; + } + } +}; -},{".":304,"./utils/crypto/encryptWithPass":351,"./utils/crypto/generateKeysComb":355,"./utils/crypto/saveKeysComb":358,"./utils/generateIv":361,"./utils/proofOfWork":366,"./utils/sha256":369,"./utils/signData":370,"./utils/toBase64":373,"./utils/uint8ToBase64":374}],332:[function(require,module,exports){ -"use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -var _1 = require("."); -var automerge_1 = __importDefault(require("automerge")); -/** - * Subscribe to all PUT updates for this key. - * @param key key of the data - * @param userNamespaced If this key bolongs to a user or its public. Making it private will enforce validation for our public key and signatures. - * @returns Promise - */ -function toolDbSubscribe(key, userNamespaced) { - var _this = this; - if (userNamespaced === void 0) { userNamespaced = false; } - return new Promise(function (resolve, reject) { - var _a, _b; - if (userNamespaced && ((_a = _this.user) === null || _a === void 0 ? void 0 : _a.pubKey) === undefined) { - reject(new Error("You are not authorized yet!")); - return; - } - var finalKey = userNamespaced ? ":" + ((_b = _this.user) === null || _b === void 0 ? void 0 : _b.pubKey) + "." + key : key; - _this.logger("Subscribe > " + finalKey); - var msgId = (0, _1.textRandom)(10); - _this.store.get(finalKey, function (err, data) { - if (data) { - try { - var message = JSON.parse(data); - _this.triggerKeyListener(finalKey, message); - } - catch (e) { - // do nothing - } - } - }); - // console.log("do subscribe", finalKey); - _this.loadCrdtDocument(finalKey, false).then(function (doc) { - if (doc) { - var savedDoc = automerge_1.default.save(doc); - var msg = { - type: "crdt", - key: finalKey, - id: (0, _1.textRandom)(10), - to: [], - doc: (0, _1.uint8ToBase64)(savedDoc), - }; - _this.triggerKeyListener(finalKey, msg); - } - }); - _this.network.sendToAll({ - type: "subscribe", - key: finalKey, - to: [], - id: msgId, - }); - resolve(); - }); -} -exports.default = toolDbSubscribe; +// Do not cache `Buffer.isEncoding` when checking encoding names as some +// modules monkey-patch it to support additional encodings +function normalizeEncoding(enc) { + var nenc = _normalizeEncoding(enc); + if (typeof nenc !== 'string' && (Buffer.isEncoding === isEncoding || !isEncoding(enc))) throw new Error('Unknown encoding: ' + enc); + return nenc || enc; +} -},{".":304,"automerge":86}],333:[function(require,module,exports){ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __generator = (this && this.__generator) || function (thisArg, body) { - var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; - return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; - function verb(n) { return function (v) { return step([n, v]); }; } - function step(op) { - if (f) throw new TypeError("Generator is already executing."); - while (_) try { - if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; - if (y = 0, t) op = [op[0] & 2, t.value]; - switch (op[0]) { - case 0: case 1: t = op; break; - case 4: _.label++; return { value: op[1], done: false }; - case 5: _.label++; y = op[1]; op = [0]; continue; - case 7: op = _.ops.pop(); _.trys.pop(); continue; - default: - if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } - if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } - if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } - if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } - if (t[2]) _.ops.pop(); - _.trys.pop(); continue; - } - op = body.call(thisArg, _); - } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } - if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; - } -}; -Object.defineProperty(exports, "__esModule", { value: true }); -var _1 = require("."); -function toolDbVerificationWrapper(data) { - var _this = this; - // This wrapper function adds our custom verification functions to all messages. - return new Promise(function (resolve) { - _this.verifyMessage(data, _this.options.pow).then(function (verified) { return __awaiter(_this, void 0, void 0, function () { - var skipCustom_1; - return __generator(this, function (_a) { - if (verified) { - skipCustom_1 = true; - this._customVerificator.forEach(function (listener) { - if (listener && data.k && data.k.startsWith(listener.key)) { - skipCustom_1 = false; - listener - .fn(data) - .then(function (verified) { - if (verified) { - resolve(_1.VerifyResult.Verified); - } - else { - resolve(_1.VerifyResult.CustomVerificationFailed); - } - }) - .catch(function (e) { - resolve(_1.VerifyResult.CustomVerificationFailed); - }); - } - }); - if (skipCustom_1) { - resolve(verified); - } - } - else { - resolve(_1.VerifyResult.InvalidVerification); - } - return [2 /*return*/]; - }); - }); }); - }); -} -exports.default = toolDbVerificationWrapper; +// StringDecoder provides an interface for efficiently splitting a series of +// buffers into a series of JS strings without breaking apart multi-byte +// characters. +exports.StringDecoder = StringDecoder; +function StringDecoder(encoding) { + this.encoding = normalizeEncoding(encoding); + var nb; + switch (this.encoding) { + case 'utf16le': + this.text = utf16Text; + this.end = utf16End; + nb = 4; + break; + case 'utf8': + this.fillLast = utf8FillLast; + nb = 4; + break; + case 'base64': + this.text = base64Text; + this.end = base64End; + nb = 3; + break; + default: + this.write = simpleWrite; + this.end = simpleEnd; + return; + } + this.lastNeed = 0; + this.lastTotal = 0; + this.lastChar = Buffer.allocUnsafe(nb); +} -},{".":304}],334:[function(require,module,exports){ -"use strict"; -var __extends = (this && this.__extends) || (function () { - var extendStatics = function (d, b) { - extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; - return extendStatics(d, b); - }; - return function (d, b) { - if (typeof b !== "function" && b !== null) - throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -})(); -var __assign = (this && this.__assign) || function () { - __assign = Object.assign || function(t) { - for (var s, i = 1, n = arguments.length; i < n; i++) { - s = arguments[i]; - for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) - t[p] = s[p]; - } - return t; - }; - return __assign.apply(this, arguments); -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.KEY_PREFIX = void 0; -var events_1 = __importDefault(require("events")); -var _1 = require("."); -var logger_1 = __importDefault(require("./logger")); -var toolDbGet_1 = __importDefault(require("./toolDbGet")); -var toolDbPut_1 = __importDefault(require("./toolDbPut")); -var toolDbSignIn_1 = __importDefault(require("./toolDbSignIn")); -var toolDbSignUp_1 = __importDefault(require("./toolDbSignUp")); -var toolDbNetwork_1 = __importDefault(require("./toolDbNetwork")); -var toolDbCrdtGet_1 = __importDefault(require("./toolDbCrdtGet")); -var toolDbCrdtPut_1 = __importDefault(require("./toolDbCrdtPut")); -var toolDbGetPubKey_1 = __importDefault(require("./toolDbGetPubKey")); -var toolDbAnonSignIn_1 = __importDefault(require("./toolDbAnonSignIn")); -var toolDbServerSync_1 = __importDefault(require("./toolDbServerSync")); -var toolDbClientOnMessage_1 = __importDefault(require("./toolDbClientOnMessage")); -var toolDbVerificationWrapper_1 = __importDefault(require("./toolDbVerificationWrapper")); -var leveldb_1 = __importDefault(require("./utils/leveldb")); -var indexedb_1 = __importDefault(require("./utils/indexedb")); -var toolDbSubscribe_1 = __importDefault(require("./toolDbSubscribe")); -var toolDbQueryKeys_1 = __importDefault(require("./toolDbQueryKeys")); -var loadCrdtDocument_1 = __importDefault(require("./loadCrdtDocument")); -var toolDbKeysSignIn_1 = __importDefault(require("./toolDbKeysSignIn")); -var handleGet_1 = __importDefault(require("./messageHandlers/handleGet")); -var handlePut_1 = __importDefault(require("./messageHandlers/handlePut")); -var handlePing_1 = __importDefault(require("./messageHandlers/handlePing")); -var handlePong_1 = __importDefault(require("./messageHandlers/handlePong")); -var handleCrdt_1 = __importDefault(require("./messageHandlers/handleCrdt")); -var handleQuery_1 = __importDefault(require("./messageHandlers/handleQuery")); -var handleCrdtGet_1 = __importDefault(require("./messageHandlers/handleCrdtGet")); -var handleCrdtPut_1 = __importDefault(require("./messageHandlers/handleCrdtPut")); -var handleSubscribe_1 = __importDefault(require("./messageHandlers/handleSubscribe")); -var arrayBufferToHex_1 = __importDefault(require("./utils/arrayBufferToHex")); -var handleFunction_1 = __importDefault(require("./messageHandlers/handleFunction")); -var toolDbFunction_1 = __importDefault(require("./toolDbFunction")); -exports.KEY_PREFIX = "3059301306072a8648ce3d020106082a8648ce3d03010703420004"; -var ToolDb = /** @class */ (function (_super) { - __extends(ToolDb, _super); - function ToolDb(options) { - if (options === void 0) { options = {}; } - var _this = _super.call(this) || this; - _this._peers = {}; - _this.logger = logger_1.default; - _this._documents = {}; - _this._pubKey = undefined; - _this.clientOnMessage = toolDbClientOnMessage_1.default; - _this.verifyMessage = _1.verifyMessage; - _this._subscriptions = []; - _this.isConnected = false; - _this._processedIds = {}; - _this._processedOutHashes = {}; - _this.subscribeData = toolDbSubscribe_1.default; - // Emitted when there are no more server peers connected to - _this.onDisconnect = function () { - // - }; - // Emitted when a server peer responds with "pong" - _this.onConnect = function () { - // - }; - _this.onPeerDisconnect = function (peerId) { - // - }; - _this.onPeerConnect = function (peerId) { - // - }; - _this.loadCrdtDocument = loadCrdtDocument_1.default; - _this.getData = toolDbGet_1.default; - _this.putData = toolDbPut_1.default; - _this.putCrdt = toolDbCrdtPut_1.default; - _this.getCrdt = toolDbCrdtGet_1.default; - _this.queryKeys = toolDbQueryKeys_1.default; - _this.doFunction = toolDbFunction_1.default; - _this.getPubKey = toolDbGetPubKey_1.default; - _this.serverSync = toolDbServerSync_1.default; - _this.signIn = toolDbSignIn_1.default; - _this.anonSignIn = toolDbAnonSignIn_1.default; - _this.keysSignIn = toolDbKeysSignIn_1.default; - _this.signUp = toolDbSignUp_1.default; - _this.verify = toolDbVerificationWrapper_1.default; - // All message handlers go here - _this.handlePing = handlePing_1.default; - _this.handlePong = handlePong_1.default; - _this.handleCrdt = handleCrdt_1.default; - _this.handleCrdtGet = handleCrdtGet_1.default; - _this.handleCrdtPut = handleCrdtPut_1.default; - _this.handleGet = handleGet_1.default; - _this.handlePut = handlePut_1.default; - _this.handleQuery = handleQuery_1.default; - _this.handleSubscribe = handleSubscribe_1.default; - _this.handleFunction = handleFunction_1.default; - /** - * id listeners listen for a specific message ID just once - */ - _this._idListeners = {}; - _this.addIdListener = function (id, fn) { - _this._idListeners[id] = fn; - }; - _this.removeIdListener = function (id) { - delete _this._idListeners[id]; - }; - /** - * Server functions allow the server to define functions to be executed by the clients - * It is up to the function creator to specify proper security on these. - * Server functions are meant to execute on data stored on the server, in a way the clients - * dont have to overload the server, use with caution! - * Custom functions are expected to be a Promise that resolves to a string, and arguments are - * passed as an array of values. Type and sanity checking is up to the developer. - */ - _this._functions = {}; - /** - * Key listeners listen for a specific key, as long as the listener remains active - */ - _this._keyListeners = []; - _this.addKeyListener = function (key, fn) { - var newListener = { - key: key, - timeout: null, - fn: fn, - }; - _this._keyListeners.push(newListener); - return _this._keyListeners.length; - }; - _this.removeKeyListener = function (id) { - var _a, _b; - if ((_a = _this._keyListeners[id]) === null || _a === void 0 ? void 0 : _a.timeout) { - clearTimeout(((_b = _this._keyListeners[id]) === null || _b === void 0 ? void 0 : _b.timeout) || undefined); - } - _this._keyListeners[id] = null; - }; - _this.triggerKeyListener = function (key, message) { - // console.warn(`triggerKeyListener ${key}`); - _this._keyListeners.forEach(function (listener) { - if ((listener === null || listener === void 0 ? void 0 : listener.key) === key) { - // console.log(`TRIGGER OK`, message); - if (listener.timeout) { - clearTimeout(listener.timeout); - } - listener.timeout = setTimeout(function () { return listener.fn(message); }, _this.options.triggerDebouce); - } - }); - }; - /** - * Custom verificators can enhance default verification on any key field - */ - _this._customVerificator = []; - _this.addCustomVerification = function (key, fn) { - var newListener = { - key: key, - fn: fn, - }; - _this._customVerificator.push(newListener); - return _this._customVerificator.length; - }; - _this.removeCustomVerification = function (id) { - _this._customVerificator[id] = null; - }; - _this.user = undefined; - _this._options = { - db: "tooldb", - maxRetries: 5, - triggerDebouce: 100, - wait: 2000, - pow: 0, - server: false, - host: "127.0.0.1", - port: 8080, - debug: false, - httpServer: undefined, - networkAdapter: toolDbNetwork_1.default, - storageName: "tooldb", - storageAdapter: typeof window === "undefined" ? leveldb_1.default : indexedb_1.default, - topic: "", - defaultKeys: undefined, - maxPeers: 4, - ssl: false, - serverName: "default-server", - }; - _this._options = __assign(__assign({}, _this.options), options); - if (!_this._options.defaultKeys) { - (0, _1.generateKeyPair)("ECDSA", false).then(function (key) { - if (key.publicKey && key.privateKey) { - _this._options.defaultKeys = key; - (0, _1.exportKey)("spki", key.publicKey).then(function (skpub) { - _this._pubKey = (0, arrayBufferToHex_1.default)(skpub); - if (_this._pubKey.startsWith(exports.KEY_PREFIX)) { - _this._pubKey = _this._pubKey.slice(exports.KEY_PREFIX.length); - } - _this.emit("init", _this._pubKey); - }); - } - }); - } - else { - (0, _1.exportKey)("spki", _this._options.defaultKeys.publicKey).then(function (skpub) { - _this._pubKey = (0, arrayBufferToHex_1.default)(skpub); - if (_this._pubKey.startsWith(exports.KEY_PREFIX)) { - _this._pubKey = _this._pubKey.slice(exports.KEY_PREFIX.length); - } - _this.emit("init", _this._pubKey); - }); - } - // These could be made to be customizable by setting the variables as public - _this._network = new _this.options.networkAdapter(_this); - _this._store = _this.options.storageAdapter(_this.options.storageName); - return _this; - } - Object.defineProperty(ToolDb.prototype, "subscriptions", { - get: function () { - return this._subscriptions; - }, - enumerable: false, - configurable: true - }); - Object.defineProperty(ToolDb.prototype, "pubKey", { - get: function () { - return this._pubKey; - }, - enumerable: false, - configurable: true - }); - Object.defineProperty(ToolDb.prototype, "processedIds", { - get: function () { - return this._processedIds; - }, - enumerable: false, - configurable: true - }); - Object.defineProperty(ToolDb.prototype, "processedOutHashes", { - get: function () { - return this._processedOutHashes; - }, - enumerable: false, - configurable: true - }); - Object.defineProperty(ToolDb.prototype, "serverPeers", { - get: function () { - return Object.values(this._peers).filter(function (peer) { return peer.isServer; }); - }, - enumerable: false, - configurable: true - }); - ToolDb.prototype.getUserNamespacedKey = function (key) { - var _a; - return ":" + (((_a = this.user) === null || _a === void 0 ? void 0 : _a.pubKey) || "") + "." + key; - }; - Object.defineProperty(ToolDb.prototype, "functions", { - get: function () { - return this._functions; - }, - enumerable: false, - configurable: true - }); - ToolDb.prototype.addServerFunction = function (functionName, fn) { - this._functions[functionName] = fn; - }; - Object.defineProperty(ToolDb.prototype, "options", { - get: function () { - return this._options; - }, - enumerable: false, - configurable: true - }); - Object.defineProperty(ToolDb.prototype, "network", { - get: function () { - return this._network; - }, - enumerable: false, - configurable: true - }); - Object.defineProperty(ToolDb.prototype, "peers", { - get: function () { - return this._peers; - }, - enumerable: false, - configurable: true - }); - Object.defineProperty(ToolDb.prototype, "store", { - get: function () { - return this._store; - }, - enumerable: false, - configurable: true - }); - Object.defineProperty(ToolDb.prototype, "documents", { - get: function () { - return this._documents; - }, - enumerable: false, - configurable: true - }); - return ToolDb; -}(events_1.default)); -exports.default = ToolDb; +StringDecoder.prototype.write = function (buf) { + if (buf.length === 0) return ''; + var r; + var i; + if (this.lastNeed) { + r = this.fillLast(buf); + if (r === undefined) return ''; + i = this.lastNeed; + this.lastNeed = 0; + } else { + i = 0; + } + if (i < buf.length) return r ? r + this.text(buf, i) : this.text(buf, i); + return r || ''; +}; -},{".":304,"./loadCrdtDocument":305,"./logger":306,"./messageHandlers/handleCrdt":307,"./messageHandlers/handleCrdtGet":308,"./messageHandlers/handleCrdtPut":309,"./messageHandlers/handleFunction":310,"./messageHandlers/handleGet":311,"./messageHandlers/handlePing":312,"./messageHandlers/handlePong":313,"./messageHandlers/handlePut":314,"./messageHandlers/handleQuery":315,"./messageHandlers/handleSubscribe":316,"./toolDbAnonSignIn":318,"./toolDbClientOnMessage":319,"./toolDbCrdtGet":320,"./toolDbCrdtPut":321,"./toolDbFunction":322,"./toolDbGet":323,"./toolDbGetPubKey":324,"./toolDbKeysSignIn":325,"./toolDbNetwork":326,"./toolDbPut":327,"./toolDbQueryKeys":328,"./toolDbServerSync":329,"./toolDbSignIn":330,"./toolDbSignUp":331,"./toolDbSubscribe":332,"./toolDbVerificationWrapper":333,"./utils/arrayBufferToHex":338,"./utils/indexedb":364,"./utils/leveldb":365,"events":211}],335:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.VerifyResult = void 0; -var VerifyResult; -(function (VerifyResult) { - VerifyResult["CustomVerificationFailed"] = "CustomVerificationFailed"; - VerifyResult["InvalidData"] = "InvalidData"; - VerifyResult["InvalidVerification"] = "InvalidVerification"; - VerifyResult["CantOverwrite"] = "CantOverwrite"; - VerifyResult["InvalidTimestamp"] = "InvalidTimestamp"; - VerifyResult["PubKeyMismatch"] = "PubKeyMismatch"; - VerifyResult["NoProofOfWork"] = "NoProofOfWork"; - VerifyResult["InvalidHashNonce"] = "InvalidHashNonce"; - VerifyResult["InvalidSignature"] = "InvalidSignature"; - VerifyResult["Verified"] = "Verified"; -})(VerifyResult = exports.VerifyResult || (exports.VerifyResult = {})); +StringDecoder.prototype.end = utf8End; -},{}],336:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); +// Returns only complete characters in a Buffer +StringDecoder.prototype.text = utf8Text; -},{}],337:[function(require,module,exports){ -"use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -var arrayBufferToString_1 = __importDefault(require("./arrayBufferToString")); -var toBase64_1 = __importDefault(require("./toBase64")); -function arrayBufferToBase64(arr) { - return (0, toBase64_1.default)((0, arrayBufferToString_1.default)(arr)); -} -exports.default = arrayBufferToBase64; +// Attempts to complete a partial non-UTF-8 character using bytes from a Buffer +StringDecoder.prototype.fillLast = function (buf) { + if (this.lastNeed <= buf.length) { + buf.copy(this.lastChar, this.lastTotal - this.lastNeed, 0, this.lastNeed); + return this.lastChar.toString(this.encoding, 0, this.lastTotal); + } + buf.copy(this.lastChar, this.lastTotal - this.lastNeed, 0, buf.length); + this.lastNeed -= buf.length; +}; -},{"./arrayBufferToString":339,"./toBase64":373}],338:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -function arrayBufferToHex(buffer) { - var data_view = new DataView(buffer); - var iii; - var len; - var hex = ""; - var c; - for (iii = 0, len = data_view.byteLength; iii < len; iii += 1) { - c = data_view.getUint8(iii).toString(16); - if (c.length < 2) { - c = "0" + c; - } - hex += c; - } - return hex; -} -exports.default = arrayBufferToHex; +// Checks the type of a UTF-8 byte, whether it's ASCII, a leading byte, or a +// continuation byte. If an invalid byte is detected, -2 is returned. +function utf8CheckByte(byte) { + if (byte <= 0x7F) return 0;else if (byte >> 5 === 0x06) return 2;else if (byte >> 4 === 0x0E) return 3;else if (byte >> 3 === 0x1E) return 4; + return byte >> 6 === 0x02 ? -1 : -2; +} -},{}],339:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -function arrayBufferToString(arr) { - var byteArray = new Uint8Array(arr); - var byteString = ""; - for (var i = 0; i < byteArray.byteLength; i += 1) { - byteString += String.fromCodePoint(byteArray[i]); - } - return byteString; -} -exports.default = arrayBufferToString; +// Checks at most 3 bytes at the end of a Buffer in order to detect an +// incomplete multi-byte UTF-8 character. The total number of bytes (2, 3, or 4) +// needed to complete the UTF-8 character (if applicable) are returned. +function utf8CheckIncomplete(self, buf, i) { + var j = buf.length - 1; + if (j < i) return 0; + var nb = utf8CheckByte(buf[j]); + if (nb >= 0) { + if (nb > 0) self.lastNeed = nb - 1; + return nb; + } + if (--j < i || nb === -2) return 0; + nb = utf8CheckByte(buf[j]); + if (nb >= 0) { + if (nb > 0) self.lastNeed = nb - 2; + return nb; + } + if (--j < i || nb === -2) return 0; + nb = utf8CheckByte(buf[j]); + if (nb >= 0) { + if (nb > 0) { + if (nb === 2) nb = 0;else self.lastNeed = nb - 3; + } + return nb; + } + return 0; +} -},{}],340:[function(require,module,exports){ -"use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -var fromBase64_1 = __importDefault(require("./fromBase64")); -var stringToArrayBuffer_1 = __importDefault(require("./stringToArrayBuffer")); -function base64ToArrayBuffer(str) { - return (0, stringToArrayBuffer_1.default)((0, fromBase64_1.default)(str)); -} -exports.default = base64ToArrayBuffer; +// Validates as many continuation bytes for a multi-byte UTF-8 character as +// needed or are available. If we see a non-continuation byte where we expect +// one, we "replace" the validated continuation bytes we've seen so far with +// a single UTF-8 replacement character ('\ufffd'), to match v8's UTF-8 decoding +// behavior. The continuation byte check is included three times in the case +// where all of the continuation bytes for a character exist in the same buffer. +// It is also done this way as a slight performance increase instead of using a +// loop. +function utf8CheckExtraBytes(self, buf, p) { + if ((buf[0] & 0xC0) !== 0x80) { + self.lastNeed = 0; + return '\ufffd'; + } + if (self.lastNeed > 1 && buf.length > 1) { + if ((buf[1] & 0xC0) !== 0x80) { + self.lastNeed = 1; + return '\ufffd'; + } + if (self.lastNeed > 2 && buf.length > 2) { + if ((buf[2] & 0xC0) !== 0x80) { + self.lastNeed = 2; + return '\ufffd'; + } + } + } +} -},{"./fromBase64":360,"./stringToArrayBuffer":371}],341:[function(require,module,exports){ -"use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -var fromBase64_1 = __importDefault(require("./fromBase64")); -function base64ToBinaryChange(based) { - var str = (0, fromBase64_1.default)(based); - var buf = new ArrayBuffer(str.length); - var bufView = new Uint8Array(buf); - for (var i = 0, strLen = str.length; i < strLen; i += 1) { - bufView[i] = str.charCodeAt(i); - } - bufView.__binaryChange = true; - return bufView; -} -exports.default = base64ToBinaryChange; +// Attempts to complete a multi-byte UTF-8 character using bytes from a Buffer. +function utf8FillLast(buf) { + var p = this.lastTotal - this.lastNeed; + var r = utf8CheckExtraBytes(this, buf, p); + if (r !== undefined) return r; + if (this.lastNeed <= buf.length) { + buf.copy(this.lastChar, p, 0, this.lastNeed); + return this.lastChar.toString(this.encoding, 0, this.lastTotal); + } + buf.copy(this.lastChar, p, 0, buf.length); + this.lastNeed -= buf.length; +} -},{"./fromBase64":360}],342:[function(require,module,exports){ -"use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -var fromBase64_1 = __importDefault(require("./fromBase64")); -function base64ToBinaryDocument(based) { - var str = (0, fromBase64_1.default)(based); - var buf = new ArrayBuffer(str.length); - var bufView = new Uint8Array(buf); - for (var i = 0, strLen = str.length; i < strLen; i += 1) { - bufView[i] = str.charCodeAt(i); - } - bufView.__binaryDocument = true; - return bufView; -} -exports.default = base64ToBinaryDocument; +// Returns all complete UTF-8 characters in a Buffer. If the Buffer ended on a +// partial character, the character's bytes are buffered until the required +// number of bytes are available. +function utf8Text(buf, i) { + var total = utf8CheckIncomplete(this, buf, i); + if (!this.lastNeed) return buf.toString('utf8', i); + this.lastTotal = total; + var end = buf.length - (total - this.lastNeed); + buf.copy(this.lastChar, 0, end); + return buf.toString('utf8', i, end); +} -},{"./fromBase64":360}],343:[function(require,module,exports){ -"use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -var fromBase64_1 = __importDefault(require("./fromBase64")); -function base64ToUint8(based) { - var str = (0, fromBase64_1.default)(based); - var buf = new ArrayBuffer(str.length); - var bufView = new Uint8Array(buf); - for (var i = 0, strLen = str.length; i < strLen; i += 1) { - bufView[i] = str.charCodeAt(i); - } - return bufView; -} -exports.default = base64ToUint8; +// For UTF-8, a replacement character is added when ending on a partial +// character. +function utf8End(buf) { + var r = buf && buf.length ? this.write(buf) : ''; + if (this.lastNeed) return r + '\ufffd'; + return r; +} -},{"./fromBase64":360}],344:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -function catchReturn(arg) { - // console.error(arg); - return undefined; -} -exports.default = catchReturn; +// UTF-16LE typically needs two bytes per character, but even if we have an even +// number of bytes available, we need to check if we end on a leading/high +// surrogate. In that case, we need to wait for the next two bytes in order to +// decode the last character properly. +function utf16Text(buf, i) { + if ((buf.length - i) % 2 === 0) { + var r = buf.toString('utf16le', i); + if (r) { + var c = r.charCodeAt(r.length - 1); + if (c >= 0xD800 && c <= 0xDBFF) { + this.lastNeed = 2; + this.lastTotal = 4; + this.lastChar[0] = buf[buf.length - 2]; + this.lastChar[1] = buf[buf.length - 1]; + return r.slice(0, -1); + } + } + return r; + } + this.lastNeed = 1; + this.lastTotal = 2; + this.lastChar[0] = buf[buf.length - 1]; + return buf.toString('utf16le', i, buf.length - 1); +} -},{}],345:[function(require,module,exports){ -(function (global){(function (){ -"use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -var stringToArrayBuffer_1 = __importDefault(require("../stringToArrayBuffer")); -function decodeKeyString(keydataB64) { - var keydataS = global.atob(keydataB64); - var keydata = (0, stringToArrayBuffer_1.default)(keydataS); - return keydata; -} -exports.default = decodeKeyString; +// For UTF-16LE we do not explicitly append special replacement characters if we +// end on a partial character, we simply let v8 handle that. +function utf16End(buf) { + var r = buf && buf.length ? this.write(buf) : ''; + if (this.lastNeed) { + var end = this.lastTotal - this.lastNeed; + return r + this.lastChar.toString('utf16le', 0, end); + } + return r; +} -}).call(this)}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"../stringToArrayBuffer":371}],346:[function(require,module,exports){ -"use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -var getCrypto_1 = __importDefault(require("../../getCrypto")); -var arrayBufferToString_1 = __importDefault(require("../arrayBufferToString")); -var base64ToUint8_1 = __importDefault(require("../base64ToUint8")); -var catchReturn_1 = __importDefault(require("../catchReturn")); -var stringToArrayBuffer_1 = __importDefault(require("../stringToArrayBuffer")); -function decryptData(data, privateKey, iv) { - var crypto = (0, getCrypto_1.default)(); - return crypto.subtle - .decrypt({ - name: "AES-GCM", - iv: (0, base64ToUint8_1.default)(iv), - tagLength: 128, // The tagLength you used to encrypt (if any) - }, privateKey, // from generateKey or importKey above - (0, stringToArrayBuffer_1.default)(data) // ArrayBuffer of the data - ) - .then(function (decrypted) { - // returns an ArrayBuffer containing the decrypted data - return (0, arrayBufferToString_1.default)(decrypted); - }) - .catch(catchReturn_1.default); -} -exports.default = decryptData; +function base64Text(buf, i) { + var n = (buf.length - i) % 3; + if (n === 0) return buf.toString('base64', i); + this.lastNeed = 3 - n; + this.lastTotal = 3; + if (n === 1) { + this.lastChar[0] = buf[buf.length - 1]; + } else { + this.lastChar[0] = buf[buf.length - 2]; + this.lastChar[1] = buf[buf.length - 1]; + } + return buf.toString('base64', i, buf.length - n); +} -},{"../../getCrypto":303,"../arrayBufferToString":339,"../base64ToUint8":343,"../catchReturn":344,"../stringToArrayBuffer":371}],347:[function(require,module,exports){ -"use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -var arrayBufferToString_1 = __importDefault(require("../arrayBufferToString")); -var catchReturn_1 = __importDefault(require("../catchReturn")); -var generateKeyFromPassword_1 = __importDefault(require("./generateKeyFromPassword")); -var stringToArrayBuffer_1 = __importDefault(require("../stringToArrayBuffer")); -var getCrypto_1 = __importDefault(require("../../getCrypto")); -function decryptWithPass(data, password, vector) { - var crypto = (0, getCrypto_1.default)(); - return (0, generateKeyFromPassword_1.default)(password) - .then(function (keyObject) { - return crypto.subtle - .decrypt({ name: "AES-GCM", iv: vector }, keyObject, (0, stringToArrayBuffer_1.default)(data)) - .then(function (result) { return (0, arrayBufferToString_1.default)(result); }) - .catch(catchReturn_1.default); - }) - .catch(catchReturn_1.default); -} -exports.default = decryptWithPass; +function base64End(buf) { + var r = buf && buf.length ? this.write(buf) : ''; + if (this.lastNeed) return r + this.lastChar.toString('base64', 0, 3 - this.lastNeed); + return r; +} -},{"../../getCrypto":303,"../arrayBufferToString":339,"../catchReturn":344,"../stringToArrayBuffer":371,"./generateKeyFromPassword":353}],348:[function(require,module,exports){ -"use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -var getCrypto_1 = __importDefault(require("../../getCrypto")); -function deriveSecret(keys) { - var crypto = (0, getCrypto_1.default)(); - return crypto.subtle.deriveKey({ - name: "ECDH", - public: keys.publicKey, - }, keys.privateKey, { - name: "AES-GCM", - length: 256, - }, true, ["encrypt", "decrypt"]); -} -exports.default = deriveSecret; +// Pass bytes on through for single-byte encodings (e.g. ascii, latin1, hex) +function simpleWrite(buf) { + return buf.toString(this.encoding); +} -},{"../../getCrypto":303}],349:[function(require,module,exports){ -(function (global){(function (){ -"use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -var arrayBufferToString_1 = __importDefault(require("../arrayBufferToString")); -function encodeKeyString(keydata) { - var keydataS = (0, arrayBufferToString_1.default)(keydata); - var keydataB64 = global.btoa(keydataS); - return keydataB64; -} -exports.default = encodeKeyString; +function simpleEnd(buf) { + return buf && buf.length ? this.write(buf) : ''; +} +},{"safe-buffer":369}],371:[function(require,module,exports){ +exports = module.exports = require('./lib/_stream_readable.js'); +exports.Stream = exports; +exports.Readable = exports; +exports.Writable = require('./lib/_stream_writable.js'); +exports.Duplex = require('./lib/_stream_duplex.js'); +exports.Transform = require('./lib/_stream_transform.js'); +exports.PassThrough = require('./lib/_stream_passthrough.js'); -}).call(this)}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"../arrayBufferToString":339}],350:[function(require,module,exports){ -"use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -var getCrypto_1 = __importDefault(require("../../getCrypto")); -var arrayBufferToString_1 = __importDefault(require("../arrayBufferToString")); -var stringToArrayBuffer_1 = __importDefault(require("../stringToArrayBuffer")); -function encryptData(data, publicKey, iv) { - var crypto = (0, getCrypto_1.default)(); - return crypto.subtle - .encrypt({ - name: "AES-GCM", - // Don't re-use initialization vectors! - // Always generate a new iv every time your encrypt! - // Recommended to use 12 bytes length - iv: iv, - // Tag length (optional) - tagLength: 128, // can be 32, 64, 96, 104, 112, 120 or 128 (default) - }, publicKey, // from generateKey or importKey above - (0, stringToArrayBuffer_1.default)(data) // ArrayBuffer of data you want to encrypt - ) - .then(function (encrypted) { - // returns an ArrayBuffer containing the encrypted data - return (0, arrayBufferToString_1.default)(encrypted); - }) - .catch(console.error); -} -exports.default = encryptData; +},{"./lib/_stream_duplex.js":360,"./lib/_stream_passthrough.js":361,"./lib/_stream_readable.js":362,"./lib/_stream_transform.js":363,"./lib/_stream_writable.js":364}],372:[function(require,module,exports){ +'use strict' +var Buffer = require('buffer').Buffer +var inherits = require('inherits') +var HashBase = require('hash-base') -},{"../../getCrypto":303,"../arrayBufferToString":339,"../stringToArrayBuffer":371}],351:[function(require,module,exports){ -"use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -var arrayBufferToString_1 = __importDefault(require("../arrayBufferToString")); -var catchReturn_1 = __importDefault(require("../catchReturn")); -var generateKeyFromPassword_1 = __importDefault(require("./generateKeyFromPassword")); -var stringToArrayBuffer_1 = __importDefault(require("../stringToArrayBuffer")); -var getCrypto_1 = __importDefault(require("../../getCrypto")); -function encryptWithPass(secretmessage, password, vector) { - var crypto = (0, getCrypto_1.default)(); - return (0, generateKeyFromPassword_1.default)(password) - .then(function (keyObject) { - // encrypt promise - return crypto.subtle - .encrypt({ name: "AES-GCM", iv: vector }, keyObject, (0, stringToArrayBuffer_1.default)(secretmessage)) - .then(function (result) { - return (0, arrayBufferToString_1.default)(result); - }) - .catch(catchReturn_1.default); - }) - .catch(catchReturn_1.default); -} -exports.default = encryptWithPass; +var ARRAY16 = new Array(16) -},{"../../getCrypto":303,"../arrayBufferToString":339,"../catchReturn":344,"../stringToArrayBuffer":371,"./generateKeyFromPassword":353}],352:[function(require,module,exports){ -"use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -var getCrypto_1 = __importDefault(require("../../getCrypto")); -function exportKey(format, key) { - var crypto = (0, getCrypto_1.default)(); - return crypto.subtle.exportKey(format, // can be "jwk" (public or private), "spki" (public only), or "pkcs8" (private only) - key // can be a publicKey or privateKey, as long as extractable was true, - ); -} -exports.default = exportKey; +var zl = [ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8, + 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12, + 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2, + 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13 +] -},{"../../getCrypto":303}],353:[function(require,module,exports){ -"use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -var getCrypto_1 = __importDefault(require("../../getCrypto")); -var stringToArrayBuffer_1 = __importDefault(require("../stringToArrayBuffer")); -function generateKeyFromPassword(password) { - var crypto = (0, getCrypto_1.default)(); - return crypto.subtle - .importKey("raw", (0, stringToArrayBuffer_1.default)(password), { name: "PBKDF2" }, false, ["deriveKey"]) - .then(function (importedPassword) { - return crypto.subtle.deriveKey({ - name: "PBKDF2", - salt: (0, stringToArrayBuffer_1.default)("t6sa@8d7!2ñs?=adjq2ng"), - iterations: 100000, - hash: "SHA-256", - }, importedPassword, { - name: "AES-GCM", - length: 128, - }, false, ["encrypt", "decrypt"]); - }); -} -exports.default = generateKeyFromPassword; +var zr = [ + 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, + 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2, + 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13, + 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14, + 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11 +] + +var sl = [ + 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8, + 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12, + 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5, + 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12, + 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6 +] -},{"../../getCrypto":303,"../stringToArrayBuffer":371}],354:[function(require,module,exports){ -"use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -var getCrypto_1 = __importDefault(require("../../getCrypto")); -function generateKeyPair(mode, extractable) { - if (extractable === void 0) { extractable = false; } - var crypto = (0, getCrypto_1.default)(); - return crypto.subtle.generateKey({ - name: mode, - namedCurve: "P-256", // can be "P-256", "P-384", or "P-521" - }, extractable, // whether the key is extractable (i.e. can be used in exportKey) - mode === "ECDSA" ? ["sign", "verify"] : ["deriveKey", "deriveBits"]); -} -exports.default = generateKeyPair; +var sr = [ + 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6, + 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11, + 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5, + 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8, + 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11 +] -},{"../../getCrypto":303}],355:[function(require,module,exports){ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __generator = (this && this.__generator) || function (thisArg, body) { - var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; - return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; - function verb(n) { return function (v) { return step([n, v]); }; } - function step(op) { - if (f) throw new TypeError("Generator is already executing."); - while (_) try { - if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; - if (y = 0, t) op = [op[0] & 2, t.value]; - switch (op[0]) { - case 0: case 1: t = op; break; - case 4: _.label++; return { value: op[1], done: false }; - case 5: _.label++; y = op[1]; op = [0]; continue; - case 7: op = _.ops.pop(); _.trys.pop(); continue; - default: - if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } - if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } - if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } - if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } - if (t[2]) _.ops.pop(); - _.trys.pop(); continue; - } - op = body.call(thisArg, _); - } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } - if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; - } -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -var generateKeyPair_1 = __importDefault(require("./generateKeyPair")); -function generateKeysComb() { - return __awaiter(this, void 0, void 0, function () { - return __generator(this, function (_a) { - return [2 /*return*/, new Promise(function (resolve) { - return (0, generateKeyPair_1.default)("ECDSA", true).then(function (signKeys) { - return (0, generateKeyPair_1.default)("ECDH", true).then(function (encryptionKeys) { - resolve({ - signKeys: signKeys, - encryptionKeys: encryptionKeys, - }); - }); - }); - })]; - }); - }); -} -exports.default = generateKeysComb; +var hl = [0x00000000, 0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xa953fd4e] +var hr = [0x50a28be6, 0x5c4dd124, 0x6d703ef3, 0x7a6d76e9, 0x00000000] -},{"./generateKeyPair":354}],356:[function(require,module,exports){ -"use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -var getCrypto_1 = __importDefault(require("../../getCrypto")); -// JsonWebKey -function importKey( -// eslint-disable-next-line no-undef -key, type, algorithm, -// eslint-disable-next-line no-undef -ops) { - var crypto = (0, getCrypto_1.default)(); - return crypto.subtle.importKey(type, // can be "jwk" (public or private), "spki" (public only), or "pkcs8" (private only) - key, { - name: algorithm, - namedCurve: "P-256", - }, true, // whether the key is extractable (i.e. can be used in exportKey) - ops // "verify" for public key import, "sign" for private key imports - ); -} -exports.default = importKey; +function RIPEMD160 () { + HashBase.call(this, 64) -},{"../../getCrypto":303}],357:[function(require,module,exports){ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __generator = (this && this.__generator) || function (thisArg, body) { - var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; - return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; - function verb(n) { return function (v) { return step([n, v]); }; } - function step(op) { - if (f) throw new TypeError("Generator is already executing."); - while (_) try { - if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; - if (y = 0, t) op = [op[0] & 2, t.value]; - switch (op[0]) { - case 0: case 1: t = op; break; - case 4: _.label++; return { value: op[1], done: false }; - case 5: _.label++; y = op[1]; op = [0]; continue; - case 7: op = _.ops.pop(); _.trys.pop(); continue; - default: - if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } - if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } - if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } - if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } - if (t[2]) _.ops.pop(); - _.trys.pop(); continue; - } - op = body.call(thisArg, _); - } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } - if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; - } -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -var catchReturn_1 = __importDefault(require("../catchReturn")); -var decodeKeyString_1 = __importDefault(require("./decodeKeyString")); -var importKey_1 = __importDefault(require("./importKey")); -function importKeys(parsedKeys) { - return __awaiter(this, void 0, void 0, function () { - var skpub, skpriv, ekpub, ekpriv; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: return [4 /*yield*/, (0, importKey_1.default)((0, decodeKeyString_1.default)(parsedKeys.skpub), "spki", "ECDSA", ["verify"]).catch(catchReturn_1.default)]; - case 1: - skpub = _a.sent(); - return [4 /*yield*/, (0, importKey_1.default)((0, decodeKeyString_1.default)(parsedKeys.skpriv), "pkcs8", "ECDSA", ["sign"]).catch(catchReturn_1.default)]; - case 2: - skpriv = _a.sent(); - return [4 /*yield*/, (0, importKey_1.default)((0, decodeKeyString_1.default)(parsedKeys.ekpub), "spki", "ECDH", []).catch(catchReturn_1.default)]; - case 3: - ekpub = _a.sent(); - return [4 /*yield*/, (0, importKey_1.default)((0, decodeKeyString_1.default)(parsedKeys.ekpriv), "pkcs8", "ECDH", ["deriveKey", "deriveBits"]).catch(catchReturn_1.default)]; - case 4: - ekpriv = _a.sent(); - return [2 /*return*/, { skpub: skpub, skpriv: skpriv, ekpub: ekpub, ekpriv: ekpriv }]; - } - }); - }); -} -function loadKeysComb(parsedKeys) { - return new Promise(function (resolve, reject) { - importKeys(parsedKeys).then(function (_a) { - var skpub = _a.skpub, skpriv = _a.skpriv, ekpub = _a.ekpub, ekpriv = _a.ekpriv; - if (!skpub || !skpriv || !ekpub || !ekpriv) { - reject(new Error("Could not import keys")); - } - else { - resolve({ - signKeys: { - publicKey: skpub, - privateKey: skpriv, - }, - encryptionKeys: { - publicKey: ekpub, - privateKey: ekpriv, - }, - }); - } - }); - }); -} -exports.default = loadKeysComb; + // state + this._a = 0x67452301 + this._b = 0xefcdab89 + this._c = 0x98badcfe + this._d = 0x10325476 + this._e = 0xc3d2e1f0 +} -},{"../catchReturn":344,"./decodeKeyString":345,"./importKey":356}],358:[function(require,module,exports){ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __generator = (this && this.__generator) || function (thisArg, body) { - var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; - return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; - function verb(n) { return function (v) { return step([n, v]); }; } - function step(op) { - if (f) throw new TypeError("Generator is already executing."); - while (_) try { - if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; - if (y = 0, t) op = [op[0] & 2, t.value]; - switch (op[0]) { - case 0: case 1: t = op; break; - case 4: _.label++; return { value: op[1], done: false }; - case 5: _.label++; y = op[1]; op = [0]; continue; - case 7: op = _.ops.pop(); _.trys.pop(); continue; - default: - if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } - if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } - if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } - if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } - if (t[2]) _.ops.pop(); - _.trys.pop(); continue; - } - op = body.call(thisArg, _); - } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } - if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; - } -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -var encodeKeyString_1 = __importDefault(require("./encodeKeyString")); -var exportKey_1 = __importDefault(require("./exportKey")); -function saveKeysComb(signKeys, encryptionKeys) { - return __awaiter(this, void 0, void 0, function () { - var skpub, skpriv, ekpub, ekpriv, jsonKeys; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: return [4 /*yield*/, (0, exportKey_1.default)("spki", signKeys.publicKey)]; - case 1: - skpub = _a.sent(); - return [4 /*yield*/, (0, exportKey_1.default)("pkcs8", signKeys.privateKey)]; - case 2: - skpriv = _a.sent(); - return [4 /*yield*/, (0, exportKey_1.default)("spki", encryptionKeys.publicKey)]; - case 3: - ekpub = _a.sent(); - return [4 /*yield*/, (0, exportKey_1.default)("pkcs8", encryptionKeys.privateKey)]; - case 4: - ekpriv = _a.sent(); - jsonKeys = { - skpub: (0, encodeKeyString_1.default)(skpub), - skpriv: (0, encodeKeyString_1.default)(skpriv), - ekpub: (0, encodeKeyString_1.default)(ekpub), - ekpriv: (0, encodeKeyString_1.default)(ekpriv), - }; - // ONLY FOR TESTING! NEVER ENABLE IN PROD - // localStorage.setItem("keys", JSON.stringify(jsonKeys)); - return [2 /*return*/, jsonKeys]; - } - }); - }); -} -exports.default = saveKeysComb; +inherits(RIPEMD160, HashBase) -},{"./encodeKeyString":349,"./exportKey":352}],359:[function(require,module,exports){ -"use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -var getCrypto_1 = __importDefault(require("../../getCrypto")); -var stringToArrayBuffer_1 = __importDefault(require("../stringToArrayBuffer")); -function verifyData(data, signature, publicKey, hashName) { - if (hashName === void 0) { hashName = "SHA-256"; } - var crypto = (0, getCrypto_1.default)(); - return crypto.subtle.verify({ - name: "ECDSA", - hash: { name: hashName }, // can be "SHA-1", "SHA-256", "SHA-384", or "SHA-512" - }, publicKey, // from generateKey or importKey above - signature, // ArrayBuffer of the signature - (0, stringToArrayBuffer_1.default)(data) // ArrayBuffer of the data - ); -} -exports.default = verifyData; +RIPEMD160.prototype._update = function () { + var words = ARRAY16 + for (var j = 0; j < 16; ++j) words[j] = this._block.readInt32LE(j * 4) -},{"../../getCrypto":303,"../stringToArrayBuffer":371}],360:[function(require,module,exports){ -(function (global){(function (){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -function fromBase64(str) { - return decodeURIComponent(escape(global.atob(str))); -} -exports.default = fromBase64; + var al = this._a | 0 + var bl = this._b | 0 + var cl = this._c | 0 + var dl = this._d | 0 + var el = this._e | 0 -}).call(this)}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{}],361:[function(require,module,exports){ -"use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -var getCrypto_1 = __importDefault(require("../getCrypto")); -function generateIv() { - var crypto = (0, getCrypto_1.default)(); - return crypto.getRandomValues(new Uint8Array(12)); -} -exports.default = generateIv; + var ar = this._a | 0 + var br = this._b | 0 + var cr = this._c | 0 + var dr = this._d | 0 + var er = this._e | 0 -},{"../getCrypto":303}],362:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -var __1 = require(".."); -function getPeerSignature(privateKey, topic, timestamp, host, port) { - var dataToSign = (0, __1.sha256)(topic + "-" + timestamp + "-" + host + ":" + port); - return (0, __1.signData)(dataToSign, privateKey, "SHA-1").then(__1.arrayBufferToBase64); -} -exports.default = getPeerSignature; + // computation + for (var i = 0; i < 80; i += 1) { + var tl + var tr + if (i < 16) { + tl = fn1(al, bl, cl, dl, el, words[zl[i]], hl[0], sl[i]) + tr = fn5(ar, br, cr, dr, er, words[zr[i]], hr[0], sr[i]) + } else if (i < 32) { + tl = fn2(al, bl, cl, dl, el, words[zl[i]], hl[1], sl[i]) + tr = fn4(ar, br, cr, dr, er, words[zr[i]], hr[1], sr[i]) + } else if (i < 48) { + tl = fn3(al, bl, cl, dl, el, words[zl[i]], hl[2], sl[i]) + tr = fn3(ar, br, cr, dr, er, words[zr[i]], hr[2], sr[i]) + } else if (i < 64) { + tl = fn4(al, bl, cl, dl, el, words[zl[i]], hl[3], sl[i]) + tr = fn2(ar, br, cr, dr, er, words[zr[i]], hr[3], sr[i]) + } else { // if (i<80) { + tl = fn5(al, bl, cl, dl, el, words[zl[i]], hl[4], sl[i]) + tr = fn1(ar, br, cr, dr, er, words[zr[i]], hr[4], sr[i]) + } -},{"..":304}],363:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -function hexToArrayBuffer(hex) { - var pairs = hex.toUpperCase().match(/[\dA-F]{2}/gi); - if (!pairs) - return new Uint8Array(); - // convert the octets to integers - var integers = pairs.map(function (s) { - return parseInt(s, 16); - }); - var array = new Uint8Array(integers); - return array.buffer; -} -exports.default = hexToArrayBuffer; + al = el + el = dl + dl = rotl(cl, 10) + cl = bl + bl = tl -},{}],364:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -function indexedb(dbName) { - if (dbName === void 0) { dbName = "tooldb"; } - var db = null; - var store = { - start: function () { - // - }, - put: function (key, data, callback) { - // - }, - get: function (key, callback) { - // - }, - query: function (key) { return Promise.resolve([]); }, - quit: function () { - // - }, - }; - store.start = function () { - // console.warn("store start"); - var open = indexedDB.open(dbName, 1); - open.onupgradeneeded = function (eve) { - eve.target.result.createObjectStore(dbName); - }; - open.onsuccess = function () { - db = open.result; - }; - open.onerror = function (eve) { - console.warn(eve || 1); - }; - }; - store.start(); - store.quit = function () { - // console.warn("store quit"); - if (db) { - db.close(); - db = null; - } - }; - store.put = function (key, data, cb) { - // console.warn("store put", key); - if (!db) { - setTimeout(function () { - store.put(key, data, cb); - }, 1); - return; - } - var tx = db.transaction([dbName], "readwrite"); - var obj = tx.objectStore(dbName); - var req = obj.put(data, "" + key); - if (cb) { - req.onsuccess = - obj.onsuccess = - tx.onsuccess = - function () { - cb(false); - }; - req.onabort = - obj.onabort = - tx.onabort = - function (eve) { - cb(eve || "put.tx.abort"); - }; - req.onerror = - obj.onerror = - tx.onerror = - function (eve) { - cb(eve || "put.tx.error"); - }; - } - }; - store.get = function (key, cb) { - // console.warn("store get", key); - if (!db) { - setTimeout(function () { - store.get(key, cb); - }, 9); - return; - } - var tx = db.transaction([dbName], "readonly"); - var obj = tx.objectStore(dbName); - var req = obj.get("" + key); - req.onsuccess = function () { - cb(false, req.result); - }; - req.onabort = function (eve) { - cb(eve || 4); - }; - req.onerror = function (eve) { - cb(eve || 5); - }; - }; - store.query = function (key) { - return new Promise(function (resolve, reject) { - try { - var keyRange = IDBKeyRange.bound(key, key + "|", true, true); - var tx = db.transaction([dbName], "readonly"); - var obj = tx.objectStore(dbName); - var keysArray_1 = []; - obj.openCursor(keyRange).onsuccess = function (event) { - var cursor = event.target.result; - if (cursor) { - keysArray_1.push(event.target.result.key); - cursor.continue(); - } - else { - resolve(keysArray_1); - } - }; - } - catch (error) { - reject(error); - } - }); - }; - setInterval(function () { - db && db.close(); - db = null; - store.start(); - }, 1000 * 15); // reset webkit bug? - return store; -} -exports.default = indexedb; + ar = er + er = dr + dr = rotl(cr, 10) + cr = br + br = tr + } -},{}],365:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -function leveldb(dbName) { - if (dbName === void 0) { dbName = "tooldb"; } - var level = require("level"); - var db = null; - var store = { - start: function () { - // - }, - put: function (key, data, callback) { - // - }, - get: function (key, callback) { - // - }, - query: function (key) { return Promise.resolve([]); }, - quit: function () { - // - }, - }; - store.start = function () { - db = level(dbName); - }; - store.start(); - store.quit = function () { - db.close(); - }; - store.put = function (key, data, cb) { - db.put(key, data, function (err) { - if (err) { - if (cb) - cb(err); - } - else { - if (cb) - cb(false); - } - }); - }; - store.get = function (key, cb) { - // console.warn("store get", key); - if (!db) { - setTimeout(function () { - store.get(key, cb); - }, 9); - return; - } - db.get(key, function (err, value) { - if (err) { - if (cb) - cb(err); - } - else { - if (cb) - cb(false, value); - } - }); - }; - store.query = function (key) { - return new Promise(function (resolve, reject) { - try { - var array_1 = []; - db.createKeyStream({ - gte: key, - lte: key + "\uffff", - }) - .on("data", function (data) { - // if (data.startsWith(key)) { - array_1.push(data); - // } - }) - .on("error", function (err) { - reject(err); - }) - .on("close", function () { - resolve(array_1); - }); - } - catch (error) { - reject(error); - } - }); - }; - return store; -} -exports.default = leveldb; + // update state + var t = (this._b + cl + dr) | 0 + this._b = (this._c + dl + er) | 0 + this._c = (this._d + el + ar) | 0 + this._d = (this._e + al + br) | 0 + this._e = (this._a + bl + cr) | 0 + this._a = t +} -},{"level":291}],366:[function(require,module,exports){ -"use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -var sha256_1 = __importDefault(require("./sha256")); -function proofOfWork(value, difficulty) { - return new Promise(function (resolve) { - var nonce = 0; - var hash = (0, sha256_1.default)("" + value + nonce); - while (hash.substring(0, difficulty) !== Array(difficulty + 1).join("0")) { - nonce += 1; - hash = (0, sha256_1.default)("" + value + nonce); - } - resolve({ nonce: nonce, hash: hash }); - }); -} -exports.default = proofOfWork; +RIPEMD160.prototype._digest = function () { + // create padding and handle blocks + this._block[this._blockOffset++] = 0x80 + if (this._blockOffset > 56) { + this._block.fill(0, this._blockOffset, 64) + this._update() + this._blockOffset = 0 + } -},{"./sha256":369}],367:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -var animals = [ - "Pug", - "Chicken", - "Slug", - "Snail", - "Pig", - "Cow", - "Sheep", - "Horse", - "Squirrel", - "Turtle", - "Unicorn", - "Dragon", - "Dolphin", - "Cat", - "Chow Chow", - "Elephant", - "Meerkat", - "Polar Bear", - "Bear", - "Rabbit", - "Koala", - "Parrot", - "Raven", - "Frog", - "Rat", - "Mouse", - "Bee", - "Tiger", - "Lion", - "Giraffe", - "Ant", - "Spider", - "Zebra", -]; -function randomAnimal() { - return animals[Math.round(Math.random() * animals.length)]; -} -exports.default = randomAnimal; + this._block.fill(0, this._blockOffset, 56) + this._block.writeUInt32LE(this._length[0], 56) + this._block.writeUInt32LE(this._length[1], 60) + this._update() -},{}],368:[function(require,module,exports){ -"use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -var crypto_1 = __importDefault(require("crypto")); -function sha1(str, hex) { - if (hex === void 0) { hex = true; } - var hash = crypto_1.default.createHash("sha1"); - hash.update(str); - return hash.digest(hex ? "hex" : "base64"); -} -exports.default = sha1; + // produce result + var buffer = Buffer.alloc ? Buffer.alloc(20) : new Buffer(20) + buffer.writeInt32LE(this._a, 0) + buffer.writeInt32LE(this._b, 4) + buffer.writeInt32LE(this._c, 8) + buffer.writeInt32LE(this._d, 12) + buffer.writeInt32LE(this._e, 16) + return buffer +} -},{"crypto":168}],369:[function(require,module,exports){ -"use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -var crypto_1 = __importDefault(require("crypto")); -function sha256(str, hex) { - if (hex === void 0) { hex = true; } - var hash = crypto_1.default.createHash("sha256"); - hash.update(str); - return hash.digest(hex ? "hex" : "base64"); -} -exports.default = sha256; +function rotl (x, n) { + return (x << n) | (x >>> (32 - n)) +} -},{"crypto":168}],370:[function(require,module,exports){ -"use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -var getCrypto_1 = __importDefault(require("../getCrypto")); -var stringToArrayBuffer_1 = __importDefault(require("./stringToArrayBuffer")); -function signData(data, privateKey, hashName) { - if (hashName === void 0) { hashName = "SHA-256"; } - var crypto = (0, getCrypto_1.default)(); - return crypto.subtle.sign({ - name: "ECDSA", - hash: { name: hashName }, // can be "SHA-1", "SHA-256", "SHA-384", or "SHA-512" - }, privateKey, // from generateKey or importKey above - (0, stringToArrayBuffer_1.default)(data) // ArrayBuffer of data you want to sign - ); -} -exports.default = signData; +function fn1 (a, b, c, d, e, m, k, s) { + return (rotl((a + (b ^ c ^ d) + m + k) | 0, s) + e) | 0 +} -},{"../getCrypto":303,"./stringToArrayBuffer":371}],371:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -function stringToArrayBuffer(str) { - var buf = new ArrayBuffer(str.length); - var bufView = new Uint8Array(buf); - for (var i = 0, strLen = str.length; i < strLen; i += 1) { - bufView[i] = str.charCodeAt(i); - } - return buf; -} -exports.default = stringToArrayBuffer; +function fn2 (a, b, c, d, e, m, k, s) { + return (rotl((a + ((b & c) | ((~b) & d)) + m + k) | 0, s) + e) | 0 +} -},{}],372:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -function textRandom(_l, _c) { - if (_l === void 0) { _l = 24; } - var l = _l; - var s = ""; - var c = _c || "0123456789ABCDEFGHIJKLMNOPQRSTUVWXZabcdefghijklmnopqrstuvwxyz"; - while (l > 0) { - s += c.charAt(Math.floor(Math.random() * c.length)); - l -= 1; - } - return s; -} -exports.default = textRandom; +function fn3 (a, b, c, d, e, m, k, s) { + return (rotl((a + ((b | (~c)) ^ d) + m + k) | 0, s) + e) | 0 +} -},{}],373:[function(require,module,exports){ -(function (global){(function (){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -function toBase64(str) { - return global.btoa(unescape(encodeURIComponent(str))); -} -exports.default = toBase64; +function fn4 (a, b, c, d, e, m, k, s) { + return (rotl((a + ((b & d) | (c & (~d))) + m + k) | 0, s) + e) | 0 +} -}).call(this)}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{}],374:[function(require,module,exports){ -"use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -var toBase64_1 = __importDefault(require("./toBase64")); -function uint8ToBase64(byteArray) { - var byteString = ""; - for (var i = 0; i < byteArray.byteLength; i += 1) { - byteString += String.fromCodePoint(byteArray[i]); - } - return (0, toBase64_1.default)(byteString); -} -exports.default = uint8ToBase64; +function fn5 (a, b, c, d, e, m, k, s) { + return (rotl((a + (b ^ (c | (~d))) + m + k) | 0, s) + e) | 0 +} -},{"./toBase64":373}],375:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -function uniq(array) { - return Array.from(new Set(array)); -} -exports.default = uniq; +module.exports = RIPEMD160 -},{}],376:[function(require,module,exports){ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __generator = (this && this.__generator) || function (thisArg, body) { - var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; - return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; - function verb(n) { return function (v) { return step([n, v]); }; } - function step(op) { - if (f) throw new TypeError("Generator is already executing."); - while (_) try { - if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; - if (y = 0, t) op = [op[0] & 2, t.value]; - switch (op[0]) { - case 0: case 1: t = op; break; - case 4: _.label++; return { value: op[1], done: false }; - case 5: _.label++; y = op[1]; op = [0]; continue; - case 7: op = _.ops.pop(); _.trys.pop(); continue; - default: - if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } - if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } - if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } - if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } - if (t[2]) _.ops.pop(); - _.trys.pop(); continue; - } - op = body.call(thisArg, _); - } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } - if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; - } -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -var sha256_1 = __importDefault(require("./sha256")); -var message_1 = require("../types/message"); -var decodeKeyString_1 = __importDefault(require("./crypto/decodeKeyString")); -var importKey_1 = __importDefault(require("./crypto/importKey")); -var verifyData_1 = __importDefault(require("./crypto/verifyData")); -var __1 = require(".."); -/** - * Verifies a message validity (PoW, pubKey, timestamp, signatures) - * @param msg AnyMessage - * @param pow amount of proof of work required, number of leading zeroes (default is 0/no pow) - * @returns boolean or undefined if the message type does not match - */ -function verifyMessage(msg, pow) { - if (pow === void 0) { pow = 0; } - return __awaiter(this, void 0, void 0, function () { - var strData, publicKeyNamespace, key_1, data, pubKeyString, pubKey, verified; - var _this = this; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: - strData = JSON.stringify(msg.v); - if (msg.t === undefined || - msg.k === undefined || - msg.h === undefined || - msg.p === undefined || - msg.s === undefined) { - return [2 /*return*/, message_1.VerifyResult.InvalidData]; - } - // Max clock shift allowed is 30 seconds. - // Ten seconds was my original threshold but it failed some times. - if (msg.t > new Date().getTime() + 30000) { - // console.warn("Invalid message timestamp."); - return [2 /*return*/, message_1.VerifyResult.InvalidTimestamp]; - } - publicKeyNamespace = false; - if (msg.k.slice(0, 1) == ":") { - publicKeyNamespace = msg.k.split(".")[0].slice(1); - } - if (!(msg.k.slice(0, 2) == "==")) return [3 /*break*/, 2]; - key_1 = msg.k; - return [4 /*yield*/, new Promise(function (resolve) { - _this.store.get(key_1, function (err, data) { - if (data) { - try { - var message = JSON.parse(data); - resolve(message); - } - catch (e) { - resolve(null); - } - } - else { - resolve(null); - } - }); - })]; - case 1: - data = _a.sent(); - if (data && data.p !== msg.p) - return [2 /*return*/, message_1.VerifyResult.CantOverwrite]; - _a.label = 2; - case 2: - pubKeyString = msg.p; - if (publicKeyNamespace && publicKeyNamespace !== pubKeyString) { - // console.warn("Provided pub keys do not match"); - return [2 /*return*/, message_1.VerifyResult.PubKeyMismatch]; - } - // Verify hash and nonce (adjust zeroes for difficulty of the network) - // While this POW does not enforce security per-se, it does make it harder - // for attackers to spam the network, and could be adjusted by peers. - // Disabled for now because it is painful on large requests - if (pow > 0) { - if (msg.h.slice(0, pow) !== new Array(pow).fill("0").join("")) { - // console.warn("No valid hash (no pow)"); - return [2 /*return*/, message_1.VerifyResult.NoProofOfWork]; - } - if ((0, sha256_1.default)("" + strData + pubKeyString + msg.t + msg.n) !== msg.h) { - // console.warn("Specified hash does not generate a valid pow"); - return [2 /*return*/, message_1.VerifyResult.InvalidHashNonce]; - } - } - return [4 /*yield*/, (0, importKey_1.default)((0, decodeKeyString_1.default)(pubKeyString), "spki", "ECDSA", ["verify"])]; - case 3: - pubKey = _a.sent(); - return [4 /*yield*/, (0, verifyData_1.default)(msg.h, (0, __1.base64ToArrayBuffer)(msg.s), pubKey)]; - case 4: - verified = _a.sent(); - // console.warn(`Signature validation: ${verified ? "Sucess" : "Failed"}`); - return [2 /*return*/, verified ? message_1.VerifyResult.Verified : message_1.VerifyResult.InvalidSignature]; - } - }); - }); -} -exports.default = verifyMessage; +},{"buffer":118,"hash-base":373,"inherits":200}],373:[function(require,module,exports){ +arguments[4][242][0].apply(exports,arguments) +},{"dup":242,"inherits":200,"readable-stream":388,"safe-buffer":390}],374:[function(require,module,exports){ +arguments[4][210][0].apply(exports,arguments) +},{"dup":210}],375:[function(require,module,exports){ +arguments[4][211][0].apply(exports,arguments) +},{"./_stream_readable":377,"./_stream_writable":379,"_process":350,"dup":211,"inherits":200}],376:[function(require,module,exports){ +arguments[4][212][0].apply(exports,arguments) +},{"./_stream_transform":378,"dup":212,"inherits":200}],377:[function(require,module,exports){ +arguments[4][213][0].apply(exports,arguments) +},{"../errors":374,"./_stream_duplex":375,"./internal/streams/async_iterator":380,"./internal/streams/buffer_list":381,"./internal/streams/destroy":382,"./internal/streams/from":384,"./internal/streams/state":386,"./internal/streams/stream":387,"_process":350,"buffer":118,"dup":213,"events":172,"inherits":200,"string_decoder/":415,"util":88}],378:[function(require,module,exports){ +arguments[4][214][0].apply(exports,arguments) +},{"../errors":374,"./_stream_duplex":375,"dup":214,"inherits":200}],379:[function(require,module,exports){ +arguments[4][215][0].apply(exports,arguments) +},{"../errors":374,"./_stream_duplex":375,"./internal/streams/destroy":382,"./internal/streams/state":386,"./internal/streams/stream":387,"_process":350,"buffer":118,"dup":215,"inherits":200,"util-deprecate":417}],380:[function(require,module,exports){ +arguments[4][216][0].apply(exports,arguments) +},{"./end-of-stream":383,"_process":350,"dup":216}],381:[function(require,module,exports){ +arguments[4][217][0].apply(exports,arguments) +},{"buffer":118,"dup":217,"util":88}],382:[function(require,module,exports){ +arguments[4][218][0].apply(exports,arguments) +},{"_process":350,"dup":218}],383:[function(require,module,exports){ +arguments[4][219][0].apply(exports,arguments) +},{"../../../errors":374,"dup":219}],384:[function(require,module,exports){ +arguments[4][220][0].apply(exports,arguments) +},{"dup":220}],385:[function(require,module,exports){ +arguments[4][221][0].apply(exports,arguments) +},{"../../../errors":374,"./end-of-stream":383,"dup":221}],386:[function(require,module,exports){ +arguments[4][222][0].apply(exports,arguments) +},{"../../../errors":374,"dup":222}],387:[function(require,module,exports){ +arguments[4][223][0].apply(exports,arguments) +},{"dup":223,"events":172}],388:[function(require,module,exports){ +arguments[4][224][0].apply(exports,arguments) +},{"./lib/_stream_duplex.js":375,"./lib/_stream_passthrough.js":376,"./lib/_stream_readable.js":377,"./lib/_stream_transform.js":378,"./lib/_stream_writable.js":379,"./lib/internal/streams/end-of-stream.js":383,"./lib/internal/streams/pipeline.js":385,"dup":224}],389:[function(require,module,exports){ +/*! run-parallel-limit. MIT License. Feross Aboukhadijeh */ +module.exports = runParallelLimit -},{"..":304,"../types/message":335,"./crypto/decodeKeyString":345,"./crypto/importKey":356,"./crypto/verifyData":359,"./sha256":369}],377:[function(require,module,exports){ -"use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -var __1 = require(".."); -var tooldb_1 = require("../tooldb"); -var hexToArrayBuffer_1 = __importDefault(require("./hexToArrayBuffer")); -function verifyPeer(peer) { - // Import the public key string - return (0, __1.importKey)((0, hexToArrayBuffer_1.default)(tooldb_1.KEY_PREFIX + peer.pubkey), "spki", "ECDSA", ["verify"]).then(function (pubKey) { - return (0, __1.verifyData)((0, __1.sha256)(peer.topic + "-" + peer.timestamp + "-" + peer.host + ":" + peer.port), (0, __1.base64ToArrayBuffer)(peer.sig), pubKey, "SHA-1"); - }); -} -exports.default = verifyPeer; +const queueMicrotask = require('queue-microtask') + +function runParallelLimit (tasks, limit, cb) { + if (typeof limit !== 'number') throw new Error('second argument must be a Number') + let results, len, pending, keys, isErrored + let isSync = true + let next + + if (Array.isArray(tasks)) { + results = [] + pending = len = tasks.length + } else { + keys = Object.keys(tasks) + results = {} + pending = len = keys.length + } + + function done (err) { + function end () { + if (cb) cb(err, results) + cb = null + } + if (isSync) queueMicrotask(end) + else end() + } + + function each (i, err, result) { + results[i] = result + if (err) isErrored = true + if (--pending === 0 || err) { + done(err) + } else if (!isErrored && next < len) { + let key + if (keys) { + key = keys[next] + next += 1 + tasks[key](function (err, result) { each(key, err, result) }) + } else { + key = next + next += 1 + tasks[key](function (err, result) { each(key, err, result) }) + } + } + } + + next = limit + if (!pending) { + // empty + done(null) + } else if (keys) { + // object + keys.some(function (key, i) { + tasks[key](function (err, result) { each(key, err, result) }) + if (i === limit - 1) return true // early return + return false + }) + } else { + // array + tasks.some(function (task, i) { + task(function (err, result) { each(i, err, result) }) + if (i === limit - 1) return true // early return + return false + }) + } + + isSync = false +} + +},{"queue-microtask":357}],390:[function(require,module,exports){ +/*! safe-buffer. MIT License. Feross Aboukhadijeh */ +/* eslint-disable node/no-deprecated-api */ +var buffer = require('buffer') +var Buffer = buffer.Buffer -},{"..":304,"../tooldb":334,"./hexToArrayBuffer":363}],378:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -function waitFor(fn, interval, timeout) { - if (interval === void 0) { interval = 100; } - if (timeout === void 0) { timeout = 30000; } - return new Promise(function (resolve, reject) { - var intervalFn = setInterval(function () { - if (fn()) { - clearInterval(intervalFn); - clearTimeout(timeoutFn); - resolve(); - } - }, interval); - var timeoutFn = setTimeout(function () { - clearInterval(intervalFn); - reject(); - }, timeout); - }); -} -exports.default = waitFor; +// alternative to using Object.keys for old browsers +function copyProps (src, dst) { + for (var key in src) { + dst[key] = src[key] + } +} +if (Buffer.from && Buffer.alloc && Buffer.allocUnsafe && Buffer.allocUnsafeSlow) { + module.exports = buffer +} else { + // Copy properties from require('buffer') + copyProps(buffer, exports) + exports.Buffer = SafeBuffer +} -},{}],379:[function(require,module,exports){ -module.exports={"2.16.840.1.101.3.4.1.1": "aes-128-ecb", -"2.16.840.1.101.3.4.1.2": "aes-128-cbc", -"2.16.840.1.101.3.4.1.3": "aes-128-ofb", -"2.16.840.1.101.3.4.1.4": "aes-128-cfb", -"2.16.840.1.101.3.4.1.21": "aes-192-ecb", -"2.16.840.1.101.3.4.1.22": "aes-192-cbc", -"2.16.840.1.101.3.4.1.23": "aes-192-ofb", -"2.16.840.1.101.3.4.1.24": "aes-192-cfb", -"2.16.840.1.101.3.4.1.41": "aes-256-ecb", -"2.16.840.1.101.3.4.1.42": "aes-256-cbc", -"2.16.840.1.101.3.4.1.43": "aes-256-ofb", -"2.16.840.1.101.3.4.1.44": "aes-256-cfb" +function SafeBuffer (arg, encodingOrOffset, length) { + return Buffer(arg, encodingOrOffset, length) } -},{}],380:[function(require,module,exports){ -// from https://github.com/indutny/self-signed/blob/gh-pages/lib/asn1.js -// Fedor, you are amazing. -'use strict' -var asn1 = require('asn1.js') +SafeBuffer.prototype = Object.create(Buffer.prototype) -exports.certificate = require('./certificate') +// Copy static methods from Buffer +copyProps(Buffer, SafeBuffer) -var RSAPrivateKey = asn1.define('RSAPrivateKey', function () { - this.seq().obj( - this.key('version').int(), - this.key('modulus').int(), - this.key('publicExponent').int(), - this.key('privateExponent').int(), - this.key('prime1').int(), - this.key('prime2').int(), - this.key('exponent1').int(), - this.key('exponent2').int(), - this.key('coefficient').int() - ) -}) -exports.RSAPrivateKey = RSAPrivateKey +SafeBuffer.from = function (arg, encodingOrOffset, length) { + if (typeof arg === 'number') { + throw new TypeError('Argument must not be a number') + } + return Buffer(arg, encodingOrOffset, length) +} -var RSAPublicKey = asn1.define('RSAPublicKey', function () { - this.seq().obj( - this.key('modulus').int(), - this.key('publicExponent').int() - ) -}) -exports.RSAPublicKey = RSAPublicKey +SafeBuffer.alloc = function (size, fill, encoding) { + if (typeof size !== 'number') { + throw new TypeError('Argument must be a number') + } + var buf = Buffer(size) + if (fill !== undefined) { + if (typeof encoding === 'string') { + buf.fill(fill, encoding) + } else { + buf.fill(fill) + } + } else { + buf.fill(0) + } + return buf +} -var PublicKey = asn1.define('SubjectPublicKeyInfo', function () { - this.seq().obj( - this.key('algorithm').use(AlgorithmIdentifier), - this.key('subjectPublicKey').bitstr() - ) -}) -exports.PublicKey = PublicKey +SafeBuffer.allocUnsafe = function (size) { + if (typeof size !== 'number') { + throw new TypeError('Argument must be a number') + } + return Buffer(size) +} -var AlgorithmIdentifier = asn1.define('AlgorithmIdentifier', function () { - this.seq().obj( - this.key('algorithm').objid(), - this.key('none').null_().optional(), - this.key('curve').objid().optional(), - this.key('params').seq().obj( - this.key('p').int(), - this.key('q').int(), - this.key('g').int() - ).optional() - ) -}) +SafeBuffer.allocUnsafeSlow = function (size) { + if (typeof size !== 'number') { + throw new TypeError('Argument must be a number') + } + return buffer.SlowBuffer(size) +} -var PrivateKeyInfo = asn1.define('PrivateKeyInfo', function () { - this.seq().obj( - this.key('version').int(), - this.key('algorithm').use(AlgorithmIdentifier), - this.key('subjectPrivateKey').octstr() - ) -}) -exports.PrivateKey = PrivateKeyInfo -var EncryptedPrivateKeyInfo = asn1.define('EncryptedPrivateKeyInfo', function () { - this.seq().obj( - this.key('algorithm').seq().obj( - this.key('id').objid(), - this.key('decrypt').seq().obj( - this.key('kde').seq().obj( - this.key('id').objid(), - this.key('kdeparams').seq().obj( - this.key('salt').octstr(), - this.key('iters').int() - ) - ), - this.key('cipher').seq().obj( - this.key('algo').objid(), - this.key('iv').octstr() - ) - ) - ), - this.key('subjectPrivateKey').octstr() - ) -}) +},{"buffer":118}],391:[function(require,module,exports){ +'use strict'; -exports.EncryptedPrivateKey = EncryptedPrivateKeyInfo +var GetIntrinsic = require('get-intrinsic'); +var define = require('define-data-property'); +var hasDescriptors = require('has-property-descriptors')(); +var gOPD = require('gopd'); -var DSAPrivateKey = asn1.define('DSAPrivateKey', function () { - this.seq().obj( - this.key('version').int(), - this.key('p').int(), - this.key('q').int(), - this.key('g').int(), - this.key('pub_key').int(), - this.key('priv_key').int() - ) -}) -exports.DSAPrivateKey = DSAPrivateKey +var $TypeError = require('es-errors/type'); +var $floor = GetIntrinsic('%Math.floor%'); -exports.DSAparam = asn1.define('DSAparam', function () { - this.int() -}) +/** @type {import('.')} */ +module.exports = function setFunctionLength(fn, length) { + if (typeof fn !== 'function') { + throw new $TypeError('`fn` is not a function'); + } + if (typeof length !== 'number' || length < 0 || length > 0xFFFFFFFF || $floor(length) !== length) { + throw new $TypeError('`length` must be a positive 32-bit integer'); + } -var ECPrivateKey = asn1.define('ECPrivateKey', function () { - this.seq().obj( - this.key('version').int(), - this.key('privateKey').octstr(), - this.key('parameters').optional().explicit(0).use(ECParameters), - this.key('publicKey').optional().explicit(1).bitstr() - ) -}) -exports.ECPrivateKey = ECPrivateKey + var loose = arguments.length > 2 && !!arguments[2]; -var ECParameters = asn1.define('ECParameters', function () { - this.choice({ - namedCurve: this.objid() - }) -}) + var functionLengthIsConfigurable = true; + var functionLengthIsWritable = true; + if ('length' in fn && gOPD) { + var desc = gOPD(fn, 'length'); + if (desc && !desc.configurable) { + functionLengthIsConfigurable = false; + } + if (desc && !desc.writable) { + functionLengthIsWritable = false; + } + } -exports.signature = asn1.define('signature', function () { - this.seq().obj( - this.key('r').int(), - this.key('s').int() - ) -}) + if (functionLengthIsConfigurable || functionLengthIsWritable || !loose) { + if (hasDescriptors) { + define(/** @type {Parameters[0]} */ (fn), 'length', length, true, true); + } else { + define(/** @type {Parameters[0]} */ (fn), 'length', length); + } + } + return fn; +}; -},{"./certificate":381,"asn1.js":33}],381:[function(require,module,exports){ -// from https://github.com/Rantanen/node-dtls/blob/25a7dc861bda38cfeac93a723500eea4f0ac2e86/Certificate.js -// thanks to @Rantanen +},{"define-data-property":136,"es-errors/type":170,"get-intrinsic":178,"gopd":179,"has-property-descriptors":180}],392:[function(require,module,exports){ +var Buffer = require('safe-buffer').Buffer -'use strict' +// prototype class for hash functions +function Hash (blockSize, finalSize) { + this._block = Buffer.alloc(blockSize) + this._finalSize = finalSize + this._blockSize = blockSize + this._len = 0 +} -var asn = require('asn1.js') +Hash.prototype.update = function (data, enc) { + if (typeof data === 'string') { + enc = enc || 'utf8' + data = Buffer.from(data, enc) + } -var Time = asn.define('Time', function () { - this.choice({ - utcTime: this.utctime(), - generalTime: this.gentime() - }) -}) + var block = this._block + var blockSize = this._blockSize + var length = data.length + var accum = this._len -var AttributeTypeValue = asn.define('AttributeTypeValue', function () { - this.seq().obj( - this.key('type').objid(), - this.key('value').any() - ) -}) + for (var offset = 0; offset < length;) { + var assigned = accum % blockSize + var remainder = Math.min(length - offset, blockSize - assigned) -var AlgorithmIdentifier = asn.define('AlgorithmIdentifier', function () { - this.seq().obj( - this.key('algorithm').objid(), - this.key('parameters').optional(), - this.key('curve').objid().optional() - ) -}) + for (var i = 0; i < remainder; i++) { + block[assigned + i] = data[offset + i] + } -var SubjectPublicKeyInfo = asn.define('SubjectPublicKeyInfo', function () { - this.seq().obj( - this.key('algorithm').use(AlgorithmIdentifier), - this.key('subjectPublicKey').bitstr() - ) -}) + accum += remainder + offset += remainder -var RelativeDistinguishedName = asn.define('RelativeDistinguishedName', function () { - this.setof(AttributeTypeValue) -}) + if ((accum % blockSize) === 0) { + this._update(block) + } + } -var RDNSequence = asn.define('RDNSequence', function () { - this.seqof(RelativeDistinguishedName) -}) + this._len += length + return this +} -var Name = asn.define('Name', function () { - this.choice({ - rdnSequence: this.use(RDNSequence) - }) -}) +Hash.prototype.digest = function (enc) { + var rem = this._len % this._blockSize -var Validity = asn.define('Validity', function () { - this.seq().obj( - this.key('notBefore').use(Time), - this.key('notAfter').use(Time) - ) -}) + this._block[rem] = 0x80 -var Extension = asn.define('Extension', function () { - this.seq().obj( - this.key('extnID').objid(), - this.key('critical').bool().def(false), - this.key('extnValue').octstr() - ) -}) + // zero (rem + 1) trailing bits, where (rem + 1) is the smallest + // non-negative solution to the equation (length + 1 + (rem + 1)) === finalSize mod blockSize + this._block.fill(0, rem + 1) -var TBSCertificate = asn.define('TBSCertificate', function () { - this.seq().obj( - this.key('version').explicit(0).int().optional(), - this.key('serialNumber').int(), - this.key('signature').use(AlgorithmIdentifier), - this.key('issuer').use(Name), - this.key('validity').use(Validity), - this.key('subject').use(Name), - this.key('subjectPublicKeyInfo').use(SubjectPublicKeyInfo), - this.key('issuerUniqueID').implicit(1).bitstr().optional(), - this.key('subjectUniqueID').implicit(2).bitstr().optional(), - this.key('extensions').explicit(3).seqof(Extension).optional() - ) -}) + if (rem >= this._finalSize) { + this._update(this._block) + this._block.fill(0) + } -var X509Certificate = asn.define('X509Certificate', function () { - this.seq().obj( - this.key('tbsCertificate').use(TBSCertificate), - this.key('signatureAlgorithm').use(AlgorithmIdentifier), - this.key('signatureValue').bitstr() - ) -}) + var bits = this._len * 8 -module.exports = X509Certificate + // uint32 + if (bits <= 0xffffffff) { + this._block.writeUInt32BE(bits, this._blockSize - 4) -},{"asn1.js":33}],382:[function(require,module,exports){ -// adapted from https://github.com/apatil/pemstrip -var findProc = /Proc-Type: 4,ENCRYPTED[\n\r]+DEK-Info: AES-((?:128)|(?:192)|(?:256))-CBC,([0-9A-H]+)[\n\r]+([0-9A-z\n\r+/=]+)[\n\r]+/m -var startRegex = /^-----BEGIN ((?:.*? KEY)|CERTIFICATE)-----/m -var fullRegex = /^-----BEGIN ((?:.*? KEY)|CERTIFICATE)-----([0-9A-z\n\r+/=]+)-----END \1-----$/m -var evp = require('evp_bytestokey') -var ciphers = require('browserify-aes') -var Buffer = require('safe-buffer').Buffer -module.exports = function (okey, password) { - var key = okey.toString() - var match = key.match(findProc) - var decrypted - if (!match) { - var match2 = key.match(fullRegex) - decrypted = Buffer.from(match2[2].replace(/[\r\n]/g, ''), 'base64') + // uint64 } else { - var suite = 'aes' + match[1] - var iv = Buffer.from(match[2], 'hex') - var cipherText = Buffer.from(match[3].replace(/[\r\n]/g, ''), 'base64') - var cipherKey = evp(password, iv.slice(0, 8), parseInt(match[1], 10)).key - var out = [] - var cipher = ciphers.createDecipheriv(suite, cipherKey, iv) - out.push(cipher.update(cipherText)) - out.push(cipher.final()) - decrypted = Buffer.concat(out) - } - var tag = key.match(startRegex)[1] - return { - tag: tag, - data: decrypted + var lowBits = (bits & 0xffffffff) >>> 0 + var highBits = (bits - lowBits) / 0x100000000 + + this._block.writeUInt32BE(highBits, this._blockSize - 8) + this._block.writeUInt32BE(lowBits, this._blockSize - 4) } + + this._update(this._block) + var hash = this._hash() + + return enc ? hash.toString(enc) : hash } -},{"browserify-aes":96,"evp_bytestokey":212,"safe-buffer":404}],383:[function(require,module,exports){ -var asn1 = require('./asn1') -var aesid = require('./aesid.json') -var fixProc = require('./fixProc') -var ciphers = require('browserify-aes') -var compat = require('pbkdf2') -var Buffer = require('safe-buffer').Buffer -module.exports = parseKeys - -function parseKeys (buffer) { - var password - if (typeof buffer === 'object' && !Buffer.isBuffer(buffer)) { - password = buffer.passphrase - buffer = buffer.key - } - if (typeof buffer === 'string') { - buffer = Buffer.from(buffer) - } - - var stripped = fixProc(buffer, password) - - var type = stripped.tag - var data = stripped.data - var subtype, ndata - switch (type) { - case 'CERTIFICATE': - ndata = asn1.certificate.decode(data, 'der').tbsCertificate.subjectPublicKeyInfo - // falls through - case 'PUBLIC KEY': - if (!ndata) { - ndata = asn1.PublicKey.decode(data, 'der') - } - subtype = ndata.algorithm.algorithm.join('.') - switch (subtype) { - case '1.2.840.113549.1.1.1': - return asn1.RSAPublicKey.decode(ndata.subjectPublicKey.data, 'der') - case '1.2.840.10045.2.1': - ndata.subjectPrivateKey = ndata.subjectPublicKey - return { - type: 'ec', - data: ndata - } - case '1.2.840.10040.4.1': - ndata.algorithm.params.pub_key = asn1.DSAparam.decode(ndata.subjectPublicKey.data, 'der') - return { - type: 'dsa', - data: ndata.algorithm.params - } - default: throw new Error('unknown key id ' + subtype) - } - // throw new Error('unknown key type ' + type) - case 'ENCRYPTED PRIVATE KEY': - data = asn1.EncryptedPrivateKey.decode(data, 'der') - data = decrypt(data, password) - // falls through - case 'PRIVATE KEY': - ndata = asn1.PrivateKey.decode(data, 'der') - subtype = ndata.algorithm.algorithm.join('.') - switch (subtype) { - case '1.2.840.113549.1.1.1': - return asn1.RSAPrivateKey.decode(ndata.subjectPrivateKey, 'der') - case '1.2.840.10045.2.1': - return { - curve: ndata.algorithm.curve, - privateKey: asn1.ECPrivateKey.decode(ndata.subjectPrivateKey, 'der').privateKey - } - case '1.2.840.10040.4.1': - ndata.algorithm.params.priv_key = asn1.DSAparam.decode(ndata.subjectPrivateKey, 'der') - return { - type: 'dsa', - params: ndata.algorithm.params - } - default: throw new Error('unknown key id ' + subtype) - } - // throw new Error('unknown key type ' + type) - case 'RSA PUBLIC KEY': - return asn1.RSAPublicKey.decode(data, 'der') - case 'RSA PRIVATE KEY': - return asn1.RSAPrivateKey.decode(data, 'der') - case 'DSA PRIVATE KEY': - return { - type: 'dsa', - params: asn1.DSAPrivateKey.decode(data, 'der') - } - case 'EC PRIVATE KEY': - data = asn1.ECPrivateKey.decode(data, 'der') - return { - curve: data.parameters.value, - privateKey: data.privateKey - } - default: throw new Error('unknown key type ' + type) - } -} -parseKeys.signature = asn1.signature -function decrypt (data, password) { - var salt = data.algorithm.decrypt.kde.kdeparams.salt - var iters = parseInt(data.algorithm.decrypt.kde.kdeparams.iters.toString(), 10) - var algo = aesid[data.algorithm.decrypt.cipher.algo.join('.')] - var iv = data.algorithm.decrypt.cipher.iv - var cipherText = data.subjectPrivateKey - var keylen = parseInt(algo.split('-')[1], 10) / 8 - var key = compat.pbkdf2Sync(password, salt, iters, keylen, 'sha1') - var cipher = ciphers.createDecipheriv(algo, key, iv) - var out = [] - out.push(cipher.update(cipherText)) - out.push(cipher.final()) - return Buffer.concat(out) +Hash.prototype._update = function () { + throw new Error('_update must be implemented by subclass') } -},{"./aesid.json":379,"./asn1":380,"./fixProc":382,"browserify-aes":96,"pbkdf2":384,"safe-buffer":404}],384:[function(require,module,exports){ -exports.pbkdf2 = require('./lib/async') -exports.pbkdf2Sync = require('./lib/sync') +module.exports = Hash -},{"./lib/async":385,"./lib/sync":388}],385:[function(require,module,exports){ -(function (global){(function (){ +},{"safe-buffer":390}],393:[function(require,module,exports){ +var exports = module.exports = function SHA (algorithm) { + algorithm = algorithm.toLowerCase() + + var Algorithm = exports[algorithm] + if (!Algorithm) throw new Error(algorithm + ' is not supported (we accept pull requests)') + + return new Algorithm() +} + +exports.sha = require('./sha') +exports.sha1 = require('./sha1') +exports.sha224 = require('./sha224') +exports.sha256 = require('./sha256') +exports.sha384 = require('./sha384') +exports.sha512 = require('./sha512') + +},{"./sha":394,"./sha1":395,"./sha224":396,"./sha256":397,"./sha384":398,"./sha512":399}],394:[function(require,module,exports){ +/* + * A JavaScript implementation of the Secure Hash Algorithm, SHA-0, as defined + * in FIPS PUB 180-1 + * This source code is derived from sha1.js of the same repository. + * The difference between SHA-0 and SHA-1 is just a bitwise rotate left + * operation was added. + */ + +var inherits = require('inherits') +var Hash = require('./hash') var Buffer = require('safe-buffer').Buffer -var checkParameters = require('./precondition') -var defaultEncoding = require('./default-encoding') -var sync = require('./sync') -var toBuffer = require('./to-buffer') +var K = [ + 0x5a827999, 0x6ed9eba1, 0x8f1bbcdc | 0, 0xca62c1d6 | 0 +] -var ZERO_BUF -var subtle = global.crypto && global.crypto.subtle -var toBrowser = { - sha: 'SHA-1', - 'sha-1': 'SHA-1', - sha1: 'SHA-1', - sha256: 'SHA-256', - 'sha-256': 'SHA-256', - sha384: 'SHA-384', - 'sha-384': 'SHA-384', - 'sha-512': 'SHA-512', - sha512: 'SHA-512' +var W = new Array(80) + +function Sha () { + this.init() + this._w = W + + Hash.call(this, 64, 56) } -var checks = [] -function checkNative (algo) { - if (global.process && !global.process.browser) { - return Promise.resolve(false) - } - if (!subtle || !subtle.importKey || !subtle.deriveBits) { - return Promise.resolve(false) - } - if (checks[algo] !== undefined) { - return checks[algo] - } - ZERO_BUF = ZERO_BUF || Buffer.alloc(8) - var prom = browserPbkdf2(ZERO_BUF, ZERO_BUF, 10, 128, algo) - .then(function () { - return true - }).catch(function () { - return false - }) - checks[algo] = prom - return prom + +inherits(Sha, Hash) + +Sha.prototype.init = function () { + this._a = 0x67452301 + this._b = 0xefcdab89 + this._c = 0x98badcfe + this._d = 0x10325476 + this._e = 0xc3d2e1f0 + + return this } -var nextTick -function getNextTick () { - if (nextTick) { - return nextTick - } - if (global.process && global.process.nextTick) { - nextTick = global.process.nextTick - } else if (global.queueMicrotask) { - nextTick = global.queueMicrotask - } else if (global.setImmediate) { - nextTick = global.setImmediate - } else { - nextTick = global.setTimeout - } - return nextTick + +function rotl5 (num) { + return (num << 5) | (num >>> 27) } -function browserPbkdf2 (password, salt, iterations, length, algo) { - return subtle.importKey( - 'raw', password, { name: 'PBKDF2' }, false, ['deriveBits'] - ).then(function (key) { - return subtle.deriveBits({ - name: 'PBKDF2', - salt: salt, - iterations: iterations, - hash: { - name: algo - } - }, key, length << 3) - }).then(function (res) { - return Buffer.from(res) - }) + +function rotl30 (num) { + return (num << 30) | (num >>> 2) } -function resolvePromise (promise, callback) { - promise.then(function (out) { - getNextTick()(function () { - callback(null, out) - }) - }, function (e) { - getNextTick()(function () { - callback(e) - }) - }) +function ft (s, b, c, d) { + if (s === 0) return (b & c) | ((~b) & d) + if (s === 2) return (b & c) | (b & d) | (c & d) + return b ^ c ^ d } -module.exports = function (password, salt, iterations, keylen, digest, callback) { - if (typeof digest === 'function') { - callback = digest - digest = undefined - } - digest = digest || 'sha1' - var algo = toBrowser[digest.toLowerCase()] +Sha.prototype._update = function (M) { + var W = this._w - if (!algo || typeof global.Promise !== 'function') { - getNextTick()(function () { - var out - try { - out = sync(password, salt, iterations, keylen, digest) - } catch (e) { - return callback(e) - } - callback(null, out) - }) - return - } + var a = this._a | 0 + var b = this._b | 0 + var c = this._c | 0 + var d = this._d | 0 + var e = this._e | 0 - checkParameters(iterations, keylen) - password = toBuffer(password, defaultEncoding, 'Password') - salt = toBuffer(salt, defaultEncoding, 'Salt') - if (typeof callback !== 'function') throw new Error('No callback provided to pbkdf2') + for (var i = 0; i < 16; ++i) W[i] = M.readInt32BE(i * 4) + for (; i < 80; ++i) W[i] = W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16] - resolvePromise(checkNative(algo).then(function (resp) { - if (resp) return browserPbkdf2(password, salt, iterations, keylen, algo) + for (var j = 0; j < 80; ++j) { + var s = ~~(j / 20) + var t = (rotl5(a) + ft(s, b, c, d) + e + W[j] + K[s]) | 0 - return sync(password, salt, iterations, keylen, digest) - }), callback) + e = d + d = c + c = rotl30(b) + b = a + a = t + } + + this._a = (a + this._a) | 0 + this._b = (b + this._b) | 0 + this._c = (c + this._c) | 0 + this._d = (d + this._d) | 0 + this._e = (e + this._e) | 0 } -}).call(this)}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"./default-encoding":386,"./precondition":387,"./sync":388,"./to-buffer":389,"safe-buffer":404}],386:[function(require,module,exports){ -(function (process,global){(function (){ -var defaultEncoding -/* istanbul ignore next */ -if (global.process && global.process.browser) { - defaultEncoding = 'utf-8' -} else if (global.process && global.process.version) { - var pVersionMajor = parseInt(process.version.split('.')[0].slice(1), 10) +Sha.prototype._hash = function () { + var H = Buffer.allocUnsafe(20) - defaultEncoding = pVersionMajor >= 6 ? 'utf-8' : 'binary' -} else { - defaultEncoding = 'utf-8' + H.writeInt32BE(this._a | 0, 0) + H.writeInt32BE(this._b | 0, 4) + H.writeInt32BE(this._c | 0, 8) + H.writeInt32BE(this._d | 0, 12) + H.writeInt32BE(this._e | 0, 16) + + return H } -module.exports = defaultEncoding -}).call(this)}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"_process":391}],387:[function(require,module,exports){ -var MAX_ALLOC = Math.pow(2, 30) - 1 // default in iojs +module.exports = Sha -module.exports = function (iterations, keylen) { - if (typeof iterations !== 'number') { - throw new TypeError('Iterations not a number') - } +},{"./hash":392,"inherits":200,"safe-buffer":390}],395:[function(require,module,exports){ +/* + * A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined + * in FIPS PUB 180-1 + * Version 2.1a Copyright Paul Johnston 2000 - 2002. + * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet + * Distributed under the BSD License + * See http://pajhome.org.uk/crypt/md5 for details. + */ + +var inherits = require('inherits') +var Hash = require('./hash') +var Buffer = require('safe-buffer').Buffer + +var K = [ + 0x5a827999, 0x6ed9eba1, 0x8f1bbcdc | 0, 0xca62c1d6 | 0 +] + +var W = new Array(80) + +function Sha1 () { + this.init() + this._w = W + + Hash.call(this, 64, 56) +} + +inherits(Sha1, Hash) - if (iterations < 0) { - throw new TypeError('Bad iterations') - } +Sha1.prototype.init = function () { + this._a = 0x67452301 + this._b = 0xefcdab89 + this._c = 0x98badcfe + this._d = 0x10325476 + this._e = 0xc3d2e1f0 - if (typeof keylen !== 'number') { - throw new TypeError('Key length not a number') - } + return this +} - if (keylen < 0 || keylen > MAX_ALLOC || keylen !== keylen) { /* eslint no-self-compare: 0 */ - throw new TypeError('Bad key length') - } +function rotl1 (num) { + return (num << 1) | (num >>> 31) } -},{}],388:[function(require,module,exports){ -var md5 = require('create-hash/md5') -var RIPEMD160 = require('ripemd160') -var sha = require('sha.js') -var Buffer = require('safe-buffer').Buffer +function rotl5 (num) { + return (num << 5) | (num >>> 27) +} -var checkParameters = require('./precondition') -var defaultEncoding = require('./default-encoding') -var toBuffer = require('./to-buffer') +function rotl30 (num) { + return (num << 30) | (num >>> 2) +} -var ZEROS = Buffer.alloc(128) -var sizes = { - md5: 16, - sha1: 20, - sha224: 28, - sha256: 32, - sha384: 48, - sha512: 64, - rmd160: 20, - ripemd160: 20 +function ft (s, b, c, d) { + if (s === 0) return (b & c) | ((~b) & d) + if (s === 2) return (b & c) | (b & d) | (c & d) + return b ^ c ^ d } -function Hmac (alg, key, saltLen) { - var hash = getDigest(alg) - var blocksize = (alg === 'sha512' || alg === 'sha384') ? 128 : 64 +Sha1.prototype._update = function (M) { + var W = this._w - if (key.length > blocksize) { - key = hash(key) - } else if (key.length < blocksize) { - key = Buffer.concat([key, ZEROS], blocksize) - } + var a = this._a | 0 + var b = this._b | 0 + var c = this._c | 0 + var d = this._d | 0 + var e = this._e | 0 - var ipad = Buffer.allocUnsafe(blocksize + sizes[alg]) - var opad = Buffer.allocUnsafe(blocksize + sizes[alg]) - for (var i = 0; i < blocksize; i++) { - ipad[i] = key[i] ^ 0x36 - opad[i] = key[i] ^ 0x5C + for (var i = 0; i < 16; ++i) W[i] = M.readInt32BE(i * 4) + for (; i < 80; ++i) W[i] = rotl1(W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16]) + + for (var j = 0; j < 80; ++j) { + var s = ~~(j / 20) + var t = (rotl5(a) + ft(s, b, c, d) + e + W[j] + K[s]) | 0 + + e = d + d = c + c = rotl30(b) + b = a + a = t } - var ipad1 = Buffer.allocUnsafe(blocksize + saltLen + 4) - ipad.copy(ipad1, 0, 0, blocksize) - this.ipad1 = ipad1 - this.ipad2 = ipad - this.opad = opad - this.alg = alg - this.blocksize = blocksize - this.hash = hash - this.size = sizes[alg] + this._a = (a + this._a) | 0 + this._b = (b + this._b) | 0 + this._c = (c + this._c) | 0 + this._d = (d + this._d) | 0 + this._e = (e + this._e) | 0 } -Hmac.prototype.run = function (data, ipad) { - data.copy(ipad, this.blocksize) - var h = this.hash(ipad) - h.copy(this.opad, this.blocksize) - return this.hash(this.opad) -} +Sha1.prototype._hash = function () { + var H = Buffer.allocUnsafe(20) -function getDigest (alg) { - function shaFunc (data) { - return sha(alg).update(data).digest() - } - function rmd160Func (data) { - return new RIPEMD160().update(data).digest() - } + H.writeInt32BE(this._a | 0, 0) + H.writeInt32BE(this._b | 0, 4) + H.writeInt32BE(this._c | 0, 8) + H.writeInt32BE(this._d | 0, 12) + H.writeInt32BE(this._e | 0, 16) - if (alg === 'rmd160' || alg === 'ripemd160') return rmd160Func - if (alg === 'md5') return md5 - return shaFunc + return H } -function pbkdf2 (password, salt, iterations, keylen, digest) { - checkParameters(iterations, keylen) - password = toBuffer(password, defaultEncoding, 'Password') - salt = toBuffer(salt, defaultEncoding, 'Salt') +module.exports = Sha1 - digest = digest || 'sha1' +},{"./hash":392,"inherits":200,"safe-buffer":390}],396:[function(require,module,exports){ +/** + * A JavaScript implementation of the Secure Hash Algorithm, SHA-256, as defined + * in FIPS 180-2 + * Version 2.2-beta Copyright Angel Marin, Paul Johnston 2000 - 2009. + * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet + * + */ - var hmac = new Hmac(digest, password, salt.length) +var inherits = require('inherits') +var Sha256 = require('./sha256') +var Hash = require('./hash') +var Buffer = require('safe-buffer').Buffer - var DK = Buffer.allocUnsafe(keylen) - var block1 = Buffer.allocUnsafe(salt.length + 4) - salt.copy(block1, 0, 0, salt.length) +var W = new Array(64) - var destPos = 0 - var hLen = sizes[digest] - var l = Math.ceil(keylen / hLen) +function Sha224 () { + this.init() - for (var i = 1; i <= l; i++) { - block1.writeUInt32BE(i, salt.length) + this._w = W // new Array(64) - var T = hmac.run(block1, hmac.ipad1) - var U = T + Hash.call(this, 64, 56) +} - for (var j = 1; j < iterations; j++) { - U = hmac.run(U, hmac.ipad2) - for (var k = 0; k < hLen; k++) T[k] ^= U[k] - } +inherits(Sha224, Sha256) - T.copy(DK, destPos) - destPos += hLen - } +Sha224.prototype.init = function () { + this._a = 0xc1059ed8 + this._b = 0x367cd507 + this._c = 0x3070dd17 + this._d = 0xf70e5939 + this._e = 0xffc00b31 + this._f = 0x68581511 + this._g = 0x64f98fa7 + this._h = 0xbefa4fa4 - return DK + return this } -module.exports = pbkdf2 +Sha224.prototype._hash = function () { + var H = Buffer.allocUnsafe(28) -},{"./default-encoding":386,"./precondition":387,"./to-buffer":389,"create-hash/md5":165,"ripemd160":402,"safe-buffer":404,"sha.js":408}],389:[function(require,module,exports){ -var Buffer = require('safe-buffer').Buffer + H.writeInt32BE(this._a, 0) + H.writeInt32BE(this._b, 4) + H.writeInt32BE(this._c, 8) + H.writeInt32BE(this._d, 12) + H.writeInt32BE(this._e, 16) + H.writeInt32BE(this._f, 20) + H.writeInt32BE(this._g, 24) -module.exports = function (thing, encoding, name) { - if (Buffer.isBuffer(thing)) { - return thing - } else if (typeof thing === 'string') { - return Buffer.from(thing, encoding) - } else if (ArrayBuffer.isView(thing)) { - return Buffer.from(thing.buffer) - } else { - throw new TypeError(name + ' must be a string, a Buffer, a typed array or a DataView') - } + return H } -},{"safe-buffer":404}],390:[function(require,module,exports){ -'use strict'; +module.exports = Sha224 -/** @type {import('.')} */ -module.exports = [ - 'Float32Array', - 'Float64Array', - 'Int8Array', - 'Int16Array', - 'Int32Array', - 'Uint8Array', - 'Uint8ClampedArray', - 'Uint16Array', - 'Uint32Array', - 'BigInt64Array', - 'BigUint64Array' -]; +},{"./hash":392,"./sha256":397,"inherits":200,"safe-buffer":390}],397:[function(require,module,exports){ +/** + * A JavaScript implementation of the Secure Hash Algorithm, SHA-256, as defined + * in FIPS 180-2 + * Version 2.2-beta Copyright Angel Marin, Paul Johnston 2000 - 2009. + * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet + * + */ -},{}],391:[function(require,module,exports){ -// shim for using process in browser -var process = module.exports = {}; +var inherits = require('inherits') +var Hash = require('./hash') +var Buffer = require('safe-buffer').Buffer -// cached from whatever global is present so that test runners that stub it -// don't break things. But we need to wrap it in a try catch in case it is -// wrapped in strict mode code which doesn't define any globals. It's inside a -// function because try/catches deoptimize in certain engines. +var K = [ + 0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5, + 0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5, + 0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3, + 0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174, + 0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC, + 0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA, + 0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7, + 0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967, + 0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13, + 0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85, + 0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3, + 0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070, + 0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5, + 0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3, + 0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208, + 0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2 +] -var cachedSetTimeout; -var cachedClearTimeout; +var W = new Array(64) -function defaultSetTimout() { - throw new Error('setTimeout has not been defined'); -} -function defaultClearTimeout () { - throw new Error('clearTimeout has not been defined'); +function Sha256 () { + this.init() + + this._w = W // new Array(64) + + Hash.call(this, 64, 56) } -(function () { - try { - if (typeof setTimeout === 'function') { - cachedSetTimeout = setTimeout; - } else { - cachedSetTimeout = defaultSetTimout; - } - } catch (e) { - cachedSetTimeout = defaultSetTimout; - } - try { - if (typeof clearTimeout === 'function') { - cachedClearTimeout = clearTimeout; - } else { - cachedClearTimeout = defaultClearTimeout; - } - } catch (e) { - cachedClearTimeout = defaultClearTimeout; - } -} ()) -function runTimeout(fun) { - if (cachedSetTimeout === setTimeout) { - //normal enviroments in sane situations - return setTimeout(fun, 0); - } - // if setTimeout wasn't available but was latter defined - if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) { - cachedSetTimeout = setTimeout; - return setTimeout(fun, 0); - } - try { - // when when somebody has screwed with setTimeout but no I.E. maddness - return cachedSetTimeout(fun, 0); - } catch(e){ - try { - // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally - return cachedSetTimeout.call(null, fun, 0); - } catch(e){ - // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error - return cachedSetTimeout.call(this, fun, 0); - } - } +inherits(Sha256, Hash) + +Sha256.prototype.init = function () { + this._a = 0x6a09e667 + this._b = 0xbb67ae85 + this._c = 0x3c6ef372 + this._d = 0xa54ff53a + this._e = 0x510e527f + this._f = 0x9b05688c + this._g = 0x1f83d9ab + this._h = 0x5be0cd19 + return this } -function runClearTimeout(marker) { - if (cachedClearTimeout === clearTimeout) { - //normal enviroments in sane situations - return clearTimeout(marker); - } - // if clearTimeout wasn't available but was latter defined - if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) { - cachedClearTimeout = clearTimeout; - return clearTimeout(marker); - } - try { - // when when somebody has screwed with setTimeout but no I.E. maddness - return cachedClearTimeout(marker); - } catch (e){ - try { - // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally - return cachedClearTimeout.call(null, marker); - } catch (e){ - // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error. - // Some versions of I.E. have different rules for clearTimeout vs setTimeout - return cachedClearTimeout.call(this, marker); - } - } +function ch (x, y, z) { + return z ^ (x & (y ^ z)) +} +function maj (x, y, z) { + return (x & y) | (z & (x | y)) +} +function sigma0 (x) { + return (x >>> 2 | x << 30) ^ (x >>> 13 | x << 19) ^ (x >>> 22 | x << 10) } -var queue = []; -var draining = false; -var currentQueue; -var queueIndex = -1; -function cleanUpNextTick() { - if (!draining || !currentQueue) { - return; - } - draining = false; - if (currentQueue.length) { - queue = currentQueue.concat(queue); - } else { - queueIndex = -1; - } - if (queue.length) { - drainQueue(); - } +function sigma1 (x) { + return (x >>> 6 | x << 26) ^ (x >>> 11 | x << 21) ^ (x >>> 25 | x << 7) } -function drainQueue() { - if (draining) { - return; - } - var timeout = runTimeout(cleanUpNextTick); - draining = true; +function gamma0 (x) { + return (x >>> 7 | x << 25) ^ (x >>> 18 | x << 14) ^ (x >>> 3) +} - var len = queue.length; - while(len) { - currentQueue = queue; - queue = []; - while (++queueIndex < len) { - if (currentQueue) { - currentQueue[queueIndex].run(); - } - } - queueIndex = -1; - len = queue.length; - } - currentQueue = null; - draining = false; - runClearTimeout(timeout); +function gamma1 (x) { + return (x >>> 17 | x << 15) ^ (x >>> 19 | x << 13) ^ (x >>> 10) } -process.nextTick = function (fun) { - var args = new Array(arguments.length - 1); - if (arguments.length > 1) { - for (var i = 1; i < arguments.length; i++) { - args[i - 1] = arguments[i]; - } - } - queue.push(new Item(fun, args)); - if (queue.length === 1 && !draining) { - runTimeout(drainQueue); - } -}; +Sha256.prototype._update = function (M) { + var W = this._w -// v8 likes predictible objects -function Item(fun, array) { - this.fun = fun; - this.array = array; + var a = this._a | 0 + var b = this._b | 0 + var c = this._c | 0 + var d = this._d | 0 + var e = this._e | 0 + var f = this._f | 0 + var g = this._g | 0 + var h = this._h | 0 + + for (var i = 0; i < 16; ++i) W[i] = M.readInt32BE(i * 4) + for (; i < 64; ++i) W[i] = (gamma1(W[i - 2]) + W[i - 7] + gamma0(W[i - 15]) + W[i - 16]) | 0 + + for (var j = 0; j < 64; ++j) { + var T1 = (h + sigma1(e) + ch(e, f, g) + K[j] + W[j]) | 0 + var T2 = (sigma0(a) + maj(a, b, c)) | 0 + + h = g + g = f + f = e + e = (d + T1) | 0 + d = c + c = b + b = a + a = (T1 + T2) | 0 + } + + this._a = (a + this._a) | 0 + this._b = (b + this._b) | 0 + this._c = (c + this._c) | 0 + this._d = (d + this._d) | 0 + this._e = (e + this._e) | 0 + this._f = (f + this._f) | 0 + this._g = (g + this._g) | 0 + this._h = (h + this._h) | 0 } -Item.prototype.run = function () { - this.fun.apply(null, this.array); -}; -process.title = 'browser'; -process.browser = true; -process.env = {}; -process.argv = []; -process.version = ''; // empty string to avoid regexp issues -process.versions = {}; -function noop() {} +Sha256.prototype._hash = function () { + var H = Buffer.allocUnsafe(32) -process.on = noop; -process.addListener = noop; -process.once = noop; -process.off = noop; -process.removeListener = noop; -process.removeAllListeners = noop; -process.emit = noop; -process.prependListener = noop; -process.prependOnceListener = noop; + H.writeInt32BE(this._a, 0) + H.writeInt32BE(this._b, 4) + H.writeInt32BE(this._c, 8) + H.writeInt32BE(this._d, 12) + H.writeInt32BE(this._e, 16) + H.writeInt32BE(this._f, 20) + H.writeInt32BE(this._g, 24) + H.writeInt32BE(this._h, 28) -process.listeners = function (name) { return [] } + return H +} -process.binding = function (name) { - throw new Error('process.binding is not supported'); -}; +module.exports = Sha256 -process.cwd = function () { return '/' }; -process.chdir = function (dir) { - throw new Error('process.chdir is not supported'); -}; -process.umask = function() { return 0; }; +},{"./hash":392,"inherits":200,"safe-buffer":390}],398:[function(require,module,exports){ +var inherits = require('inherits') +var SHA512 = require('./sha512') +var Hash = require('./hash') +var Buffer = require('safe-buffer').Buffer -},{}],392:[function(require,module,exports){ -exports.publicEncrypt = require('./publicEncrypt') -exports.privateDecrypt = require('./privateDecrypt') +var W = new Array(160) -exports.privateEncrypt = function privateEncrypt (key, buf) { - return exports.publicEncrypt(key, buf, true) +function Sha384 () { + this.init() + this._w = W + + Hash.call(this, 128, 112) } -exports.publicDecrypt = function publicDecrypt (key, buf) { - return exports.privateDecrypt(key, buf, true) +inherits(Sha384, SHA512) + +Sha384.prototype.init = function () { + this._ah = 0xcbbb9d5d + this._bh = 0x629a292a + this._ch = 0x9159015a + this._dh = 0x152fecd8 + this._eh = 0x67332667 + this._fh = 0x8eb44a87 + this._gh = 0xdb0c2e0d + this._hh = 0x47b5481d + + this._al = 0xc1059ed8 + this._bl = 0x367cd507 + this._cl = 0x3070dd17 + this._dl = 0xf70e5939 + this._el = 0xffc00b31 + this._fl = 0x68581511 + this._gl = 0x64f98fa7 + this._hl = 0xbefa4fa4 + + return this } -},{"./privateDecrypt":395,"./publicEncrypt":396}],393:[function(require,module,exports){ -var createHash = require('create-hash') -var Buffer = require('safe-buffer').Buffer +Sha384.prototype._hash = function () { + var H = Buffer.allocUnsafe(48) -module.exports = function (seed, len) { - var t = Buffer.alloc(0) - var i = 0 - var c - while (t.length < len) { - c = i2ops(i++) - t = Buffer.concat([t, createHash('sha1').update(seed).update(c).digest()]) + function writeInt64BE (h, l, offset) { + H.writeInt32BE(h, offset) + H.writeInt32BE(l, offset + 4) } - return t.slice(0, len) -} -function i2ops (c) { - var out = Buffer.allocUnsafe(4) - out.writeUInt32BE(c, 0) - return out + writeInt64BE(this._ah, this._al, 0) + writeInt64BE(this._bh, this._bl, 8) + writeInt64BE(this._ch, this._cl, 16) + writeInt64BE(this._dh, this._dl, 24) + writeInt64BE(this._eh, this._el, 32) + writeInt64BE(this._fh, this._fl, 40) + + return H } -},{"create-hash":164,"safe-buffer":404}],394:[function(require,module,exports){ -arguments[4][47][0].apply(exports,arguments) -},{"buffer":93,"dup":47}],395:[function(require,module,exports){ -var parseKeys = require('parse-asn1') -var mgf = require('./mgf') -var xor = require('./xor') -var BN = require('bn.js') -var crt = require('browserify-rsa') -var createHash = require('create-hash') -var withPublic = require('./withPublic') +module.exports = Sha384 + +},{"./hash":392,"./sha512":399,"inherits":200,"safe-buffer":390}],399:[function(require,module,exports){ +var inherits = require('inherits') +var Hash = require('./hash') var Buffer = require('safe-buffer').Buffer -module.exports = function privateDecrypt (privateKey, enc, reverse) { - var padding - if (privateKey.padding) { - padding = privateKey.padding - } else if (reverse) { - padding = 1 - } else { - padding = 4 - } +var K = [ + 0x428a2f98, 0xd728ae22, 0x71374491, 0x23ef65cd, + 0xb5c0fbcf, 0xec4d3b2f, 0xe9b5dba5, 0x8189dbbc, + 0x3956c25b, 0xf348b538, 0x59f111f1, 0xb605d019, + 0x923f82a4, 0xaf194f9b, 0xab1c5ed5, 0xda6d8118, + 0xd807aa98, 0xa3030242, 0x12835b01, 0x45706fbe, + 0x243185be, 0x4ee4b28c, 0x550c7dc3, 0xd5ffb4e2, + 0x72be5d74, 0xf27b896f, 0x80deb1fe, 0x3b1696b1, + 0x9bdc06a7, 0x25c71235, 0xc19bf174, 0xcf692694, + 0xe49b69c1, 0x9ef14ad2, 0xefbe4786, 0x384f25e3, + 0x0fc19dc6, 0x8b8cd5b5, 0x240ca1cc, 0x77ac9c65, + 0x2de92c6f, 0x592b0275, 0x4a7484aa, 0x6ea6e483, + 0x5cb0a9dc, 0xbd41fbd4, 0x76f988da, 0x831153b5, + 0x983e5152, 0xee66dfab, 0xa831c66d, 0x2db43210, + 0xb00327c8, 0x98fb213f, 0xbf597fc7, 0xbeef0ee4, + 0xc6e00bf3, 0x3da88fc2, 0xd5a79147, 0x930aa725, + 0x06ca6351, 0xe003826f, 0x14292967, 0x0a0e6e70, + 0x27b70a85, 0x46d22ffc, 0x2e1b2138, 0x5c26c926, + 0x4d2c6dfc, 0x5ac42aed, 0x53380d13, 0x9d95b3df, + 0x650a7354, 0x8baf63de, 0x766a0abb, 0x3c77b2a8, + 0x81c2c92e, 0x47edaee6, 0x92722c85, 0x1482353b, + 0xa2bfe8a1, 0x4cf10364, 0xa81a664b, 0xbc423001, + 0xc24b8b70, 0xd0f89791, 0xc76c51a3, 0x0654be30, + 0xd192e819, 0xd6ef5218, 0xd6990624, 0x5565a910, + 0xf40e3585, 0x5771202a, 0x106aa070, 0x32bbd1b8, + 0x19a4c116, 0xb8d2d0c8, 0x1e376c08, 0x5141ab53, + 0x2748774c, 0xdf8eeb99, 0x34b0bcb5, 0xe19b48a8, + 0x391c0cb3, 0xc5c95a63, 0x4ed8aa4a, 0xe3418acb, + 0x5b9cca4f, 0x7763e373, 0x682e6ff3, 0xd6b2b8a3, + 0x748f82ee, 0x5defb2fc, 0x78a5636f, 0x43172f60, + 0x84c87814, 0xa1f0ab72, 0x8cc70208, 0x1a6439ec, + 0x90befffa, 0x23631e28, 0xa4506ceb, 0xde82bde9, + 0xbef9a3f7, 0xb2c67915, 0xc67178f2, 0xe372532b, + 0xca273ece, 0xea26619c, 0xd186b8c7, 0x21c0c207, + 0xeada7dd6, 0xcde0eb1e, 0xf57d4f7f, 0xee6ed178, + 0x06f067aa, 0x72176fba, 0x0a637dc5, 0xa2c898a6, + 0x113f9804, 0xbef90dae, 0x1b710b35, 0x131c471b, + 0x28db77f5, 0x23047d84, 0x32caab7b, 0x40c72493, + 0x3c9ebe0a, 0x15c9bebc, 0x431d67c4, 0x9c100d4c, + 0x4cc5d4be, 0xcb3e42b6, 0x597f299c, 0xfc657e2a, + 0x5fcb6fab, 0x3ad6faec, 0x6c44198c, 0x4a475817 +] - var key = parseKeys(privateKey) - var k = key.modulus.byteLength() - if (enc.length > k || new BN(enc).cmp(key.modulus) >= 0) { - throw new Error('decryption error') - } - var msg - if (reverse) { - msg = withPublic(new BN(enc), key) - } else { - msg = crt(enc, key) - } - var zBuffer = Buffer.alloc(k - msg.length) - msg = Buffer.concat([zBuffer, msg], k) - if (padding === 4) { - return oaep(key, msg) - } else if (padding === 1) { - return pkcs1(key, msg, reverse) - } else if (padding === 3) { - return msg - } else { - throw new Error('unknown padding') - } -} +var W = new Array(160) -function oaep (key, msg) { - var k = key.modulus.byteLength() - var iHash = createHash('sha1').update(Buffer.alloc(0)).digest() - var hLen = iHash.length - if (msg[0] !== 0) { - throw new Error('decryption error') - } - var maskedSeed = msg.slice(1, hLen + 1) - var maskedDb = msg.slice(hLen + 1) - var seed = xor(maskedSeed, mgf(maskedDb, hLen)) - var db = xor(maskedDb, mgf(seed, k - hLen - 1)) - if (compare(iHash, db.slice(0, hLen))) { - throw new Error('decryption error') - } - var i = hLen - while (db[i] === 0) { - i++ - } - if (db[i++] !== 1) { - throw new Error('decryption error') - } - return db.slice(i) +function Sha512 () { + this.init() + this._w = W + + Hash.call(this, 128, 112) } -function pkcs1 (key, msg, reverse) { - var p1 = msg.slice(0, 2) - var i = 2 - var status = 0 - while (msg[i++] !== 0) { - if (i >= msg.length) { - status++ - break - } - } - var ps = msg.slice(2, i - 1) +inherits(Sha512, Hash) - if ((p1.toString('hex') !== '0002' && !reverse) || (p1.toString('hex') !== '0001' && reverse)) { - status++ - } - if (ps.length < 8) { - status++ - } - if (status) { - throw new Error('decryption error') - } - return msg.slice(i) -} -function compare (a, b) { - a = Buffer.from(a) - b = Buffer.from(b) - var dif = 0 - var len = a.length - if (a.length !== b.length) { - dif++ - len = Math.min(a.length, b.length) - } - var i = -1 - while (++i < len) { - dif += (a[i] ^ b[i]) - } - return dif -} +Sha512.prototype.init = function () { + this._ah = 0x6a09e667 + this._bh = 0xbb67ae85 + this._ch = 0x3c6ef372 + this._dh = 0xa54ff53a + this._eh = 0x510e527f + this._fh = 0x9b05688c + this._gh = 0x1f83d9ab + this._hh = 0x5be0cd19 -},{"./mgf":393,"./withPublic":397,"./xor":398,"bn.js":394,"browserify-rsa":114,"create-hash":164,"parse-asn1":383,"safe-buffer":404}],396:[function(require,module,exports){ -var parseKeys = require('parse-asn1') -var randomBytes = require('randombytes') -var createHash = require('create-hash') -var mgf = require('./mgf') -var xor = require('./xor') -var BN = require('bn.js') -var withPublic = require('./withPublic') -var crt = require('browserify-rsa') -var Buffer = require('safe-buffer').Buffer + this._al = 0xf3bcc908 + this._bl = 0x84caa73b + this._cl = 0xfe94f82b + this._dl = 0x5f1d36f1 + this._el = 0xade682d1 + this._fl = 0x2b3e6c1f + this._gl = 0xfb41bd6b + this._hl = 0x137e2179 -module.exports = function publicEncrypt (publicKey, msg, reverse) { - var padding - if (publicKey.padding) { - padding = publicKey.padding - } else if (reverse) { - padding = 1 - } else { - padding = 4 - } - var key = parseKeys(publicKey) - var paddedMsg - if (padding === 4) { - paddedMsg = oaep(key, msg) - } else if (padding === 1) { - paddedMsg = pkcs1(key, msg, reverse) - } else if (padding === 3) { - paddedMsg = new BN(msg) - if (paddedMsg.cmp(key.modulus) >= 0) { - throw new Error('data too long for modulus') - } - } else { - throw new Error('unknown padding') - } - if (reverse) { - return crt(paddedMsg, key) - } else { - return withPublic(paddedMsg, key) - } + return this } -function oaep (key, msg) { - var k = key.modulus.byteLength() - var mLen = msg.length - var iHash = createHash('sha1').update(Buffer.alloc(0)).digest() - var hLen = iHash.length - var hLen2 = 2 * hLen - if (mLen > k - hLen2 - 2) { - throw new Error('message too long') - } - var ps = Buffer.alloc(k - mLen - hLen2 - 2) - var dblen = k - hLen - 1 - var seed = randomBytes(hLen) - var maskedDb = xor(Buffer.concat([iHash, ps, Buffer.alloc(1, 1), msg], dblen), mgf(seed, dblen)) - var maskedSeed = xor(seed, mgf(maskedDb, hLen)) - return new BN(Buffer.concat([Buffer.alloc(1), maskedSeed, maskedDb], k)) -} -function pkcs1 (key, msg, reverse) { - var mLen = msg.length - var k = key.modulus.byteLength() - if (mLen > k - 11) { - throw new Error('message too long') - } - var ps - if (reverse) { - ps = Buffer.alloc(k - mLen - 3, 0xff) - } else { - ps = nonZero(k - mLen - 3) - } - return new BN(Buffer.concat([Buffer.from([0, reverse ? 1 : 2]), ps, Buffer.alloc(1), msg], k)) +function Ch (x, y, z) { + return z ^ (x & (y ^ z)) } -function nonZero (len) { - var out = Buffer.allocUnsafe(len) - var i = 0 - var cache = randomBytes(len * 2) - var cur = 0 - var num - while (i < len) { - if (cur === cache.length) { - cache = randomBytes(len * 2) - cur = 0 - } - num = cache[cur++] - if (num) { - out[i++] = num - } - } - return out + +function maj (x, y, z) { + return (x & y) | (z & (x | y)) } -},{"./mgf":393,"./withPublic":397,"./xor":398,"bn.js":394,"browserify-rsa":114,"create-hash":164,"parse-asn1":383,"randombytes":400,"safe-buffer":404}],397:[function(require,module,exports){ -var BN = require('bn.js') -var Buffer = require('safe-buffer').Buffer +function sigma0 (x, xl) { + return (x >>> 28 | xl << 4) ^ (xl >>> 2 | x << 30) ^ (xl >>> 7 | x << 25) +} -function withPublic (paddedMsg, key) { - return Buffer.from(paddedMsg - .toRed(BN.mont(key.modulus)) - .redPow(new BN(key.publicExponent)) - .fromRed() - .toArray()) +function sigma1 (x, xl) { + return (x >>> 14 | xl << 18) ^ (x >>> 18 | xl << 14) ^ (xl >>> 9 | x << 23) } -module.exports = withPublic +function Gamma0 (x, xl) { + return (x >>> 1 | xl << 31) ^ (x >>> 8 | xl << 24) ^ (x >>> 7) +} -},{"bn.js":394,"safe-buffer":404}],398:[function(require,module,exports){ -module.exports = function xor (a, b) { - var len = a.length - var i = -1 - while (++i < len) { - a[i] ^= b[i] - } - return a +function Gamma0l (x, xl) { + return (x >>> 1 | xl << 31) ^ (x >>> 8 | xl << 24) ^ (x >>> 7 | xl << 25) } -},{}],399:[function(require,module,exports){ -(function (global){(function (){ -/*! queue-microtask. MIT License. Feross Aboukhadijeh */ -let promise +function Gamma1 (x, xl) { + return (x >>> 19 | xl << 13) ^ (xl >>> 29 | x << 3) ^ (x >>> 6) +} -module.exports = typeof queueMicrotask === 'function' - ? queueMicrotask.bind(typeof window !== 'undefined' ? window : global) - // reuse resolved promise, and allocate it lazily - : cb => (promise || (promise = Promise.resolve())) - .then(cb) - .catch(err => setTimeout(() => { throw err }, 0)) +function Gamma1l (x, xl) { + return (x >>> 19 | xl << 13) ^ (xl >>> 29 | x << 3) ^ (x >>> 6 | xl << 26) +} -}).call(this)}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{}],400:[function(require,module,exports){ -(function (process,global){(function (){ -'use strict' +function getCarry (a, b) { + return (a >>> 0) < (b >>> 0) ? 1 : 0 +} -// limit of Crypto.getRandomValues() -// https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues -var MAX_BYTES = 65536 +Sha512.prototype._update = function (M) { + var W = this._w -// Node supports requesting up to this number of bytes -// https://github.com/nodejs/node/blob/master/lib/internal/crypto/random.js#L48 -var MAX_UINT32 = 4294967295 + var ah = this._ah | 0 + var bh = this._bh | 0 + var ch = this._ch | 0 + var dh = this._dh | 0 + var eh = this._eh | 0 + var fh = this._fh | 0 + var gh = this._gh | 0 + var hh = this._hh | 0 -function oldBrowser () { - throw new Error('Secure random number generation is not supported by this browser.\nUse Chrome, Firefox or Internet Explorer 11') -} + var al = this._al | 0 + var bl = this._bl | 0 + var cl = this._cl | 0 + var dl = this._dl | 0 + var el = this._el | 0 + var fl = this._fl | 0 + var gl = this._gl | 0 + var hl = this._hl | 0 -var Buffer = require('safe-buffer').Buffer -var crypto = global.crypto || global.msCrypto + for (var i = 0; i < 32; i += 2) { + W[i] = M.readInt32BE(i * 4) + W[i + 1] = M.readInt32BE(i * 4 + 4) + } + for (; i < 160; i += 2) { + var xh = W[i - 15 * 2] + var xl = W[i - 15 * 2 + 1] + var gamma0 = Gamma0(xh, xl) + var gamma0l = Gamma0l(xl, xh) -if (crypto && crypto.getRandomValues) { - module.exports = randomBytes -} else { - module.exports = oldBrowser -} + xh = W[i - 2 * 2] + xl = W[i - 2 * 2 + 1] + var gamma1 = Gamma1(xh, xl) + var gamma1l = Gamma1l(xl, xh) -function randomBytes (size, cb) { - // phantomjs needs to throw - if (size > MAX_UINT32) throw new RangeError('requested too many random bytes') + // W[i] = gamma0 + W[i - 7] + gamma1 + W[i - 16] + var Wi7h = W[i - 7 * 2] + var Wi7l = W[i - 7 * 2 + 1] - var bytes = Buffer.allocUnsafe(size) + var Wi16h = W[i - 16 * 2] + var Wi16l = W[i - 16 * 2 + 1] - if (size > 0) { // getRandomValues fails on IE if size == 0 - if (size > MAX_BYTES) { // this is the max bytes crypto.getRandomValues - // can do at once see https://developer.mozilla.org/en-US/docs/Web/API/window.crypto.getRandomValues - for (var generated = 0; generated < size; generated += MAX_BYTES) { - // buffer.slice automatically checks if the end is past the end of - // the buffer so we don't have to here - crypto.getRandomValues(bytes.slice(generated, generated + MAX_BYTES)) - } - } else { - crypto.getRandomValues(bytes) - } - } + var Wil = (gamma0l + Wi7l) | 0 + var Wih = (gamma0 + Wi7h + getCarry(Wil, gamma0l)) | 0 + Wil = (Wil + gamma1l) | 0 + Wih = (Wih + gamma1 + getCarry(Wil, gamma1l)) | 0 + Wil = (Wil + Wi16l) | 0 + Wih = (Wih + Wi16h + getCarry(Wil, Wi16l)) | 0 - if (typeof cb === 'function') { - return process.nextTick(function () { - cb(null, bytes) - }) + W[i] = Wih + W[i + 1] = Wil } - return bytes -} - -}).call(this)}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"_process":391,"safe-buffer":404}],401:[function(require,module,exports){ -(function (process,global){(function (){ -'use strict' + for (var j = 0; j < 160; j += 2) { + Wih = W[j] + Wil = W[j + 1] -function oldBrowser () { - throw new Error('secure random number generation not supported by this browser\nuse chrome, FireFox or Internet Explorer 11') -} -var safeBuffer = require('safe-buffer') -var randombytes = require('randombytes') -var Buffer = safeBuffer.Buffer -var kBufferMaxLength = safeBuffer.kMaxLength -var crypto = global.crypto || global.msCrypto -var kMaxUint32 = Math.pow(2, 32) - 1 -function assertOffset (offset, length) { - if (typeof offset !== 'number' || offset !== offset) { // eslint-disable-line no-self-compare - throw new TypeError('offset must be a number') - } + var majh = maj(ah, bh, ch) + var majl = maj(al, bl, cl) - if (offset > kMaxUint32 || offset < 0) { - throw new TypeError('offset must be a uint32') - } + var sigma0h = sigma0(ah, al) + var sigma0l = sigma0(al, ah) + var sigma1h = sigma1(eh, el) + var sigma1l = sigma1(el, eh) - if (offset > kBufferMaxLength || offset > length) { - throw new RangeError('offset out of range') - } -} + // t1 = h + sigma1 + ch + K[j] + W[j] + var Kih = K[j] + var Kil = K[j + 1] -function assertSize (size, offset, length) { - if (typeof size !== 'number' || size !== size) { // eslint-disable-line no-self-compare - throw new TypeError('size must be a number') - } + var chh = Ch(eh, fh, gh) + var chl = Ch(el, fl, gl) - if (size > kMaxUint32 || size < 0) { - throw new TypeError('size must be a uint32') - } + var t1l = (hl + sigma1l) | 0 + var t1h = (hh + sigma1h + getCarry(t1l, hl)) | 0 + t1l = (t1l + chl) | 0 + t1h = (t1h + chh + getCarry(t1l, chl)) | 0 + t1l = (t1l + Kil) | 0 + t1h = (t1h + Kih + getCarry(t1l, Kil)) | 0 + t1l = (t1l + Wil) | 0 + t1h = (t1h + Wih + getCarry(t1l, Wil)) | 0 - if (size + offset > length || size > kBufferMaxLength) { - throw new RangeError('buffer too small') - } -} -if ((crypto && crypto.getRandomValues) || !process.browser) { - exports.randomFill = randomFill - exports.randomFillSync = randomFillSync -} else { - exports.randomFill = oldBrowser - exports.randomFillSync = oldBrowser -} -function randomFill (buf, offset, size, cb) { - if (!Buffer.isBuffer(buf) && !(buf instanceof global.Uint8Array)) { - throw new TypeError('"buf" argument must be a Buffer or Uint8Array') - } + // t2 = sigma0 + maj + var t2l = (sigma0l + majl) | 0 + var t2h = (sigma0h + majh + getCarry(t2l, sigma0l)) | 0 - if (typeof offset === 'function') { - cb = offset - offset = 0 - size = buf.length - } else if (typeof size === 'function') { - cb = size - size = buf.length - offset - } else if (typeof cb !== 'function') { - throw new TypeError('"cb" argument must be a function') + hh = gh + hl = gl + gh = fh + gl = fl + fh = eh + fl = el + el = (dl + t1l) | 0 + eh = (dh + t1h + getCarry(el, dl)) | 0 + dh = ch + dl = cl + ch = bh + cl = bl + bh = ah + bl = al + al = (t1l + t2l) | 0 + ah = (t1h + t2h + getCarry(al, t1l)) | 0 } - assertOffset(offset, buf.length) - assertSize(size, offset, buf.length) - return actualFill(buf, offset, size, cb) -} -function actualFill (buf, offset, size, cb) { - if (process.browser) { - var ourBuf = buf.buffer - var uint = new Uint8Array(ourBuf, offset, size) - crypto.getRandomValues(uint) - if (cb) { - process.nextTick(function () { - cb(null, buf) - }) - return - } - return buf - } - if (cb) { - randombytes(size, function (err, bytes) { - if (err) { - return cb(err) - } - bytes.copy(buf, offset) - cb(null, buf) - }) - return - } - var bytes = randombytes(size) - bytes.copy(buf, offset) - return buf + this._al = (this._al + al) | 0 + this._bl = (this._bl + bl) | 0 + this._cl = (this._cl + cl) | 0 + this._dl = (this._dl + dl) | 0 + this._el = (this._el + el) | 0 + this._fl = (this._fl + fl) | 0 + this._gl = (this._gl + gl) | 0 + this._hl = (this._hl + hl) | 0 + + this._ah = (this._ah + ah + getCarry(this._al, al)) | 0 + this._bh = (this._bh + bh + getCarry(this._bl, bl)) | 0 + this._ch = (this._ch + ch + getCarry(this._cl, cl)) | 0 + this._dh = (this._dh + dh + getCarry(this._dl, dl)) | 0 + this._eh = (this._eh + eh + getCarry(this._el, el)) | 0 + this._fh = (this._fh + fh + getCarry(this._fl, fl)) | 0 + this._gh = (this._gh + gh + getCarry(this._gl, gl)) | 0 + this._hh = (this._hh + hh + getCarry(this._hl, hl)) | 0 } -function randomFillSync (buf, offset, size) { - if (typeof offset === 'undefined') { - offset = 0 - } - if (!Buffer.isBuffer(buf) && !(buf instanceof global.Uint8Array)) { - throw new TypeError('"buf" argument must be a Buffer or Uint8Array') - } - assertOffset(offset, buf.length) +Sha512.prototype._hash = function () { + var H = Buffer.allocUnsafe(64) - if (size === undefined) size = buf.length - offset + function writeInt64BE (h, l, offset) { + H.writeInt32BE(h, offset) + H.writeInt32BE(l, offset + 4) + } - assertSize(size, offset, buf.length) + writeInt64BE(this._ah, this._al, 0) + writeInt64BE(this._bh, this._bl, 8) + writeInt64BE(this._ch, this._cl, 16) + writeInt64BE(this._dh, this._dl, 24) + writeInt64BE(this._eh, this._el, 32) + writeInt64BE(this._fh, this._fl, 40) + writeInt64BE(this._gh, this._gl, 48) + writeInt64BE(this._hh, this._hl, 56) - return actualFill(buf, offset, size) + return H } -}).call(this)}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"_process":391,"randombytes":400,"safe-buffer":404}],402:[function(require,module,exports){ -'use strict' -var Buffer = require('buffer').Buffer -var inherits = require('inherits') -var HashBase = require('hash-base') +module.exports = Sha512 -var ARRAY16 = new Array(16) +},{"./hash":392,"inherits":200,"safe-buffer":390}],400:[function(require,module,exports){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. -var zl = [ - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8, - 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12, - 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2, - 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13 -] +module.exports = Stream; -var zr = [ - 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, - 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2, - 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13, - 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14, - 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11 -] +var EE = require('events').EventEmitter; +var inherits = require('inherits'); -var sl = [ - 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8, - 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12, - 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5, - 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12, - 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6 -] +inherits(Stream, EE); +Stream.Readable = require('readable-stream/lib/_stream_readable.js'); +Stream.Writable = require('readable-stream/lib/_stream_writable.js'); +Stream.Duplex = require('readable-stream/lib/_stream_duplex.js'); +Stream.Transform = require('readable-stream/lib/_stream_transform.js'); +Stream.PassThrough = require('readable-stream/lib/_stream_passthrough.js'); +Stream.finished = require('readable-stream/lib/internal/streams/end-of-stream.js') +Stream.pipeline = require('readable-stream/lib/internal/streams/pipeline.js') -var sr = [ - 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6, - 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11, - 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5, - 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8, - 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11 -] +// Backwards-compat with node 0.4.x +Stream.Stream = Stream; -var hl = [0x00000000, 0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xa953fd4e] -var hr = [0x50a28be6, 0x5c4dd124, 0x6d703ef3, 0x7a6d76e9, 0x00000000] -function RIPEMD160 () { - HashBase.call(this, 64) - // state - this._a = 0x67452301 - this._b = 0xefcdab89 - this._c = 0x98badcfe - this._d = 0x10325476 - this._e = 0xc3d2e1f0 -} +// old-style streams. Note that the pipe method (the only relevant +// part of this class) is overridden in the Readable class. -inherits(RIPEMD160, HashBase) +function Stream() { + EE.call(this); +} -RIPEMD160.prototype._update = function () { - var words = ARRAY16 - for (var j = 0; j < 16; ++j) words[j] = this._block.readInt32LE(j * 4) +Stream.prototype.pipe = function(dest, options) { + var source = this; - var al = this._a | 0 - var bl = this._b | 0 - var cl = this._c | 0 - var dl = this._d | 0 - var el = this._e | 0 + function ondata(chunk) { + if (dest.writable) { + if (false === dest.write(chunk) && source.pause) { + source.pause(); + } + } + } - var ar = this._a | 0 - var br = this._b | 0 - var cr = this._c | 0 - var dr = this._d | 0 - var er = this._e | 0 + source.on('data', ondata); - // computation - for (var i = 0; i < 80; i += 1) { - var tl - var tr - if (i < 16) { - tl = fn1(al, bl, cl, dl, el, words[zl[i]], hl[0], sl[i]) - tr = fn5(ar, br, cr, dr, er, words[zr[i]], hr[0], sr[i]) - } else if (i < 32) { - tl = fn2(al, bl, cl, dl, el, words[zl[i]], hl[1], sl[i]) - tr = fn4(ar, br, cr, dr, er, words[zr[i]], hr[1], sr[i]) - } else if (i < 48) { - tl = fn3(al, bl, cl, dl, el, words[zl[i]], hl[2], sl[i]) - tr = fn3(ar, br, cr, dr, er, words[zr[i]], hr[2], sr[i]) - } else if (i < 64) { - tl = fn4(al, bl, cl, dl, el, words[zl[i]], hl[3], sl[i]) - tr = fn2(ar, br, cr, dr, er, words[zr[i]], hr[3], sr[i]) - } else { // if (i<80) { - tl = fn5(al, bl, cl, dl, el, words[zl[i]], hl[4], sl[i]) - tr = fn1(ar, br, cr, dr, er, words[zr[i]], hr[4], sr[i]) + function ondrain() { + if (source.readable && source.resume) { + source.resume(); } + } - al = el - el = dl - dl = rotl(cl, 10) - cl = bl - bl = tl + dest.on('drain', ondrain); - ar = er - er = dr - dr = rotl(cr, 10) - cr = br - br = tr + // If the 'end' option is not supplied, dest.end() will be called when + // source gets the 'end' or 'close' events. Only dest.end() once. + if (!dest._isStdio && (!options || options.end !== false)) { + source.on('end', onend); + source.on('close', onclose); } - // update state - var t = (this._b + cl + dr) | 0 - this._b = (this._c + dl + er) | 0 - this._c = (this._d + el + ar) | 0 - this._d = (this._e + al + br) | 0 - this._e = (this._a + bl + cr) | 0 - this._a = t -} + var didOnEnd = false; + function onend() { + if (didOnEnd) return; + didOnEnd = true; -RIPEMD160.prototype._digest = function () { - // create padding and handle blocks - this._block[this._blockOffset++] = 0x80 - if (this._blockOffset > 56) { - this._block.fill(0, this._blockOffset, 64) - this._update() - this._blockOffset = 0 + dest.end(); } - this._block.fill(0, this._blockOffset, 56) - this._block.writeUInt32LE(this._length[0], 56) - this._block.writeUInt32LE(this._length[1], 60) - this._update() - // produce result - var buffer = Buffer.alloc ? Buffer.alloc(20) : new Buffer(20) - buffer.writeInt32LE(this._a, 0) - buffer.writeInt32LE(this._b, 4) - buffer.writeInt32LE(this._c, 8) - buffer.writeInt32LE(this._d, 12) - buffer.writeInt32LE(this._e, 16) - return buffer -} + function onclose() { + if (didOnEnd) return; + didOnEnd = true; -function rotl (x, n) { - return (x << n) | (x >>> (32 - n)) -} + if (typeof dest.destroy === 'function') dest.destroy(); + } -function fn1 (a, b, c, d, e, m, k, s) { - return (rotl((a + (b ^ c ^ d) + m + k) | 0, s) + e) | 0 -} + // don't leave dangling pipes when there are errors. + function onerror(er) { + cleanup(); + if (EE.listenerCount(this, 'error') === 0) { + throw er; // Unhandled stream error in pipe. + } + } -function fn2 (a, b, c, d, e, m, k, s) { - return (rotl((a + ((b & c) | ((~b) & d)) + m + k) | 0, s) + e) | 0 -} + source.on('error', onerror); + dest.on('error', onerror); -function fn3 (a, b, c, d, e, m, k, s) { - return (rotl((a + ((b | (~c)) ^ d) + m + k) | 0, s) + e) | 0 -} + // remove all the event listeners that were added. + function cleanup() { + source.removeListener('data', ondata); + dest.removeListener('drain', ondrain); -function fn4 (a, b, c, d, e, m, k, s) { - return (rotl((a + ((b & d) | (c & (~d))) + m + k) | 0, s) + e) | 0 -} + source.removeListener('end', onend); + source.removeListener('close', onclose); -function fn5 (a, b, c, d, e, m, k, s) { - return (rotl((a + (b ^ (c | (~d))) + m + k) | 0, s) + e) | 0 -} + source.removeListener('error', onerror); + dest.removeListener('error', onerror); -module.exports = RIPEMD160 + source.removeListener('end', cleanup); + source.removeListener('close', cleanup); -},{"buffer":137,"hash-base":224,"inherits":256}],403:[function(require,module,exports){ -/*! run-parallel-limit. MIT License. Feross Aboukhadijeh */ -module.exports = runParallelLimit + dest.removeListener('close', cleanup); + } -const queueMicrotask = require('queue-microtask') + source.on('end', cleanup); + source.on('close', cleanup); -function runParallelLimit (tasks, limit, cb) { - if (typeof limit !== 'number') throw new Error('second argument must be a Number') - let results, len, pending, keys, isErrored - let isSync = true - let next + dest.on('close', cleanup); - if (Array.isArray(tasks)) { - results = [] - pending = len = tasks.length - } else { - keys = Object.keys(tasks) - results = {} - pending = len = keys.length - } + dest.emit('pipe', source); - function done (err) { - function end () { - if (cb) cb(err, results) - cb = null - } - if (isSync) queueMicrotask(end) - else end() + // Allow for unix-like usage: A.pipe(B).pipe(C) + return dest; +}; + +},{"events":172,"inherits":200,"readable-stream/lib/_stream_duplex.js":402,"readable-stream/lib/_stream_passthrough.js":403,"readable-stream/lib/_stream_readable.js":404,"readable-stream/lib/_stream_transform.js":405,"readable-stream/lib/_stream_writable.js":406,"readable-stream/lib/internal/streams/end-of-stream.js":410,"readable-stream/lib/internal/streams/pipeline.js":412}],401:[function(require,module,exports){ +arguments[4][210][0].apply(exports,arguments) +},{"dup":210}],402:[function(require,module,exports){ +arguments[4][211][0].apply(exports,arguments) +},{"./_stream_readable":404,"./_stream_writable":406,"_process":350,"dup":211,"inherits":200}],403:[function(require,module,exports){ +arguments[4][212][0].apply(exports,arguments) +},{"./_stream_transform":405,"dup":212,"inherits":200}],404:[function(require,module,exports){ +arguments[4][213][0].apply(exports,arguments) +},{"../errors":401,"./_stream_duplex":402,"./internal/streams/async_iterator":407,"./internal/streams/buffer_list":408,"./internal/streams/destroy":409,"./internal/streams/from":411,"./internal/streams/state":413,"./internal/streams/stream":414,"_process":350,"buffer":118,"dup":213,"events":172,"inherits":200,"string_decoder/":415,"util":88}],405:[function(require,module,exports){ +arguments[4][214][0].apply(exports,arguments) +},{"../errors":401,"./_stream_duplex":402,"dup":214,"inherits":200}],406:[function(require,module,exports){ +arguments[4][215][0].apply(exports,arguments) +},{"../errors":401,"./_stream_duplex":402,"./internal/streams/destroy":409,"./internal/streams/state":413,"./internal/streams/stream":414,"_process":350,"buffer":118,"dup":215,"inherits":200,"util-deprecate":417}],407:[function(require,module,exports){ +arguments[4][216][0].apply(exports,arguments) +},{"./end-of-stream":410,"_process":350,"dup":216}],408:[function(require,module,exports){ +arguments[4][217][0].apply(exports,arguments) +},{"buffer":118,"dup":217,"util":88}],409:[function(require,module,exports){ +arguments[4][218][0].apply(exports,arguments) +},{"_process":350,"dup":218}],410:[function(require,module,exports){ +arguments[4][219][0].apply(exports,arguments) +},{"../../../errors":401,"dup":219}],411:[function(require,module,exports){ +arguments[4][220][0].apply(exports,arguments) +},{"dup":220}],412:[function(require,module,exports){ +arguments[4][221][0].apply(exports,arguments) +},{"../../../errors":401,"./end-of-stream":410,"dup":221}],413:[function(require,module,exports){ +arguments[4][222][0].apply(exports,arguments) +},{"../../../errors":401,"dup":222}],414:[function(require,module,exports){ +arguments[4][223][0].apply(exports,arguments) +},{"dup":223,"events":172}],415:[function(require,module,exports){ +arguments[4][370][0].apply(exports,arguments) +},{"dup":370,"safe-buffer":390}],416:[function(require,module,exports){ +(function (setImmediate,clearImmediate){(function (){ +var nextTick = require('process/browser.js').nextTick; +var apply = Function.prototype.apply; +var slice = Array.prototype.slice; +var immediateIds = {}; +var nextImmediateId = 0; + +// DOM APIs, for completeness + +exports.setTimeout = function() { + return new Timeout(apply.call(setTimeout, window, arguments), clearTimeout); +}; +exports.setInterval = function() { + return new Timeout(apply.call(setInterval, window, arguments), clearInterval); +}; +exports.clearTimeout = +exports.clearInterval = function(timeout) { timeout.close(); }; + +function Timeout(id, clearFn) { + this._id = id; + this._clearFn = clearFn; +} +Timeout.prototype.unref = Timeout.prototype.ref = function() {}; +Timeout.prototype.close = function() { + this._clearFn.call(window, this._id); +}; + +// Does not start the time, just sets up the members needed. +exports.enroll = function(item, msecs) { + clearTimeout(item._idleTimeoutId); + item._idleTimeout = msecs; +}; + +exports.unenroll = function(item) { + clearTimeout(item._idleTimeoutId); + item._idleTimeout = -1; +}; + +exports._unrefActive = exports.active = function(item) { + clearTimeout(item._idleTimeoutId); + + var msecs = item._idleTimeout; + if (msecs >= 0) { + item._idleTimeoutId = setTimeout(function onTimeout() { + if (item._onTimeout) + item._onTimeout(); + }, msecs); } +}; - function each (i, err, result) { - results[i] = result - if (err) isErrored = true - if (--pending === 0 || err) { - done(err) - } else if (!isErrored && next < len) { - let key - if (keys) { - key = keys[next] - next += 1 - tasks[key](function (err, result) { each(key, err, result) }) +// That's not how node.js implements it but the exposed api is the same. +exports.setImmediate = typeof setImmediate === "function" ? setImmediate : function(fn) { + var id = nextImmediateId++; + var args = arguments.length < 2 ? false : slice.call(arguments, 1); + + immediateIds[id] = true; + + nextTick(function onNextTick() { + if (immediateIds[id]) { + // fn.call() is faster so we optimize for the common use-case + // @see http://jsperf.com/call-apply-segu + if (args) { + fn.apply(null, args); } else { - key = next - next += 1 - tasks[key](function (err, result) { each(key, err, result) }) + fn.call(null); } + // Prevent ids from leaking + exports.clearImmediate(id); } - } - - next = limit - if (!pending) { - // empty - done(null) - } else if (keys) { - // object - keys.some(function (key, i) { - tasks[key](function (err, result) { each(key, err, result) }) - if (i === limit - 1) return true // early return - return false - }) - } else { - // array - tasks.some(function (task, i) { - task(function (err, result) { each(i, err, result) }) - if (i === limit - 1) return true // early return - return false - }) - } + }); - isSync = false -} + return id; +}; -},{"queue-microtask":399}],404:[function(require,module,exports){ -/* eslint-disable node/no-deprecated-api */ -var buffer = require('buffer') -var Buffer = buffer.Buffer +exports.clearImmediate = typeof clearImmediate === "function" ? clearImmediate : function(id) { + delete immediateIds[id]; +}; +}).call(this)}).call(this,require("timers").setImmediate,require("timers").clearImmediate) +},{"process/browser.js":350,"timers":416}],417:[function(require,module,exports){ +(function (global){(function (){ -// alternative to using Object.keys for old browsers -function copyProps (src, dst) { - for (var key in src) { - dst[key] = src[key] - } -} -if (Buffer.from && Buffer.alloc && Buffer.allocUnsafe && Buffer.allocUnsafeSlow) { - module.exports = buffer -} else { - // Copy properties from require('buffer') - copyProps(buffer, exports) - exports.Buffer = SafeBuffer -} +/** + * Module exports. + */ -function SafeBuffer (arg, encodingOrOffset, length) { - return Buffer(arg, encodingOrOffset, length) -} +module.exports = deprecate; -// Copy static methods from Buffer -copyProps(Buffer, SafeBuffer) +/** + * Mark that a method should not be used. + * Returns a modified function which warns once by default. + * + * If `localStorage.noDeprecation = true` is set, then it is a no-op. + * + * If `localStorage.throwDeprecation = true` is set, then deprecated functions + * will throw an Error when invoked. + * + * If `localStorage.traceDeprecation = true` is set, then deprecated functions + * will invoke `console.trace()` instead of `console.error()`. + * + * @param {Function} fn - the function to deprecate + * @param {String} msg - the string to print to the console when `fn` is invoked + * @returns {Function} a new "deprecated" version of `fn` + * @api public + */ -SafeBuffer.from = function (arg, encodingOrOffset, length) { - if (typeof arg === 'number') { - throw new TypeError('Argument must not be a number') +function deprecate (fn, msg) { + if (config('noDeprecation')) { + return fn; } - return Buffer(arg, encodingOrOffset, length) -} -SafeBuffer.alloc = function (size, fill, encoding) { - if (typeof size !== 'number') { - throw new TypeError('Argument must be a number') - } - var buf = Buffer(size) - if (fill !== undefined) { - if (typeof encoding === 'string') { - buf.fill(fill, encoding) - } else { - buf.fill(fill) + var warned = false; + function deprecated() { + if (!warned) { + if (config('throwDeprecation')) { + throw new Error(msg); + } else if (config('traceDeprecation')) { + console.trace(msg); + } else { + console.warn(msg); + } + warned = true; } - } else { - buf.fill(0) + return fn.apply(this, arguments); } - return buf + + return deprecated; } -SafeBuffer.allocUnsafe = function (size) { - if (typeof size !== 'number') { - throw new TypeError('Argument must be a number') +/** + * Checks `localStorage` for boolean values for the given `name`. + * + * @param {String} name + * @returns {Boolean} + * @api private + */ + +function config (name) { + // accessing global.localStorage can trigger a DOMException in sandboxed iframes + try { + if (!global.localStorage) return false; + } catch (_) { + return false; } - return Buffer(size) + var val = global.localStorage[name]; + if (null == val) return false; + return String(val).toLowerCase() === 'true'; } -SafeBuffer.allocUnsafeSlow = function (size) { - if (typeof size !== 'number') { - throw new TypeError('Argument must be a number') - } - return buffer.SlowBuffer(size) +}).call(this)}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{}],418:[function(require,module,exports){ +module.exports = function isBuffer(arg) { + return arg && typeof arg === 'object' + && typeof arg.copy === 'function' + && typeof arg.fill === 'function' + && typeof arg.readUInt8 === 'function'; } +},{}],419:[function(require,module,exports){ +// Currently in sync with Node.js lib/internal/util/types.js +// https://github.com/nodejs/node/commit/112cc7c27551254aa2b17098fb774867f05ed0d9 -},{"buffer":137}],405:[function(require,module,exports){ -(function (process){(function (){ -/* eslint-disable node/no-deprecated-api */ +'use strict'; -'use strict' +var isArgumentsObject = require('is-arguments'); +var isGeneratorFunction = require('is-generator-function'); +var whichTypedArray = require('which-typed-array'); +var isTypedArray = require('is-typed-array'); -var buffer = require('buffer') -var Buffer = buffer.Buffer +function uncurryThis(f) { + return f.call.bind(f); +} -var safer = {} +var BigIntSupported = typeof BigInt !== 'undefined'; +var SymbolSupported = typeof Symbol !== 'undefined'; -var key +var ObjectToString = uncurryThis(Object.prototype.toString); -for (key in buffer) { - if (!buffer.hasOwnProperty(key)) continue - if (key === 'SlowBuffer' || key === 'Buffer') continue - safer[key] = buffer[key] -} +var numberValue = uncurryThis(Number.prototype.valueOf); +var stringValue = uncurryThis(String.prototype.valueOf); +var booleanValue = uncurryThis(Boolean.prototype.valueOf); -var Safer = safer.Buffer = {} -for (key in Buffer) { - if (!Buffer.hasOwnProperty(key)) continue - if (key === 'allocUnsafe' || key === 'allocUnsafeSlow') continue - Safer[key] = Buffer[key] +if (BigIntSupported) { + var bigIntValue = uncurryThis(BigInt.prototype.valueOf); } -safer.Buffer.prototype = Buffer.prototype - -if (!Safer.from || Safer.from === Uint8Array.from) { - Safer.from = function (value, encodingOrOffset, length) { - if (typeof value === 'number') { - throw new TypeError('The "value" argument must not be of type number. Received type ' + typeof value) - } - if (value && typeof value.length === 'undefined') { - throw new TypeError('The first argument must be one of type string, Buffer, ArrayBuffer, Array, or Array-like Object. Received type ' + typeof value) - } - return Buffer(value, encodingOrOffset, length) - } +if (SymbolSupported) { + var symbolValue = uncurryThis(Symbol.prototype.valueOf); } -if (!Safer.alloc) { - Safer.alloc = function (size, fill, encoding) { - if (typeof size !== 'number') { - throw new TypeError('The "size" argument must be of type number. Received type ' + typeof size) - } - if (size < 0 || size >= 2 * (1 << 30)) { - throw new RangeError('The value "' + size + '" is invalid for option "size"') - } - var buf = Buffer(size) - if (!fill || fill.length === 0) { - buf.fill(0) - } else if (typeof encoding === 'string') { - buf.fill(fill, encoding) - } else { - buf.fill(fill) - } - return buf +function checkBoxedPrimitive(value, prototypeValueOf) { + if (typeof value !== 'object') { + return false; } -} - -if (!safer.kStringMaxLength) { try { - safer.kStringMaxLength = process.binding('buffer').kStringMaxLength - } catch (e) { - // we can't determine kStringMaxLength in environments where process.binding - // is unsupported, so let's not set it + prototypeValueOf(value); + return true; + } catch(e) { + return false; } } -if (!safer.constants) { - safer.constants = { - MAX_LENGTH: safer.kMaxLength - } - if (safer.kStringMaxLength) { - safer.constants.MAX_STRING_LENGTH = safer.kStringMaxLength - } +exports.isArgumentsObject = isArgumentsObject; +exports.isGeneratorFunction = isGeneratorFunction; +exports.isTypedArray = isTypedArray; + +// Taken from here and modified for better browser support +// https://github.com/sindresorhus/p-is-promise/blob/cda35a513bda03f977ad5cde3a079d237e82d7ef/index.js +function isPromise(input) { + return ( + ( + typeof Promise !== 'undefined' && + input instanceof Promise + ) || + ( + input !== null && + typeof input === 'object' && + typeof input.then === 'function' && + typeof input.catch === 'function' + ) + ); } +exports.isPromise = isPromise; -module.exports = safer +function isArrayBufferView(value) { + if (typeof ArrayBuffer !== 'undefined' && ArrayBuffer.isView) { + return ArrayBuffer.isView(value); + } -}).call(this)}).call(this,require('_process')) -},{"_process":391,"buffer":137}],406:[function(require,module,exports){ -'use strict'; + return ( + isTypedArray(value) || + isDataView(value) + ); +} +exports.isArrayBufferView = isArrayBufferView; -var GetIntrinsic = require('get-intrinsic'); -var define = require('define-data-property'); -var hasDescriptors = require('has-property-descriptors')(); -var gOPD = require('gopd'); -var $TypeError = require('es-errors/type'); -var $floor = GetIntrinsic('%Math.floor%'); +function isUint8Array(value) { + return whichTypedArray(value) === 'Uint8Array'; +} +exports.isUint8Array = isUint8Array; -/** @type {import('.')} */ -module.exports = function setFunctionLength(fn, length) { - if (typeof fn !== 'function') { - throw new $TypeError('`fn` is not a function'); - } - if (typeof length !== 'number' || length < 0 || length > 0xFFFFFFFF || $floor(length) !== length) { - throw new $TypeError('`length` must be a positive 32-bit integer'); - } +function isUint8ClampedArray(value) { + return whichTypedArray(value) === 'Uint8ClampedArray'; +} +exports.isUint8ClampedArray = isUint8ClampedArray; - var loose = arguments.length > 2 && !!arguments[2]; +function isUint16Array(value) { + return whichTypedArray(value) === 'Uint16Array'; +} +exports.isUint16Array = isUint16Array; - var functionLengthIsConfigurable = true; - var functionLengthIsWritable = true; - if ('length' in fn && gOPD) { - var desc = gOPD(fn, 'length'); - if (desc && !desc.configurable) { - functionLengthIsConfigurable = false; - } - if (desc && !desc.writable) { - functionLengthIsWritable = false; - } - } +function isUint32Array(value) { + return whichTypedArray(value) === 'Uint32Array'; +} +exports.isUint32Array = isUint32Array; - if (functionLengthIsConfigurable || functionLengthIsWritable || !loose) { - if (hasDescriptors) { - define(/** @type {Parameters[0]} */ (fn), 'length', length, true, true); - } else { - define(/** @type {Parameters[0]} */ (fn), 'length', length); - } - } - return fn; -}; +function isInt8Array(value) { + return whichTypedArray(value) === 'Int8Array'; +} +exports.isInt8Array = isInt8Array; -},{"define-data-property":173,"es-errors/type":209,"get-intrinsic":217,"gopd":218,"has-property-descriptors":219}],407:[function(require,module,exports){ -var Buffer = require('safe-buffer').Buffer +function isInt16Array(value) { + return whichTypedArray(value) === 'Int16Array'; +} +exports.isInt16Array = isInt16Array; -// prototype class for hash functions -function Hash (blockSize, finalSize) { - this._block = Buffer.alloc(blockSize) - this._finalSize = finalSize - this._blockSize = blockSize - this._len = 0 +function isInt32Array(value) { + return whichTypedArray(value) === 'Int32Array'; } +exports.isInt32Array = isInt32Array; -Hash.prototype.update = function (data, enc) { - if (typeof data === 'string') { - enc = enc || 'utf8' - data = Buffer.from(data, enc) - } +function isFloat32Array(value) { + return whichTypedArray(value) === 'Float32Array'; +} +exports.isFloat32Array = isFloat32Array; - var block = this._block - var blockSize = this._blockSize - var length = data.length - var accum = this._len +function isFloat64Array(value) { + return whichTypedArray(value) === 'Float64Array'; +} +exports.isFloat64Array = isFloat64Array; - for (var offset = 0; offset < length;) { - var assigned = accum % blockSize - var remainder = Math.min(length - offset, blockSize - assigned) +function isBigInt64Array(value) { + return whichTypedArray(value) === 'BigInt64Array'; +} +exports.isBigInt64Array = isBigInt64Array; - for (var i = 0; i < remainder; i++) { - block[assigned + i] = data[offset + i] - } +function isBigUint64Array(value) { + return whichTypedArray(value) === 'BigUint64Array'; +} +exports.isBigUint64Array = isBigUint64Array; - accum += remainder - offset += remainder +function isMapToString(value) { + return ObjectToString(value) === '[object Map]'; +} +isMapToString.working = ( + typeof Map !== 'undefined' && + isMapToString(new Map()) +); - if ((accum % blockSize) === 0) { - this._update(block) - } +function isMap(value) { + if (typeof Map === 'undefined') { + return false; } - this._len += length - return this + return isMapToString.working + ? isMapToString(value) + : value instanceof Map; } +exports.isMap = isMap; -Hash.prototype.digest = function (enc) { - var rem = this._len % this._blockSize - - this._block[rem] = 0x80 - - // zero (rem + 1) trailing bits, where (rem + 1) is the smallest - // non-negative solution to the equation (length + 1 + (rem + 1)) === finalSize mod blockSize - this._block.fill(0, rem + 1) - - if (rem >= this._finalSize) { - this._update(this._block) - this._block.fill(0) +function isSetToString(value) { + return ObjectToString(value) === '[object Set]'; +} +isSetToString.working = ( + typeof Set !== 'undefined' && + isSetToString(new Set()) +); +function isSet(value) { + if (typeof Set === 'undefined') { + return false; } - var bits = this._len * 8 - - // uint32 - if (bits <= 0xffffffff) { - this._block.writeUInt32BE(bits, this._blockSize - 4) - - // uint64 - } else { - var lowBits = (bits & 0xffffffff) >>> 0 - var highBits = (bits - lowBits) / 0x100000000 + return isSetToString.working + ? isSetToString(value) + : value instanceof Set; +} +exports.isSet = isSet; - this._block.writeUInt32BE(highBits, this._blockSize - 8) - this._block.writeUInt32BE(lowBits, this._blockSize - 4) +function isWeakMapToString(value) { + return ObjectToString(value) === '[object WeakMap]'; +} +isWeakMapToString.working = ( + typeof WeakMap !== 'undefined' && + isWeakMapToString(new WeakMap()) +); +function isWeakMap(value) { + if (typeof WeakMap === 'undefined') { + return false; } - this._update(this._block) - var hash = this._hash() - - return enc ? hash.toString(enc) : hash + return isWeakMapToString.working + ? isWeakMapToString(value) + : value instanceof WeakMap; } +exports.isWeakMap = isWeakMap; -Hash.prototype._update = function () { - throw new Error('_update must be implemented by subclass') +function isWeakSetToString(value) { + return ObjectToString(value) === '[object WeakSet]'; } - -module.exports = Hash - -},{"safe-buffer":404}],408:[function(require,module,exports){ -var exports = module.exports = function SHA (algorithm) { - algorithm = algorithm.toLowerCase() - - var Algorithm = exports[algorithm] - if (!Algorithm) throw new Error(algorithm + ' is not supported (we accept pull requests)') - - return new Algorithm() +isWeakSetToString.working = ( + typeof WeakSet !== 'undefined' && + isWeakSetToString(new WeakSet()) +); +function isWeakSet(value) { + return isWeakSetToString(value); } +exports.isWeakSet = isWeakSet; -exports.sha = require('./sha') -exports.sha1 = require('./sha1') -exports.sha224 = require('./sha224') -exports.sha256 = require('./sha256') -exports.sha384 = require('./sha384') -exports.sha512 = require('./sha512') +function isArrayBufferToString(value) { + return ObjectToString(value) === '[object ArrayBuffer]'; +} +isArrayBufferToString.working = ( + typeof ArrayBuffer !== 'undefined' && + isArrayBufferToString(new ArrayBuffer()) +); +function isArrayBuffer(value) { + if (typeof ArrayBuffer === 'undefined') { + return false; + } -},{"./sha":409,"./sha1":410,"./sha224":411,"./sha256":412,"./sha384":413,"./sha512":414}],409:[function(require,module,exports){ -/* - * A JavaScript implementation of the Secure Hash Algorithm, SHA-0, as defined - * in FIPS PUB 180-1 - * This source code is derived from sha1.js of the same repository. - * The difference between SHA-0 and SHA-1 is just a bitwise rotate left - * operation was added. - */ + return isArrayBufferToString.working + ? isArrayBufferToString(value) + : value instanceof ArrayBuffer; +} +exports.isArrayBuffer = isArrayBuffer; -var inherits = require('inherits') -var Hash = require('./hash') -var Buffer = require('safe-buffer').Buffer +function isDataViewToString(value) { + return ObjectToString(value) === '[object DataView]'; +} +isDataViewToString.working = ( + typeof ArrayBuffer !== 'undefined' && + typeof DataView !== 'undefined' && + isDataViewToString(new DataView(new ArrayBuffer(1), 0, 1)) +); +function isDataView(value) { + if (typeof DataView === 'undefined') { + return false; + } -var K = [ - 0x5a827999, 0x6ed9eba1, 0x8f1bbcdc | 0, 0xca62c1d6 | 0 -] + return isDataViewToString.working + ? isDataViewToString(value) + : value instanceof DataView; +} +exports.isDataView = isDataView; -var W = new Array(80) +// Store a copy of SharedArrayBuffer in case it's deleted elsewhere +var SharedArrayBufferCopy = typeof SharedArrayBuffer !== 'undefined' ? SharedArrayBuffer : undefined; +function isSharedArrayBufferToString(value) { + return ObjectToString(value) === '[object SharedArrayBuffer]'; +} +function isSharedArrayBuffer(value) { + if (typeof SharedArrayBufferCopy === 'undefined') { + return false; + } -function Sha () { - this.init() - this._w = W + if (typeof isSharedArrayBufferToString.working === 'undefined') { + isSharedArrayBufferToString.working = isSharedArrayBufferToString(new SharedArrayBufferCopy()); + } - Hash.call(this, 64, 56) + return isSharedArrayBufferToString.working + ? isSharedArrayBufferToString(value) + : value instanceof SharedArrayBufferCopy; } +exports.isSharedArrayBuffer = isSharedArrayBuffer; -inherits(Sha, Hash) - -Sha.prototype.init = function () { - this._a = 0x67452301 - this._b = 0xefcdab89 - this._c = 0x98badcfe - this._d = 0x10325476 - this._e = 0xc3d2e1f0 +function isAsyncFunction(value) { + return ObjectToString(value) === '[object AsyncFunction]'; +} +exports.isAsyncFunction = isAsyncFunction; - return this +function isMapIterator(value) { + return ObjectToString(value) === '[object Map Iterator]'; } +exports.isMapIterator = isMapIterator; -function rotl5 (num) { - return (num << 5) | (num >>> 27) +function isSetIterator(value) { + return ObjectToString(value) === '[object Set Iterator]'; } +exports.isSetIterator = isSetIterator; -function rotl30 (num) { - return (num << 30) | (num >>> 2) +function isGeneratorObject(value) { + return ObjectToString(value) === '[object Generator]'; } +exports.isGeneratorObject = isGeneratorObject; -function ft (s, b, c, d) { - if (s === 0) return (b & c) | ((~b) & d) - if (s === 2) return (b & c) | (b & d) | (c & d) - return b ^ c ^ d +function isWebAssemblyCompiledModule(value) { + return ObjectToString(value) === '[object WebAssembly.Module]'; } +exports.isWebAssemblyCompiledModule = isWebAssemblyCompiledModule; -Sha.prototype._update = function (M) { - var W = this._w +function isNumberObject(value) { + return checkBoxedPrimitive(value, numberValue); +} +exports.isNumberObject = isNumberObject; - var a = this._a | 0 - var b = this._b | 0 - var c = this._c | 0 - var d = this._d | 0 - var e = this._e | 0 +function isStringObject(value) { + return checkBoxedPrimitive(value, stringValue); +} +exports.isStringObject = isStringObject; - for (var i = 0; i < 16; ++i) W[i] = M.readInt32BE(i * 4) - for (; i < 80; ++i) W[i] = W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16] +function isBooleanObject(value) { + return checkBoxedPrimitive(value, booleanValue); +} +exports.isBooleanObject = isBooleanObject; - for (var j = 0; j < 80; ++j) { - var s = ~~(j / 20) - var t = (rotl5(a) + ft(s, b, c, d) + e + W[j] + K[s]) | 0 +function isBigIntObject(value) { + return BigIntSupported && checkBoxedPrimitive(value, bigIntValue); +} +exports.isBigIntObject = isBigIntObject; - e = d - d = c - c = rotl30(b) - b = a - a = t - } +function isSymbolObject(value) { + return SymbolSupported && checkBoxedPrimitive(value, symbolValue); +} +exports.isSymbolObject = isSymbolObject; - this._a = (a + this._a) | 0 - this._b = (b + this._b) | 0 - this._c = (c + this._c) | 0 - this._d = (d + this._d) | 0 - this._e = (e + this._e) | 0 +function isBoxedPrimitive(value) { + return ( + isNumberObject(value) || + isStringObject(value) || + isBooleanObject(value) || + isBigIntObject(value) || + isSymbolObject(value) + ); } +exports.isBoxedPrimitive = isBoxedPrimitive; -Sha.prototype._hash = function () { - var H = Buffer.allocUnsafe(20) +function isAnyArrayBuffer(value) { + return typeof Uint8Array !== 'undefined' && ( + isArrayBuffer(value) || + isSharedArrayBuffer(value) + ); +} +exports.isAnyArrayBuffer = isAnyArrayBuffer; - H.writeInt32BE(this._a | 0, 0) - H.writeInt32BE(this._b | 0, 4) - H.writeInt32BE(this._c | 0, 8) - H.writeInt32BE(this._d | 0, 12) - H.writeInt32BE(this._e | 0, 16) +['isProxy', 'isExternal', 'isModuleNamespaceObject'].forEach(function(method) { + Object.defineProperty(exports, method, { + enumerable: false, + value: function() { + throw new Error(method + ' is not supported in userland'); + } + }); +}); - return H -} +},{"is-arguments":201,"is-generator-function":204,"is-typed-array":205,"which-typed-array":427}],420:[function(require,module,exports){ +(function (process){(function (){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. -module.exports = Sha +var getOwnPropertyDescriptors = Object.getOwnPropertyDescriptors || + function getOwnPropertyDescriptors(obj) { + var keys = Object.keys(obj); + var descriptors = {}; + for (var i = 0; i < keys.length; i++) { + descriptors[keys[i]] = Object.getOwnPropertyDescriptor(obj, keys[i]); + } + return descriptors; + }; -},{"./hash":407,"inherits":256,"safe-buffer":404}],410:[function(require,module,exports){ -/* - * A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined - * in FIPS PUB 180-1 - * Version 2.1a Copyright Paul Johnston 2000 - 2002. - * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet - * Distributed under the BSD License - * See http://pajhome.org.uk/crypt/md5 for details. - */ +var formatRegExp = /%[sdj%]/g; +exports.format = function(f) { + if (!isString(f)) { + var objects = []; + for (var i = 0; i < arguments.length; i++) { + objects.push(inspect(arguments[i])); + } + return objects.join(' '); + } -var inherits = require('inherits') -var Hash = require('./hash') -var Buffer = require('safe-buffer').Buffer + var i = 1; + var args = arguments; + var len = args.length; + var str = String(f).replace(formatRegExp, function(x) { + if (x === '%%') return '%'; + if (i >= len) return x; + switch (x) { + case '%s': return String(args[i++]); + case '%d': return Number(args[i++]); + case '%j': + try { + return JSON.stringify(args[i++]); + } catch (_) { + return '[Circular]'; + } + default: + return x; + } + }); + for (var x = args[i]; i < len; x = args[++i]) { + if (isNull(x) || !isObject(x)) { + str += ' ' + x; + } else { + str += ' ' + inspect(x); + } + } + return str; +}; -var K = [ - 0x5a827999, 0x6ed9eba1, 0x8f1bbcdc | 0, 0xca62c1d6 | 0 -] -var W = new Array(80) +// Mark that a method should not be used. +// Returns a modified function which warns once by default. +// If --no-deprecation is set, then it is a no-op. +exports.deprecate = function(fn, msg) { + if (typeof process !== 'undefined' && process.noDeprecation === true) { + return fn; + } -function Sha1 () { - this.init() - this._w = W + // Allow for deprecating things in the process of starting up. + if (typeof process === 'undefined') { + return function() { + return exports.deprecate(fn, msg).apply(this, arguments); + }; + } - Hash.call(this, 64, 56) -} + var warned = false; + function deprecated() { + if (!warned) { + if (process.throwDeprecation) { + throw new Error(msg); + } else if (process.traceDeprecation) { + console.trace(msg); + } else { + console.error(msg); + } + warned = true; + } + return fn.apply(this, arguments); + } -inherits(Sha1, Hash) + return deprecated; +}; -Sha1.prototype.init = function () { - this._a = 0x67452301 - this._b = 0xefcdab89 - this._c = 0x98badcfe - this._d = 0x10325476 - this._e = 0xc3d2e1f0 - return this -} +var debugs = {}; +var debugEnvRegex = /^$/; -function rotl1 (num) { - return (num << 1) | (num >>> 31) +if (process.env.NODE_DEBUG) { + var debugEnv = process.env.NODE_DEBUG; + debugEnv = debugEnv.replace(/[|\\{}()[\]^$+?.]/g, '\\$&') + .replace(/\*/g, '.*') + .replace(/,/g, '$|^') + .toUpperCase(); + debugEnvRegex = new RegExp('^' + debugEnv + '$', 'i'); } +exports.debuglog = function(set) { + set = set.toUpperCase(); + if (!debugs[set]) { + if (debugEnvRegex.test(set)) { + var pid = process.pid; + debugs[set] = function() { + var msg = exports.format.apply(exports, arguments); + console.error('%s %d: %s', set, pid, msg); + }; + } else { + debugs[set] = function() {}; + } + } + return debugs[set]; +}; -function rotl5 (num) { - return (num << 5) | (num >>> 27) -} -function rotl30 (num) { - return (num << 30) | (num >>> 2) +/** + * Echos the value of a value. Trys to print the value out + * in the best way possible given the different types. + * + * @param {Object} obj The object to print out. + * @param {Object} opts Optional options object that alters the output. + */ +/* legacy: obj, showHidden, depth, colors*/ +function inspect(obj, opts) { + // default options + var ctx = { + seen: [], + stylize: stylizeNoColor + }; + // legacy... + if (arguments.length >= 3) ctx.depth = arguments[2]; + if (arguments.length >= 4) ctx.colors = arguments[3]; + if (isBoolean(opts)) { + // legacy... + ctx.showHidden = opts; + } else if (opts) { + // got an "options" object + exports._extend(ctx, opts); + } + // set default options + if (isUndefined(ctx.showHidden)) ctx.showHidden = false; + if (isUndefined(ctx.depth)) ctx.depth = 2; + if (isUndefined(ctx.colors)) ctx.colors = false; + if (isUndefined(ctx.customInspect)) ctx.customInspect = true; + if (ctx.colors) ctx.stylize = stylizeWithColor; + return formatValue(ctx, obj, ctx.depth); } +exports.inspect = inspect; -function ft (s, b, c, d) { - if (s === 0) return (b & c) | ((~b) & d) - if (s === 2) return (b & c) | (b & d) | (c & d) - return b ^ c ^ d -} -Sha1.prototype._update = function (M) { - var W = this._w +// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics +inspect.colors = { + 'bold' : [1, 22], + 'italic' : [3, 23], + 'underline' : [4, 24], + 'inverse' : [7, 27], + 'white' : [37, 39], + 'grey' : [90, 39], + 'black' : [30, 39], + 'blue' : [34, 39], + 'cyan' : [36, 39], + 'green' : [32, 39], + 'magenta' : [35, 39], + 'red' : [31, 39], + 'yellow' : [33, 39] +}; - var a = this._a | 0 - var b = this._b | 0 - var c = this._c | 0 - var d = this._d | 0 - var e = this._e | 0 +// Don't use 'blue' not visible on cmd.exe +inspect.styles = { + 'special': 'cyan', + 'number': 'yellow', + 'boolean': 'yellow', + 'undefined': 'grey', + 'null': 'bold', + 'string': 'green', + 'date': 'magenta', + // "name": intentionally not styling + 'regexp': 'red' +}; - for (var i = 0; i < 16; ++i) W[i] = M.readInt32BE(i * 4) - for (; i < 80; ++i) W[i] = rotl1(W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16]) - for (var j = 0; j < 80; ++j) { - var s = ~~(j / 20) - var t = (rotl5(a) + ft(s, b, c, d) + e + W[j] + K[s]) | 0 +function stylizeWithColor(str, styleType) { + var style = inspect.styles[styleType]; - e = d - d = c - c = rotl30(b) - b = a - a = t + if (style) { + return '\u001b[' + inspect.colors[style][0] + 'm' + str + + '\u001b[' + inspect.colors[style][1] + 'm'; + } else { + return str; } - - this._a = (a + this._a) | 0 - this._b = (b + this._b) | 0 - this._c = (c + this._c) | 0 - this._d = (d + this._d) | 0 - this._e = (e + this._e) | 0 } -Sha1.prototype._hash = function () { - var H = Buffer.allocUnsafe(20) - - H.writeInt32BE(this._a | 0, 0) - H.writeInt32BE(this._b | 0, 4) - H.writeInt32BE(this._c | 0, 8) - H.writeInt32BE(this._d | 0, 12) - H.writeInt32BE(this._e | 0, 16) - return H +function stylizeNoColor(str, styleType) { + return str; } -module.exports = Sha1 - -},{"./hash":407,"inherits":256,"safe-buffer":404}],411:[function(require,module,exports){ -/** - * A JavaScript implementation of the Secure Hash Algorithm, SHA-256, as defined - * in FIPS 180-2 - * Version 2.2-beta Copyright Angel Marin, Paul Johnston 2000 - 2009. - * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet - * - */ - -var inherits = require('inherits') -var Sha256 = require('./sha256') -var Hash = require('./hash') -var Buffer = require('safe-buffer').Buffer - -var W = new Array(64) -function Sha224 () { - this.init() +function arrayToHash(array) { + var hash = {}; - this._w = W // new Array(64) + array.forEach(function(val, idx) { + hash[val] = true; + }); - Hash.call(this, 64, 56) + return hash; } -inherits(Sha224, Sha256) -Sha224.prototype.init = function () { - this._a = 0xc1059ed8 - this._b = 0x367cd507 - this._c = 0x3070dd17 - this._d = 0xf70e5939 - this._e = 0xffc00b31 - this._f = 0x68581511 - this._g = 0x64f98fa7 - this._h = 0xbefa4fa4 +function formatValue(ctx, value, recurseTimes) { + // Provide a hook for user-specified inspect functions. + // Check that value is an object with an inspect function on it + if (ctx.customInspect && + value && + isFunction(value.inspect) && + // Filter out the util module, it's inspect function is special + value.inspect !== exports.inspect && + // Also filter out any prototype objects using the circular check. + !(value.constructor && value.constructor.prototype === value)) { + var ret = value.inspect(recurseTimes, ctx); + if (!isString(ret)) { + ret = formatValue(ctx, ret, recurseTimes); + } + return ret; + } - return this -} + // Primitive types cannot have properties + var primitive = formatPrimitive(ctx, value); + if (primitive) { + return primitive; + } -Sha224.prototype._hash = function () { - var H = Buffer.allocUnsafe(28) + // Look up the keys of the object. + var keys = Object.keys(value); + var visibleKeys = arrayToHash(keys); - H.writeInt32BE(this._a, 0) - H.writeInt32BE(this._b, 4) - H.writeInt32BE(this._c, 8) - H.writeInt32BE(this._d, 12) - H.writeInt32BE(this._e, 16) - H.writeInt32BE(this._f, 20) - H.writeInt32BE(this._g, 24) + if (ctx.showHidden) { + keys = Object.getOwnPropertyNames(value); + } - return H -} + // IE doesn't make error fields non-enumerable + // http://msdn.microsoft.com/en-us/library/ie/dww52sbt(v=vs.94).aspx + if (isError(value) + && (keys.indexOf('message') >= 0 || keys.indexOf('description') >= 0)) { + return formatError(value); + } -module.exports = Sha224 + // Some type of object without properties can be shortcutted. + if (keys.length === 0) { + if (isFunction(value)) { + var name = value.name ? ': ' + value.name : ''; + return ctx.stylize('[Function' + name + ']', 'special'); + } + if (isRegExp(value)) { + return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); + } + if (isDate(value)) { + return ctx.stylize(Date.prototype.toString.call(value), 'date'); + } + if (isError(value)) { + return formatError(value); + } + } -},{"./hash":407,"./sha256":412,"inherits":256,"safe-buffer":404}],412:[function(require,module,exports){ -/** - * A JavaScript implementation of the Secure Hash Algorithm, SHA-256, as defined - * in FIPS 180-2 - * Version 2.2-beta Copyright Angel Marin, Paul Johnston 2000 - 2009. - * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet - * - */ + var base = '', array = false, braces = ['{', '}']; -var inherits = require('inherits') -var Hash = require('./hash') -var Buffer = require('safe-buffer').Buffer + // Make Array say that they are Array + if (isArray(value)) { + array = true; + braces = ['[', ']']; + } -var K = [ - 0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5, - 0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5, - 0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3, - 0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174, - 0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC, - 0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA, - 0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7, - 0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967, - 0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13, - 0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85, - 0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3, - 0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070, - 0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5, - 0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3, - 0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208, - 0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2 -] + // Make functions say that they are functions + if (isFunction(value)) { + var n = value.name ? ': ' + value.name : ''; + base = ' [Function' + n + ']'; + } -var W = new Array(64) + // Make RegExps say that they are RegExps + if (isRegExp(value)) { + base = ' ' + RegExp.prototype.toString.call(value); + } -function Sha256 () { - this.init() + // Make dates with properties first say the date + if (isDate(value)) { + base = ' ' + Date.prototype.toUTCString.call(value); + } - this._w = W // new Array(64) + // Make error with message first say the error + if (isError(value)) { + base = ' ' + formatError(value); + } - Hash.call(this, 64, 56) -} + if (keys.length === 0 && (!array || value.length == 0)) { + return braces[0] + base + braces[1]; + } -inherits(Sha256, Hash) + if (recurseTimes < 0) { + if (isRegExp(value)) { + return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); + } else { + return ctx.stylize('[Object]', 'special'); + } + } -Sha256.prototype.init = function () { - this._a = 0x6a09e667 - this._b = 0xbb67ae85 - this._c = 0x3c6ef372 - this._d = 0xa54ff53a - this._e = 0x510e527f - this._f = 0x9b05688c - this._g = 0x1f83d9ab - this._h = 0x5be0cd19 + ctx.seen.push(value); - return this -} + var output; + if (array) { + output = formatArray(ctx, value, recurseTimes, visibleKeys, keys); + } else { + output = keys.map(function(key) { + return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array); + }); + } -function ch (x, y, z) { - return z ^ (x & (y ^ z)) -} + ctx.seen.pop(); -function maj (x, y, z) { - return (x & y) | (z & (x | y)) + return reduceToSingleString(output, base, braces); } -function sigma0 (x) { - return (x >>> 2 | x << 30) ^ (x >>> 13 | x << 19) ^ (x >>> 22 | x << 10) -} -function sigma1 (x) { - return (x >>> 6 | x << 26) ^ (x >>> 11 | x << 21) ^ (x >>> 25 | x << 7) +function formatPrimitive(ctx, value) { + if (isUndefined(value)) + return ctx.stylize('undefined', 'undefined'); + if (isString(value)) { + var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '') + .replace(/'/g, "\\'") + .replace(/\\"/g, '"') + '\''; + return ctx.stylize(simple, 'string'); + } + if (isNumber(value)) + return ctx.stylize('' + value, 'number'); + if (isBoolean(value)) + return ctx.stylize('' + value, 'boolean'); + // For some reason typeof null is "object", so special case here. + if (isNull(value)) + return ctx.stylize('null', 'null'); } -function gamma0 (x) { - return (x >>> 7 | x << 25) ^ (x >>> 18 | x << 14) ^ (x >>> 3) -} -function gamma1 (x) { - return (x >>> 17 | x << 15) ^ (x >>> 19 | x << 13) ^ (x >>> 10) +function formatError(value) { + return '[' + Error.prototype.toString.call(value) + ']'; } -Sha256.prototype._update = function (M) { - var W = this._w - - var a = this._a | 0 - var b = this._b | 0 - var c = this._c | 0 - var d = this._d | 0 - var e = this._e | 0 - var f = this._f | 0 - var g = this._g | 0 - var h = this._h | 0 - for (var i = 0; i < 16; ++i) W[i] = M.readInt32BE(i * 4) - for (; i < 64; ++i) W[i] = (gamma1(W[i - 2]) + W[i - 7] + gamma0(W[i - 15]) + W[i - 16]) | 0 +function formatArray(ctx, value, recurseTimes, visibleKeys, keys) { + var output = []; + for (var i = 0, l = value.length; i < l; ++i) { + if (hasOwnProperty(value, String(i))) { + output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, + String(i), true)); + } else { + output.push(''); + } + } + keys.forEach(function(key) { + if (!key.match(/^\d+$/)) { + output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, + key, true)); + } + }); + return output; +} - for (var j = 0; j < 64; ++j) { - var T1 = (h + sigma1(e) + ch(e, f, g) + K[j] + W[j]) | 0 - var T2 = (sigma0(a) + maj(a, b, c)) | 0 - h = g - g = f - f = e - e = (d + T1) | 0 - d = c - c = b - b = a - a = (T1 + T2) | 0 +function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) { + var name, str, desc; + desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] }; + if (desc.get) { + if (desc.set) { + str = ctx.stylize('[Getter/Setter]', 'special'); + } else { + str = ctx.stylize('[Getter]', 'special'); + } + } else { + if (desc.set) { + str = ctx.stylize('[Setter]', 'special'); + } + } + if (!hasOwnProperty(visibleKeys, key)) { + name = '[' + key + ']'; + } + if (!str) { + if (ctx.seen.indexOf(desc.value) < 0) { + if (isNull(recurseTimes)) { + str = formatValue(ctx, desc.value, null); + } else { + str = formatValue(ctx, desc.value, recurseTimes - 1); + } + if (str.indexOf('\n') > -1) { + if (array) { + str = str.split('\n').map(function(line) { + return ' ' + line; + }).join('\n').slice(2); + } else { + str = '\n' + str.split('\n').map(function(line) { + return ' ' + line; + }).join('\n'); + } + } + } else { + str = ctx.stylize('[Circular]', 'special'); + } + } + if (isUndefined(name)) { + if (array && key.match(/^\d+$/)) { + return str; + } + name = JSON.stringify('' + key); + if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) { + name = name.slice(1, -1); + name = ctx.stylize(name, 'name'); + } else { + name = name.replace(/'/g, "\\'") + .replace(/\\"/g, '"') + .replace(/(^"|"$)/g, "'"); + name = ctx.stylize(name, 'string'); + } } - this._a = (a + this._a) | 0 - this._b = (b + this._b) | 0 - this._c = (c + this._c) | 0 - this._d = (d + this._d) | 0 - this._e = (e + this._e) | 0 - this._f = (f + this._f) | 0 - this._g = (g + this._g) | 0 - this._h = (h + this._h) | 0 + return name + ': ' + str; } -Sha256.prototype._hash = function () { - var H = Buffer.allocUnsafe(32) - H.writeInt32BE(this._a, 0) - H.writeInt32BE(this._b, 4) - H.writeInt32BE(this._c, 8) - H.writeInt32BE(this._d, 12) - H.writeInt32BE(this._e, 16) - H.writeInt32BE(this._f, 20) - H.writeInt32BE(this._g, 24) - H.writeInt32BE(this._h, 28) +function reduceToSingleString(output, base, braces) { + var numLinesEst = 0; + var length = output.reduce(function(prev, cur) { + numLinesEst++; + if (cur.indexOf('\n') >= 0) numLinesEst++; + return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1; + }, 0); - return H -} + if (length > 60) { + return braces[0] + + (base === '' ? '' : base + '\n ') + + ' ' + + output.join(',\n ') + + ' ' + + braces[1]; + } -module.exports = Sha256 + return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1]; +} -},{"./hash":407,"inherits":256,"safe-buffer":404}],413:[function(require,module,exports){ -var inherits = require('inherits') -var SHA512 = require('./sha512') -var Hash = require('./hash') -var Buffer = require('safe-buffer').Buffer -var W = new Array(160) +// NOTE: These type checking functions intentionally don't use `instanceof` +// because it is fragile and can be easily faked with `Object.create()`. +exports.types = require('./support/types'); -function Sha384 () { - this.init() - this._w = W +function isArray(ar) { + return Array.isArray(ar); +} +exports.isArray = isArray; - Hash.call(this, 128, 112) +function isBoolean(arg) { + return typeof arg === 'boolean'; } +exports.isBoolean = isBoolean; -inherits(Sha384, SHA512) +function isNull(arg) { + return arg === null; +} +exports.isNull = isNull; -Sha384.prototype.init = function () { - this._ah = 0xcbbb9d5d - this._bh = 0x629a292a - this._ch = 0x9159015a - this._dh = 0x152fecd8 - this._eh = 0x67332667 - this._fh = 0x8eb44a87 - this._gh = 0xdb0c2e0d - this._hh = 0x47b5481d +function isNullOrUndefined(arg) { + return arg == null; +} +exports.isNullOrUndefined = isNullOrUndefined; - this._al = 0xc1059ed8 - this._bl = 0x367cd507 - this._cl = 0x3070dd17 - this._dl = 0xf70e5939 - this._el = 0xffc00b31 - this._fl = 0x68581511 - this._gl = 0x64f98fa7 - this._hl = 0xbefa4fa4 +function isNumber(arg) { + return typeof arg === 'number'; +} +exports.isNumber = isNumber; - return this +function isString(arg) { + return typeof arg === 'string'; } +exports.isString = isString; -Sha384.prototype._hash = function () { - var H = Buffer.allocUnsafe(48) +function isSymbol(arg) { + return typeof arg === 'symbol'; +} +exports.isSymbol = isSymbol; - function writeInt64BE (h, l, offset) { - H.writeInt32BE(h, offset) - H.writeInt32BE(l, offset + 4) - } +function isUndefined(arg) { + return arg === void 0; +} +exports.isUndefined = isUndefined; - writeInt64BE(this._ah, this._al, 0) - writeInt64BE(this._bh, this._bl, 8) - writeInt64BE(this._ch, this._cl, 16) - writeInt64BE(this._dh, this._dl, 24) - writeInt64BE(this._eh, this._el, 32) - writeInt64BE(this._fh, this._fl, 40) +function isRegExp(re) { + return isObject(re) && objectToString(re) === '[object RegExp]'; +} +exports.isRegExp = isRegExp; +exports.types.isRegExp = isRegExp; - return H +function isObject(arg) { + return typeof arg === 'object' && arg !== null; } +exports.isObject = isObject; -module.exports = Sha384 +function isDate(d) { + return isObject(d) && objectToString(d) === '[object Date]'; +} +exports.isDate = isDate; +exports.types.isDate = isDate; -},{"./hash":407,"./sha512":414,"inherits":256,"safe-buffer":404}],414:[function(require,module,exports){ -var inherits = require('inherits') -var Hash = require('./hash') -var Buffer = require('safe-buffer').Buffer +function isError(e) { + return isObject(e) && + (objectToString(e) === '[object Error]' || e instanceof Error); +} +exports.isError = isError; +exports.types.isNativeError = isError; -var K = [ - 0x428a2f98, 0xd728ae22, 0x71374491, 0x23ef65cd, - 0xb5c0fbcf, 0xec4d3b2f, 0xe9b5dba5, 0x8189dbbc, - 0x3956c25b, 0xf348b538, 0x59f111f1, 0xb605d019, - 0x923f82a4, 0xaf194f9b, 0xab1c5ed5, 0xda6d8118, - 0xd807aa98, 0xa3030242, 0x12835b01, 0x45706fbe, - 0x243185be, 0x4ee4b28c, 0x550c7dc3, 0xd5ffb4e2, - 0x72be5d74, 0xf27b896f, 0x80deb1fe, 0x3b1696b1, - 0x9bdc06a7, 0x25c71235, 0xc19bf174, 0xcf692694, - 0xe49b69c1, 0x9ef14ad2, 0xefbe4786, 0x384f25e3, - 0x0fc19dc6, 0x8b8cd5b5, 0x240ca1cc, 0x77ac9c65, - 0x2de92c6f, 0x592b0275, 0x4a7484aa, 0x6ea6e483, - 0x5cb0a9dc, 0xbd41fbd4, 0x76f988da, 0x831153b5, - 0x983e5152, 0xee66dfab, 0xa831c66d, 0x2db43210, - 0xb00327c8, 0x98fb213f, 0xbf597fc7, 0xbeef0ee4, - 0xc6e00bf3, 0x3da88fc2, 0xd5a79147, 0x930aa725, - 0x06ca6351, 0xe003826f, 0x14292967, 0x0a0e6e70, - 0x27b70a85, 0x46d22ffc, 0x2e1b2138, 0x5c26c926, - 0x4d2c6dfc, 0x5ac42aed, 0x53380d13, 0x9d95b3df, - 0x650a7354, 0x8baf63de, 0x766a0abb, 0x3c77b2a8, - 0x81c2c92e, 0x47edaee6, 0x92722c85, 0x1482353b, - 0xa2bfe8a1, 0x4cf10364, 0xa81a664b, 0xbc423001, - 0xc24b8b70, 0xd0f89791, 0xc76c51a3, 0x0654be30, - 0xd192e819, 0xd6ef5218, 0xd6990624, 0x5565a910, - 0xf40e3585, 0x5771202a, 0x106aa070, 0x32bbd1b8, - 0x19a4c116, 0xb8d2d0c8, 0x1e376c08, 0x5141ab53, - 0x2748774c, 0xdf8eeb99, 0x34b0bcb5, 0xe19b48a8, - 0x391c0cb3, 0xc5c95a63, 0x4ed8aa4a, 0xe3418acb, - 0x5b9cca4f, 0x7763e373, 0x682e6ff3, 0xd6b2b8a3, - 0x748f82ee, 0x5defb2fc, 0x78a5636f, 0x43172f60, - 0x84c87814, 0xa1f0ab72, 0x8cc70208, 0x1a6439ec, - 0x90befffa, 0x23631e28, 0xa4506ceb, 0xde82bde9, - 0xbef9a3f7, 0xb2c67915, 0xc67178f2, 0xe372532b, - 0xca273ece, 0xea26619c, 0xd186b8c7, 0x21c0c207, - 0xeada7dd6, 0xcde0eb1e, 0xf57d4f7f, 0xee6ed178, - 0x06f067aa, 0x72176fba, 0x0a637dc5, 0xa2c898a6, - 0x113f9804, 0xbef90dae, 0x1b710b35, 0x131c471b, - 0x28db77f5, 0x23047d84, 0x32caab7b, 0x40c72493, - 0x3c9ebe0a, 0x15c9bebc, 0x431d67c4, 0x9c100d4c, - 0x4cc5d4be, 0xcb3e42b6, 0x597f299c, 0xfc657e2a, - 0x5fcb6fab, 0x3ad6faec, 0x6c44198c, 0x4a475817 -] +function isFunction(arg) { + return typeof arg === 'function'; +} +exports.isFunction = isFunction; -var W = new Array(160) +function isPrimitive(arg) { + return arg === null || + typeof arg === 'boolean' || + typeof arg === 'number' || + typeof arg === 'string' || + typeof arg === 'symbol' || // ES6 symbol + typeof arg === 'undefined'; +} +exports.isPrimitive = isPrimitive; -function Sha512 () { - this.init() - this._w = W +exports.isBuffer = require('./support/isBuffer'); - Hash.call(this, 128, 112) +function objectToString(o) { + return Object.prototype.toString.call(o); } -inherits(Sha512, Hash) -Sha512.prototype.init = function () { - this._ah = 0x6a09e667 - this._bh = 0xbb67ae85 - this._ch = 0x3c6ef372 - this._dh = 0xa54ff53a - this._eh = 0x510e527f - this._fh = 0x9b05688c - this._gh = 0x1f83d9ab - this._hh = 0x5be0cd19 +function pad(n) { + return n < 10 ? '0' + n.toString(10) : n.toString(10); +} - this._al = 0xf3bcc908 - this._bl = 0x84caa73b - this._cl = 0xfe94f82b - this._dl = 0x5f1d36f1 - this._el = 0xade682d1 - this._fl = 0x2b3e6c1f - this._gl = 0xfb41bd6b - this._hl = 0x137e2179 - return this -} +var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', + 'Oct', 'Nov', 'Dec']; -function Ch (x, y, z) { - return z ^ (x & (y ^ z)) +// 26 Feb 16:19:34 +function timestamp() { + var d = new Date(); + var time = [pad(d.getHours()), + pad(d.getMinutes()), + pad(d.getSeconds())].join(':'); + return [d.getDate(), months[d.getMonth()], time].join(' '); } -function maj (x, y, z) { - return (x & y) | (z & (x | y)) -} -function sigma0 (x, xl) { - return (x >>> 28 | xl << 4) ^ (xl >>> 2 | x << 30) ^ (xl >>> 7 | x << 25) -} +// log is just a thin wrapper to console.log that prepends a timestamp +exports.log = function() { + console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments)); +}; -function sigma1 (x, xl) { - return (x >>> 14 | xl << 18) ^ (x >>> 18 | xl << 14) ^ (xl >>> 9 | x << 23) -} -function Gamma0 (x, xl) { - return (x >>> 1 | xl << 31) ^ (x >>> 8 | xl << 24) ^ (x >>> 7) -} +/** + * Inherit the prototype methods from one constructor into another. + * + * The Function.prototype.inherits from lang.js rewritten as a standalone + * function (not on Function.prototype). NOTE: If this file is to be loaded + * during bootstrapping this function needs to be rewritten using some native + * functions as prototype setup using normal JavaScript does not work as + * expected during bootstrapping (see mirror.js in r114903). + * + * @param {function} ctor Constructor function which needs to inherit the + * prototype. + * @param {function} superCtor Constructor function to inherit prototype from. + */ +exports.inherits = require('inherits'); -function Gamma0l (x, xl) { - return (x >>> 1 | xl << 31) ^ (x >>> 8 | xl << 24) ^ (x >>> 7 | xl << 25) -} +exports._extend = function(origin, add) { + // Don't do anything if add isn't an object + if (!add || !isObject(add)) return origin; -function Gamma1 (x, xl) { - return (x >>> 19 | xl << 13) ^ (xl >>> 29 | x << 3) ^ (x >>> 6) -} + var keys = Object.keys(add); + var i = keys.length; + while (i--) { + origin[keys[i]] = add[keys[i]]; + } + return origin; +}; -function Gamma1l (x, xl) { - return (x >>> 19 | xl << 13) ^ (xl >>> 29 | x << 3) ^ (x >>> 6 | xl << 26) +function hasOwnProperty(obj, prop) { + return Object.prototype.hasOwnProperty.call(obj, prop); } -function getCarry (a, b) { - return (a >>> 0) < (b >>> 0) ? 1 : 0 -} +var kCustomPromisifiedSymbol = typeof Symbol !== 'undefined' ? Symbol('util.promisify.custom') : undefined; -Sha512.prototype._update = function (M) { - var W = this._w +exports.promisify = function promisify(original) { + if (typeof original !== 'function') + throw new TypeError('The "original" argument must be of type Function'); - var ah = this._ah | 0 - var bh = this._bh | 0 - var ch = this._ch | 0 - var dh = this._dh | 0 - var eh = this._eh | 0 - var fh = this._fh | 0 - var gh = this._gh | 0 - var hh = this._hh | 0 + if (kCustomPromisifiedSymbol && original[kCustomPromisifiedSymbol]) { + var fn = original[kCustomPromisifiedSymbol]; + if (typeof fn !== 'function') { + throw new TypeError('The "util.promisify.custom" argument must be of type Function'); + } + Object.defineProperty(fn, kCustomPromisifiedSymbol, { + value: fn, enumerable: false, writable: false, configurable: true + }); + return fn; + } - var al = this._al | 0 - var bl = this._bl | 0 - var cl = this._cl | 0 - var dl = this._dl | 0 - var el = this._el | 0 - var fl = this._fl | 0 - var gl = this._gl | 0 - var hl = this._hl | 0 + function fn() { + var promiseResolve, promiseReject; + var promise = new Promise(function (resolve, reject) { + promiseResolve = resolve; + promiseReject = reject; + }); - for (var i = 0; i < 32; i += 2) { - W[i] = M.readInt32BE(i * 4) - W[i + 1] = M.readInt32BE(i * 4 + 4) + var args = []; + for (var i = 0; i < arguments.length; i++) { + args.push(arguments[i]); + } + args.push(function (err, value) { + if (err) { + promiseReject(err); + } else { + promiseResolve(value); + } + }); + + try { + original.apply(this, args); + } catch (err) { + promiseReject(err); + } + + return promise; } - for (; i < 160; i += 2) { - var xh = W[i - 15 * 2] - var xl = W[i - 15 * 2 + 1] - var gamma0 = Gamma0(xh, xl) - var gamma0l = Gamma0l(xl, xh) - xh = W[i - 2 * 2] - xl = W[i - 2 * 2 + 1] - var gamma1 = Gamma1(xh, xl) - var gamma1l = Gamma1l(xl, xh) + Object.setPrototypeOf(fn, Object.getPrototypeOf(original)); - // W[i] = gamma0 + W[i - 7] + gamma1 + W[i - 16] - var Wi7h = W[i - 7 * 2] - var Wi7l = W[i - 7 * 2 + 1] + if (kCustomPromisifiedSymbol) Object.defineProperty(fn, kCustomPromisifiedSymbol, { + value: fn, enumerable: false, writable: false, configurable: true + }); + return Object.defineProperties( + fn, + getOwnPropertyDescriptors(original) + ); +} - var Wi16h = W[i - 16 * 2] - var Wi16l = W[i - 16 * 2 + 1] +exports.promisify.custom = kCustomPromisifiedSymbol - var Wil = (gamma0l + Wi7l) | 0 - var Wih = (gamma0 + Wi7h + getCarry(Wil, gamma0l)) | 0 - Wil = (Wil + gamma1l) | 0 - Wih = (Wih + gamma1 + getCarry(Wil, gamma1l)) | 0 - Wil = (Wil + Wi16l) | 0 - Wih = (Wih + Wi16h + getCarry(Wil, Wi16l)) | 0 +function callbackifyOnRejected(reason, cb) { + // `!reason` guard inspired by bluebird (Ref: https://goo.gl/t5IS6M). + // Because `null` is a special error value in callbacks which means "no error + // occurred", we error-wrap so the callback consumer can distinguish between + // "the promise rejected with null" or "the promise fulfilled with undefined". + if (!reason) { + var newReason = new Error('Promise was rejected with a falsy value'); + newReason.reason = reason; + reason = newReason; + } + return cb(reason); +} - W[i] = Wih - W[i + 1] = Wil +function callbackify(original) { + if (typeof original !== 'function') { + throw new TypeError('The "original" argument must be of type Function'); } - for (var j = 0; j < 160; j += 2) { - Wih = W[j] - Wil = W[j + 1] + // We DO NOT return the promise as it gives the user a false sense that + // the promise is actually somehow related to the callback's execution + // and that the callback throwing will reject the promise. + function callbackified() { + var args = []; + for (var i = 0; i < arguments.length; i++) { + args.push(arguments[i]); + } - var majh = maj(ah, bh, ch) - var majl = maj(al, bl, cl) + var maybeCb = args.pop(); + if (typeof maybeCb !== 'function') { + throw new TypeError('The last argument must be of type Function'); + } + var self = this; + var cb = function() { + return maybeCb.apply(self, arguments); + }; + // In true node style we process the callback on `nextTick` with all the + // implications (stack, `uncaughtException`, `async_hooks`) + original.apply(this, args) + .then(function(ret) { process.nextTick(cb.bind(null, null, ret)) }, + function(rej) { process.nextTick(callbackifyOnRejected.bind(null, rej, cb)) }); + } - var sigma0h = sigma0(ah, al) - var sigma0l = sigma0(al, ah) - var sigma1h = sigma1(eh, el) - var sigma1l = sigma1(el, eh) + Object.setPrototypeOf(callbackified, Object.getPrototypeOf(original)); + Object.defineProperties(callbackified, + getOwnPropertyDescriptors(original)); + return callbackified; +} +exports.callbackify = callbackify; - // t1 = h + sigma1 + ch + K[j] + W[j] - var Kih = K[j] - var Kil = K[j + 1] +}).call(this)}).call(this,require('_process')) +},{"./support/isBuffer":418,"./support/types":419,"_process":350,"inherits":200}],421:[function(require,module,exports){ +var v1 = require('./v1'); +var v4 = require('./v4'); - var chh = Ch(eh, fh, gh) - var chl = Ch(el, fl, gl) +var uuid = v4; +uuid.v1 = v1; +uuid.v4 = v4; - var t1l = (hl + sigma1l) | 0 - var t1h = (hh + sigma1h + getCarry(t1l, hl)) | 0 - t1l = (t1l + chl) | 0 - t1h = (t1h + chh + getCarry(t1l, chl)) | 0 - t1l = (t1l + Kil) | 0 - t1h = (t1h + Kih + getCarry(t1l, Kil)) | 0 - t1l = (t1l + Wil) | 0 - t1h = (t1h + Wih + getCarry(t1l, Wil)) | 0 +module.exports = uuid; - // t2 = sigma0 + maj - var t2l = (sigma0l + majl) | 0 - var t2h = (sigma0h + majh + getCarry(t2l, sigma0l)) | 0 +},{"./v1":424,"./v4":425}],422:[function(require,module,exports){ +/** + * Convert array of 16 byte values to UUID string format of the form: + * XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX + */ +var byteToHex = []; +for (var i = 0; i < 256; ++i) { + byteToHex[i] = (i + 0x100).toString(16).substr(1); +} - hh = gh - hl = gl - gh = fh - gl = fl - fh = eh - fl = el - el = (dl + t1l) | 0 - eh = (dh + t1h + getCarry(el, dl)) | 0 - dh = ch - dl = cl - ch = bh - cl = bl - bh = ah - bl = al - al = (t1l + t2l) | 0 - ah = (t1h + t2h + getCarry(al, t1l)) | 0 - } +function bytesToUuid(buf, offset) { + var i = offset || 0; + var bth = byteToHex; + // join used to fix memory issue caused by concatenation: https://bugs.chromium.org/p/v8/issues/detail?id=3175#c4 + return ([ + bth[buf[i++]], bth[buf[i++]], + bth[buf[i++]], bth[buf[i++]], '-', + bth[buf[i++]], bth[buf[i++]], '-', + bth[buf[i++]], bth[buf[i++]], '-', + bth[buf[i++]], bth[buf[i++]], '-', + bth[buf[i++]], bth[buf[i++]], + bth[buf[i++]], bth[buf[i++]], + bth[buf[i++]], bth[buf[i++]] + ]).join(''); +} - this._al = (this._al + al) | 0 - this._bl = (this._bl + bl) | 0 - this._cl = (this._cl + cl) | 0 - this._dl = (this._dl + dl) | 0 - this._el = (this._el + el) | 0 - this._fl = (this._fl + fl) | 0 - this._gl = (this._gl + gl) | 0 - this._hl = (this._hl + hl) | 0 +module.exports = bytesToUuid; - this._ah = (this._ah + ah + getCarry(this._al, al)) | 0 - this._bh = (this._bh + bh + getCarry(this._bl, bl)) | 0 - this._ch = (this._ch + ch + getCarry(this._cl, cl)) | 0 - this._dh = (this._dh + dh + getCarry(this._dl, dl)) | 0 - this._eh = (this._eh + eh + getCarry(this._el, el)) | 0 - this._fh = (this._fh + fh + getCarry(this._fl, fl)) | 0 - this._gh = (this._gh + gh + getCarry(this._gl, gl)) | 0 - this._hh = (this._hh + hh + getCarry(this._hl, hl)) | 0 -} +},{}],423:[function(require,module,exports){ +// Unique ID creation requires a high quality random # generator. In the +// browser this is a little complicated due to unknown quality of Math.random() +// and inconsistent support for the `crypto` API. We do the best we can via +// feature-detection -Sha512.prototype._hash = function () { - var H = Buffer.allocUnsafe(64) +// getRandomValues needs to be invoked in a context where "this" is a Crypto +// implementation. Also, find the complete implementation of crypto on IE11. +var getRandomValues = (typeof(crypto) != 'undefined' && crypto.getRandomValues && crypto.getRandomValues.bind(crypto)) || + (typeof(msCrypto) != 'undefined' && typeof window.msCrypto.getRandomValues == 'function' && msCrypto.getRandomValues.bind(msCrypto)); - function writeInt64BE (h, l, offset) { - H.writeInt32BE(h, offset) - H.writeInt32BE(l, offset + 4) - } +if (getRandomValues) { + // WHATWG crypto RNG - http://wiki.whatwg.org/wiki/Crypto + var rnds8 = new Uint8Array(16); // eslint-disable-line no-undef - writeInt64BE(this._ah, this._al, 0) - writeInt64BE(this._bh, this._bl, 8) - writeInt64BE(this._ch, this._cl, 16) - writeInt64BE(this._dh, this._dl, 24) - writeInt64BE(this._eh, this._el, 32) - writeInt64BE(this._fh, this._fl, 40) - writeInt64BE(this._gh, this._gl, 48) - writeInt64BE(this._hh, this._hl, 56) + module.exports = function whatwgRNG() { + getRandomValues(rnds8); + return rnds8; + }; +} else { + // Math.random()-based (RNG) + // + // If all else fails, use Math.random(). It's fast, but is of unspecified + // quality. + var rnds = new Array(16); - return H + module.exports = function mathRNG() { + for (var i = 0, r; i < 16; i++) { + if ((i & 0x03) === 0) r = Math.random() * 0x100000000; + rnds[i] = r >>> ((i & 0x03) << 3) & 0xff; + } + + return rnds; + }; } -module.exports = Sha512 +},{}],424:[function(require,module,exports){ +var rng = require('./lib/rng'); +var bytesToUuid = require('./lib/bytesToUuid'); -},{"./hash":407,"inherits":256,"safe-buffer":404}],415:[function(require,module,exports){ -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. +// **`v1()` - Generate time-based UUID** // -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. +// Inspired by https://github.com/LiosK/UUID.js +// and http://docs.python.org/library/uuid.html -'use strict'; +var _nodeId; +var _clockseq; -/**/ +// Previous uuid creation time +var _lastMSecs = 0; +var _lastNSecs = 0; -var Buffer = require('safe-buffer').Buffer; -/**/ +// See https://github.com/uuidjs/uuid for API details +function v1(options, buf, offset) { + var i = buf && offset || 0; + var b = buf || []; -var isEncoding = Buffer.isEncoding || function (encoding) { - encoding = '' + encoding; - switch (encoding && encoding.toLowerCase()) { - case 'hex':case 'utf8':case 'utf-8':case 'ascii':case 'binary':case 'base64':case 'ucs2':case 'ucs-2':case 'utf16le':case 'utf-16le':case 'raw': - return true; - default: - return false; - } -}; + options = options || {}; + var node = options.node || _nodeId; + var clockseq = options.clockseq !== undefined ? options.clockseq : _clockseq; -function _normalizeEncoding(enc) { - if (!enc) return 'utf8'; - var retried; - while (true) { - switch (enc) { - case 'utf8': - case 'utf-8': - return 'utf8'; - case 'ucs2': - case 'ucs-2': - case 'utf16le': - case 'utf-16le': - return 'utf16le'; - case 'latin1': - case 'binary': - return 'latin1'; - case 'base64': - case 'ascii': - case 'hex': - return enc; - default: - if (retried) return; // undefined - enc = ('' + enc).toLowerCase(); - retried = true; + // node and clockseq need to be initialized to random values if they're not + // specified. We do this lazily to minimize issues related to insufficient + // system entropy. See #189 + if (node == null || clockseq == null) { + var seedBytes = rng(); + if (node == null) { + // Per 4.5, create and 48-bit node id, (47 random bits + multicast bit = 1) + node = _nodeId = [ + seedBytes[0] | 0x01, + seedBytes[1], seedBytes[2], seedBytes[3], seedBytes[4], seedBytes[5] + ]; + } + if (clockseq == null) { + // Per 4.2.2, randomize (14 bit) clockseq + clockseq = _clockseq = (seedBytes[6] << 8 | seedBytes[7]) & 0x3fff; } } -}; -// Do not cache `Buffer.isEncoding` when checking encoding names as some -// modules monkey-patch it to support additional encodings -function normalizeEncoding(enc) { - var nenc = _normalizeEncoding(enc); - if (typeof nenc !== 'string' && (Buffer.isEncoding === isEncoding || !isEncoding(enc))) throw new Error('Unknown encoding: ' + enc); - return nenc || enc; -} + // UUID timestamps are 100 nano-second units since the Gregorian epoch, + // (1582-10-15 00:00). JSNumbers aren't precise enough for this, so + // time is handled internally as 'msecs' (integer milliseconds) and 'nsecs' + // (100-nanoseconds offset from msecs) since unix epoch, 1970-01-01 00:00. + var msecs = options.msecs !== undefined ? options.msecs : new Date().getTime(); -// StringDecoder provides an interface for efficiently splitting a series of -// buffers into a series of JS strings without breaking apart multi-byte -// characters. -exports.StringDecoder = StringDecoder; -function StringDecoder(encoding) { - this.encoding = normalizeEncoding(encoding); - var nb; - switch (this.encoding) { - case 'utf16le': - this.text = utf16Text; - this.end = utf16End; - nb = 4; - break; - case 'utf8': - this.fillLast = utf8FillLast; - nb = 4; - break; - case 'base64': - this.text = base64Text; - this.end = base64End; - nb = 3; - break; - default: - this.write = simpleWrite; - this.end = simpleEnd; - return; + // Per 4.2.1.2, use count of uuid's generated during the current clock + // cycle to simulate higher resolution clock + var nsecs = options.nsecs !== undefined ? options.nsecs : _lastNSecs + 1; + + // Time since last uuid creation (in msecs) + var dt = (msecs - _lastMSecs) + (nsecs - _lastNSecs)/10000; + + // Per 4.2.1.2, Bump clockseq on clock regression + if (dt < 0 && options.clockseq === undefined) { + clockseq = clockseq + 1 & 0x3fff; } - this.lastNeed = 0; - this.lastTotal = 0; - this.lastChar = Buffer.allocUnsafe(nb); -} -StringDecoder.prototype.write = function (buf) { - if (buf.length === 0) return ''; - var r; - var i; - if (this.lastNeed) { - r = this.fillLast(buf); - if (r === undefined) return ''; - i = this.lastNeed; - this.lastNeed = 0; - } else { - i = 0; + // Reset nsecs if clock regresses (new clockseq) or we've moved onto a new + // time interval + if ((dt < 0 || msecs > _lastMSecs) && options.nsecs === undefined) { + nsecs = 0; } - if (i < buf.length) return r ? r + this.text(buf, i) : this.text(buf, i); - return r || ''; -}; -StringDecoder.prototype.end = utf8End; + // Per 4.2.1.2 Throw error if too many uuids are requested + if (nsecs >= 10000) { + throw new Error('uuid.v1(): Can\'t create more than 10M uuids/sec'); + } -// Returns only complete characters in a Buffer -StringDecoder.prototype.text = utf8Text; + _lastMSecs = msecs; + _lastNSecs = nsecs; + _clockseq = clockseq; -// Attempts to complete a partial non-UTF-8 character using bytes from a Buffer -StringDecoder.prototype.fillLast = function (buf) { - if (this.lastNeed <= buf.length) { - buf.copy(this.lastChar, this.lastTotal - this.lastNeed, 0, this.lastNeed); - return this.lastChar.toString(this.encoding, 0, this.lastTotal); - } - buf.copy(this.lastChar, this.lastTotal - this.lastNeed, 0, buf.length); - this.lastNeed -= buf.length; -}; + // Per 4.1.4 - Convert from unix epoch to Gregorian epoch + msecs += 12219292800000; -// Checks the type of a UTF-8 byte, whether it's ASCII, a leading byte, or a -// continuation byte. If an invalid byte is detected, -2 is returned. -function utf8CheckByte(byte) { - if (byte <= 0x7F) return 0;else if (byte >> 5 === 0x06) return 2;else if (byte >> 4 === 0x0E) return 3;else if (byte >> 3 === 0x1E) return 4; - return byte >> 6 === 0x02 ? -1 : -2; -} + // `time_low` + var tl = ((msecs & 0xfffffff) * 10000 + nsecs) % 0x100000000; + b[i++] = tl >>> 24 & 0xff; + b[i++] = tl >>> 16 & 0xff; + b[i++] = tl >>> 8 & 0xff; + b[i++] = tl & 0xff; -// Checks at most 3 bytes at the end of a Buffer in order to detect an -// incomplete multi-byte UTF-8 character. The total number of bytes (2, 3, or 4) -// needed to complete the UTF-8 character (if applicable) are returned. -function utf8CheckIncomplete(self, buf, i) { - var j = buf.length - 1; - if (j < i) return 0; - var nb = utf8CheckByte(buf[j]); - if (nb >= 0) { - if (nb > 0) self.lastNeed = nb - 1; - return nb; - } - if (--j < i || nb === -2) return 0; - nb = utf8CheckByte(buf[j]); - if (nb >= 0) { - if (nb > 0) self.lastNeed = nb - 2; - return nb; - } - if (--j < i || nb === -2) return 0; - nb = utf8CheckByte(buf[j]); - if (nb >= 0) { - if (nb > 0) { - if (nb === 2) nb = 0;else self.lastNeed = nb - 3; - } - return nb; - } - return 0; -} + // `time_mid` + var tmh = (msecs / 0x100000000 * 10000) & 0xfffffff; + b[i++] = tmh >>> 8 & 0xff; + b[i++] = tmh & 0xff; -// Validates as many continuation bytes for a multi-byte UTF-8 character as -// needed or are available. If we see a non-continuation byte where we expect -// one, we "replace" the validated continuation bytes we've seen so far with -// a single UTF-8 replacement character ('\ufffd'), to match v8's UTF-8 decoding -// behavior. The continuation byte check is included three times in the case -// where all of the continuation bytes for a character exist in the same buffer. -// It is also done this way as a slight performance increase instead of using a -// loop. -function utf8CheckExtraBytes(self, buf, p) { - if ((buf[0] & 0xC0) !== 0x80) { - self.lastNeed = 0; - return '\ufffd'; - } - if (self.lastNeed > 1 && buf.length > 1) { - if ((buf[1] & 0xC0) !== 0x80) { - self.lastNeed = 1; - return '\ufffd'; - } - if (self.lastNeed > 2 && buf.length > 2) { - if ((buf[2] & 0xC0) !== 0x80) { - self.lastNeed = 2; - return '\ufffd'; - } - } + // `time_high_and_version` + b[i++] = tmh >>> 24 & 0xf | 0x10; // include version + b[i++] = tmh >>> 16 & 0xff; + + // `clock_seq_hi_and_reserved` (Per 4.2.2 - include variant) + b[i++] = clockseq >>> 8 | 0x80; + + // `clock_seq_low` + b[i++] = clockseq & 0xff; + + // `node` + for (var n = 0; n < 6; ++n) { + b[i + n] = node[n]; } + + return buf ? buf : bytesToUuid(b); } -// Attempts to complete a multi-byte UTF-8 character using bytes from a Buffer. -function utf8FillLast(buf) { - var p = this.lastTotal - this.lastNeed; - var r = utf8CheckExtraBytes(this, buf, p); - if (r !== undefined) return r; - if (this.lastNeed <= buf.length) { - buf.copy(this.lastChar, p, 0, this.lastNeed); - return this.lastChar.toString(this.encoding, 0, this.lastTotal); +module.exports = v1; + +},{"./lib/bytesToUuid":422,"./lib/rng":423}],425:[function(require,module,exports){ +var rng = require('./lib/rng'); +var bytesToUuid = require('./lib/bytesToUuid'); + +function v4(options, buf, offset) { + var i = buf && offset || 0; + + if (typeof(options) == 'string') { + buf = options === 'binary' ? new Array(16) : null; + options = null; } - buf.copy(this.lastChar, p, 0, buf.length); - this.lastNeed -= buf.length; -} + options = options || {}; -// Returns all complete UTF-8 characters in a Buffer. If the Buffer ended on a -// partial character, the character's bytes are buffered until the required -// number of bytes are available. -function utf8Text(buf, i) { - var total = utf8CheckIncomplete(this, buf, i); - if (!this.lastNeed) return buf.toString('utf8', i); - this.lastTotal = total; - var end = buf.length - (total - this.lastNeed); - buf.copy(this.lastChar, 0, end); - return buf.toString('utf8', i, end); -} + var rnds = options.random || (options.rng || rng)(); -// For UTF-8, a replacement character is added when ending on a partial -// character. -function utf8End(buf) { - var r = buf && buf.length ? this.write(buf) : ''; - if (this.lastNeed) return r + '\ufffd'; - return r; -} + // Per 4.4, set bits for version and `clock_seq_hi_and_reserved` + rnds[6] = (rnds[6] & 0x0f) | 0x40; + rnds[8] = (rnds[8] & 0x3f) | 0x80; -// UTF-16LE typically needs two bytes per character, but even if we have an even -// number of bytes available, we need to check if we end on a leading/high -// surrogate. In that case, we need to wait for the next two bytes in order to -// decode the last character properly. -function utf16Text(buf, i) { - if ((buf.length - i) % 2 === 0) { - var r = buf.toString('utf16le', i); - if (r) { - var c = r.charCodeAt(r.length - 1); - if (c >= 0xD800 && c <= 0xDBFF) { - this.lastNeed = 2; - this.lastTotal = 4; - this.lastChar[0] = buf[buf.length - 2]; - this.lastChar[1] = buf[buf.length - 1]; - return r.slice(0, -1); - } + // Copy bytes to buffer, if provided + if (buf) { + for (var ii = 0; ii < 16; ++ii) { + buf[i + ii] = rnds[ii]; } - return r; } - this.lastNeed = 1; - this.lastTotal = 2; - this.lastChar[0] = buf[buf.length - 1]; - return buf.toString('utf16le', i, buf.length - 1); -} -// For UTF-16LE we do not explicitly append special replacement characters if we -// end on a partial character, we simply let v8 handle that. -function utf16End(buf) { - var r = buf && buf.length ? this.write(buf) : ''; - if (this.lastNeed) { - var end = this.lastTotal - this.lastNeed; - return r + this.lastChar.toString('utf16le', 0, end); - } - return r; + return buf || bytesToUuid(rnds); } -function base64Text(buf, i) { - var n = (buf.length - i) % 3; - if (n === 0) return buf.toString('base64', i); - this.lastNeed = 3 - n; - this.lastTotal = 3; - if (n === 1) { - this.lastChar[0] = buf[buf.length - 1]; - } else { - this.lastChar[0] = buf[buf.length - 2]; - this.lastChar[1] = buf[buf.length - 1]; - } - return buf.toString('base64', i, buf.length - n); -} +module.exports = v4; -function base64End(buf) { - var r = buf && buf.length ? this.write(buf) : ''; - if (this.lastNeed) return r + this.lastChar.toString('base64', 0, 3 - this.lastNeed); - return r; -} +},{"./lib/bytesToUuid":422,"./lib/rng":423}],426:[function(require,module,exports){ +var indexOf = function (xs, item) { + if (xs.indexOf) return xs.indexOf(item); + else for (var i = 0; i < xs.length; i++) { + if (xs[i] === item) return i; + } + return -1; +}; +var Object_keys = function (obj) { + if (Object.keys) return Object.keys(obj) + else { + var res = []; + for (var key in obj) res.push(key) + return res; + } +}; -// Pass bytes on through for single-byte encodings (e.g. ascii, latin1, hex) -function simpleWrite(buf) { - return buf.toString(this.encoding); -} +var forEach = function (xs, fn) { + if (xs.forEach) return xs.forEach(fn) + else for (var i = 0; i < xs.length; i++) { + fn(xs[i], i, xs); + } +}; -function simpleEnd(buf) { - return buf && buf.length ? this.write(buf) : ''; -} -},{"safe-buffer":404}],416:[function(require,module,exports){ -(function (global){(function (){ +var defineProp = (function() { + try { + Object.defineProperty({}, '_', {}); + return function(obj, name, value) { + Object.defineProperty(obj, name, { + writable: true, + enumerable: false, + configurable: true, + value: value + }) + }; + } catch(e) { + return function(obj, name, value) { + obj[name] = value; + }; + } +}()); -/** - * Module exports. - */ +var globals = ['Array', 'Boolean', 'Date', 'Error', 'EvalError', 'Function', +'Infinity', 'JSON', 'Math', 'NaN', 'Number', 'Object', 'RangeError', +'ReferenceError', 'RegExp', 'String', 'SyntaxError', 'TypeError', 'URIError', +'decodeURI', 'decodeURIComponent', 'encodeURI', 'encodeURIComponent', 'escape', +'eval', 'isFinite', 'isNaN', 'parseFloat', 'parseInt', 'undefined', 'unescape']; -module.exports = deprecate; +function Context() {} +Context.prototype = {}; -/** - * Mark that a method should not be used. - * Returns a modified function which warns once by default. - * - * If `localStorage.noDeprecation = true` is set, then it is a no-op. - * - * If `localStorage.throwDeprecation = true` is set, then deprecated functions - * will throw an Error when invoked. - * - * If `localStorage.traceDeprecation = true` is set, then deprecated functions - * will invoke `console.trace()` instead of `console.error()`. - * - * @param {Function} fn - the function to deprecate - * @param {String} msg - the string to print to the console when `fn` is invoked - * @returns {Function} a new "deprecated" version of `fn` - * @api public - */ +var Script = exports.Script = function NodeScript (code) { + if (!(this instanceof Script)) return new Script(code); + this.code = code; +}; -function deprecate (fn, msg) { - if (config('noDeprecation')) { - return fn; - } +Script.prototype.runInContext = function (context) { + if (!(context instanceof Context)) { + throw new TypeError("needs a 'context' argument."); + } + + var iframe = document.createElement('iframe'); + if (!iframe.style) iframe.style = {}; + iframe.style.display = 'none'; + + document.body.appendChild(iframe); + + var win = iframe.contentWindow; + var wEval = win.eval, wExecScript = win.execScript; + + if (!wEval && wExecScript) { + // win.eval() magically appears when this is called in IE: + wExecScript.call(win, 'null'); + wEval = win.eval; + } + + forEach(Object_keys(context), function (key) { + win[key] = context[key]; + }); + forEach(globals, function (key) { + if (context[key]) { + win[key] = context[key]; + } + }); + + var winKeys = Object_keys(win); + + var res = wEval.call(win, this.code); + + forEach(Object_keys(win), function (key) { + // Avoid copying circular objects like `top` and `window` by only + // updating existing context properties or new properties in the `win` + // that was only introduced after the eval. + if (key in context || indexOf(winKeys, key) === -1) { + context[key] = win[key]; + } + }); - var warned = false; - function deprecated() { - if (!warned) { - if (config('throwDeprecation')) { - throw new Error(msg); - } else if (config('traceDeprecation')) { - console.trace(msg); - } else { - console.warn(msg); - } - warned = true; + forEach(globals, function (key) { + if (!(key in context)) { + defineProp(context, key, win[key]); + } + }); + + document.body.removeChild(iframe); + + return res; +}; + +Script.prototype.runInThisContext = function () { + return eval(this.code); // maybe... +}; + +Script.prototype.runInNewContext = function (context) { + var ctx = Script.createContext(context); + var res = this.runInContext(ctx); + + if (context) { + forEach(Object_keys(ctx), function (key) { + context[key] = ctx[key]; + }); } - return fn.apply(this, arguments); - } - return deprecated; -} + return res; +}; -/** - * Checks `localStorage` for boolean values for the given `name`. - * - * @param {String} name - * @returns {Boolean} - * @api private - */ +forEach(Object_keys(Script.prototype), function (name) { + exports[name] = Script[name] = function (code) { + var s = Script(code); + return s[name].apply(s, [].slice.call(arguments, 1)); + }; +}); -function config (name) { - // accessing global.localStorage can trigger a DOMException in sandboxed iframes - try { - if (!global.localStorage) return false; - } catch (_) { - return false; - } - var val = global.localStorage[name]; - if (null == val) return false; - return String(val).toLowerCase() === 'true'; -} +exports.isContext = function (context) { + return context instanceof Context; +}; -}).call(this)}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{}],417:[function(require,module,exports){ +exports.createScript = function (code) { + return exports.Script(code); +}; + +exports.createContext = Script.createContext = function (context) { + var copy = new Context(); + if(typeof context === 'object') { + forEach(Object_keys(context), function (key) { + copy[key] = context[key]; + }); + } + return copy; +}; + +},{}],427:[function(require,module,exports){ (function (global){(function (){ 'use strict'; @@ -71976,7 +71794,7 @@ module.exports = function whichTypedArray(value) { }; }).call(this)}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"available-typed-arrays":89,"call-bind":158,"call-bind/callBound":157,"for-each":214,"gopd":218,"has-tostringtag/shams":223}],418:[function(require,module,exports){ +},{"available-typed-arrays":84,"call-bind":121,"call-bind/callBound":120,"for-each":175,"gopd":179,"has-tostringtag/shams":184}],428:[function(require,module,exports){ 'use strict'; module.exports = function () { diff --git a/src/assets/resources/formats.json b/src/assets/resources/formats.json index c3728c1..bb378d5 100644 --- a/src/assets/resources/formats.json +++ b/src/assets/resources/formats.json @@ -13,7 +13,8 @@ "MKM", "OTJ", "BIG", - "BLB" + "BLB", + "DSK" ], "filterSets": [ "DMU", @@ -26,7 +27,8 @@ "MKM", "OTJ", "BIG", - "BLB" + "BLB", + "DSK" ], "bannedTitleIds": [ 3142 @@ -60,7 +62,8 @@ "MKM", "OTJ", "BIG", - "BLB" + "BLB", + "DSK" ], "filterSets": [ "DMU", @@ -73,7 +76,8 @@ "MKM", "OTJ", "BIG", - "BLB" + "BLB", + "DSK" ], "bannedTitleIds": [ 352252, @@ -150,7 +154,10 @@ "OTJ", "BIG", "Y24_OTJ", - "BLB" + "BLB", + "Y25", + "Y25_BLB", + "DSK" ], "filterSets": [ "ANB", @@ -165,7 +172,10 @@ "OTJ", "BIG", "Y24_OTJ", - "BLB" + "BLB", + "Y25_BLB", + "Y25", + "DSK" ], "bannedTitleIds": [], "suspendedTitleIds": [], @@ -241,6 +251,7 @@ "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -367,7 +378,9 @@ "M3C", "BLB", "BLC", - "DSK" + "DSK", + "Y25", + "Y25_BLB" ], "filterSets": [ "2XM", @@ -402,6 +415,7 @@ "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -528,7 +542,9 @@ "M3C", "BLB", "BLC", - "DSK" + "DSK", + "Y25_BLB", + "Y25" ], "bannedTitleIds": [], "suspendedTitleIds": [], @@ -2266,7 +2282,10 @@ "OTJ", "BIG", "Y24_OTJ", - "BLB" + "BLB", + "Y25", + "Y25_BLB", + "DSK" ], "filterSets": [ "ANB", @@ -2281,7 +2300,10 @@ "OTJ", "BIG", "Y24_OTJ", - "BLB" + "BLB", + "Y25_BLB", + "Y25", + "DSK" ], "bannedTitleIds": [ 488856, @@ -2339,6 +2361,7 @@ "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -2465,7 +2488,9 @@ "M3C", "BLB", "BLC", - "DSK" + "DSK", + "Y25", + "Y25_BLB" ], "filterSets": [ "2XM", @@ -2500,6 +2525,7 @@ "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -2626,7 +2652,9 @@ "M3C", "BLB", "BLC", - "DSK" + "DSK", + "Y25_BLB", + "Y25" ], "bannedTitleIds": [ 21415, @@ -2690,6 +2718,7 @@ "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -2816,7 +2845,9 @@ "M3C", "BLB", "BLC", - "DSK" + "DSK", + "Y25", + "Y25_BLB" ], "filterSets": [ "2XM", @@ -2851,6 +2882,7 @@ "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -2977,7 +3009,9 @@ "M3C", "BLB", "BLC", - "DSK" + "DSK", + "Y25_BLB", + "Y25" ], "bannedTitleIds": [ 351741, @@ -3062,6 +3096,7 @@ "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -3188,7 +3223,9 @@ "M3C", "BLB", "BLC", - "DSK" + "DSK", + "Y25", + "Y25_BLB" ], "filterSets": [ "2XM", @@ -3223,6 +3260,7 @@ "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -3349,7 +3387,9 @@ "M3C", "BLB", "BLC", - "DSK" + "DSK", + "Y25_BLB", + "Y25" ], "bannedTitleIds": [ 21415, @@ -3409,6 +3449,7 @@ "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -3535,7 +3576,9 @@ "M3C", "BLB", "BLC", - "DSK" + "DSK", + "Y25", + "Y25_BLB" ], "filterSets": [ "2XM", @@ -3570,6 +3613,7 @@ "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -3696,7 +3740,9 @@ "M3C", "BLB", "BLC", - "DSK" + "DSK", + "Y25_BLB", + "Y25" ], "bannedTitleIds": [ 351741, @@ -3773,6 +3819,7 @@ "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -3899,7 +3946,9 @@ "M3C", "BLB", "BLC", - "DSK" + "DSK", + "Y25", + "Y25_BLB" ], "filterSets": [ "2XM", @@ -3934,6 +3983,7 @@ "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -4060,7 +4110,9 @@ "M3C", "BLB", "BLC", - "DSK" + "DSK", + "Y25_BLB", + "Y25" ], "bannedTitleIds": [ 351741, @@ -4135,6 +4187,7 @@ "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -4261,7 +4314,9 @@ "M3C", "BLB", "BLC", - "DSK" + "DSK", + "Y25", + "Y25_BLB" ], "filterSets": [ "2XM", @@ -4296,6 +4351,7 @@ "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -4422,7 +4478,9 @@ "M3C", "BLB", "BLC", - "DSK" + "DSK", + "Y25_BLB", + "Y25" ], "bannedTitleIds": [ 351741, @@ -4586,7 +4644,10 @@ "OTJ", "BIG", "Y24_OTJ", - "BLB" + "BLB", + "Y25", + "Y25_BLB", + "DSK" ], "filterSets": [ "ANB", @@ -4601,7 +4662,10 @@ "OTJ", "BIG", "Y24_OTJ", - "BLB" + "BLB", + "Y25_BLB", + "Y25", + "DSK" ], "bannedTitleIds": [], "suspendedTitleIds": [], @@ -4677,6 +4741,7 @@ "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -4803,7 +4868,9 @@ "M3C", "BLB", "BLC", - "DSK" + "DSK", + "Y25", + "Y25_BLB" ], "filterSets": [ "2XM", @@ -4838,6 +4905,7 @@ "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -4964,7 +5032,9 @@ "M3C", "BLB", "BLC", - "DSK" + "DSK", + "Y25_BLB", + "Y25" ], "bannedTitleIds": [ 487194, @@ -5046,6 +5116,7 @@ "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -5172,7 +5243,9 @@ "M3C", "BLB", "BLC", - "DSK" + "DSK", + "Y25", + "Y25_BLB" ], "filterSets": [ "2XM", @@ -5207,6 +5280,7 @@ "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -5333,7 +5407,9 @@ "M3C", "BLB", "BLC", - "DSK" + "DSK", + "Y25_BLB", + "Y25" ], "bannedTitleIds": [ 351741, @@ -5433,6 +5509,7 @@ "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -5559,7 +5636,9 @@ "M3C", "BLB", "BLC", - "DSK" + "DSK", + "Y25", + "Y25_BLB" ], "filterSets": [ "2XM", @@ -5594,6 +5673,7 @@ "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -5720,7 +5800,9 @@ "M3C", "BLB", "BLC", - "DSK" + "DSK", + "Y25_BLB", + "Y25" ], "bannedTitleIds": [ 12194, @@ -5776,6 +5858,7 @@ "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -5902,7 +5985,9 @@ "M3C", "BLB", "BLC", - "DSK" + "DSK", + "Y25", + "Y25_BLB" ], "filterSets": [ "2XM", @@ -5937,6 +6022,7 @@ "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -6063,7 +6149,9 @@ "M3C", "BLB", "BLC", - "DSK" + "DSK", + "Y25_BLB", + "Y25" ], "bannedTitleIds": [ 487194, @@ -6146,7 +6234,8 @@ "MKM", "OTJ", "BIG", - "BLB" + "BLB", + "DSK" ], "filterSets": [ "DMU", @@ -6159,7 +6248,8 @@ "MKM", "OTJ", "BIG", - "BLB" + "BLB", + "DSK" ], "bannedTitleIds": [], "suspendedTitleIds": [], @@ -6215,7 +6305,10 @@ "OTJ", "BIG", "Y24_OTJ", - "BLB" + "BLB", + "Y25", + "Y25_BLB", + "DSK" ], "filterSets": [ "ANB", @@ -6230,7 +6323,10 @@ "OTJ", "BIG", "Y24_OTJ", - "BLB" + "BLB", + "Y25_BLB", + "Y25", + "DSK" ], "bannedTitleIds": [ 3142, @@ -6293,7 +6389,10 @@ "OTJ", "BIG", "Y24_OTJ", - "BLB" + "BLB", + "Y25", + "Y25_BLB", + "DSK" ], "filterSets": [ "ANB", @@ -6308,7 +6407,10 @@ "OTJ", "BIG", "Y24_OTJ", - "BLB" + "BLB", + "Y25_BLB", + "Y25", + "DSK" ], "bannedTitleIds": [ 181902, @@ -6366,6 +6468,7 @@ "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -6492,7 +6595,9 @@ "M3C", "BLB", "BLC", - "DSK" + "DSK", + "Y25", + "Y25_BLB" ], "filterSets": [ "2XM", @@ -6527,6 +6632,7 @@ "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -6653,7 +6759,9 @@ "M3C", "BLB", "BLC", - "DSK" + "DSK", + "Y25_BLB", + "Y25" ], "bannedTitleIds": [ 351741, @@ -6773,7 +6881,10 @@ "OTJ", "BIG", "Y24_OTJ", - "BLB" + "BLB", + "Y25", + "Y25_BLB", + "DSK" ], "filterSets": [ "ANB", @@ -6788,7 +6899,10 @@ "OTJ", "BIG", "Y24_OTJ", - "BLB" + "BLB", + "Y25_BLB", + "Y25", + "DSK" ], "bannedTitleIds": [ 336370, @@ -6966,7 +7080,10 @@ "MH3", "M3C", "BLC", - "BLB" + "BLB", + "Y25", + "Y25_BLB", + "DSK" ], "filterSets": [ "2XM", @@ -7124,7 +7241,10 @@ "MH3", "M3C", "BLB", - "BLC" + "BLC", + "Y25_BLB", + "Y25", + "DSK" ], "bannedTitleIds": [], "suspendedTitleIds": [], @@ -9721,20 +9841,22 @@ { "name": "Standard_Recent", "legalSets": [ - "BLB", + "WOE", + "LCI", + "MKM", "OTJ", "BIG", - "MKM", - "LCI", - "WOE" + "BLB", + "DSK" ], "filterSets": [ - "BLB", + "WOE", + "LCI", + "MKM", "OTJ", "BIG", - "MKM", - "LCI", - "WOE" + "BLB", + "DSK" ], "bannedTitleIds": [ 557819, @@ -9812,6 +9934,7 @@ "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -9938,7 +10061,9 @@ "M3C", "BLB", "BLC", - "DSK" + "DSK", + "Y25", + "Y25_BLB" ], "filterSets": [ "2XM", @@ -9973,6 +10098,7 @@ "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -10099,7 +10225,9 @@ "M3C", "BLB", "BLC", - "DSK" + "DSK", + "Y25_BLB", + "Y25" ], "bannedTitleIds": [], "suspendedTitleIds": [], @@ -10244,7 +10372,8 @@ "MKM", "BIG", "OTJ", - "BLB" + "BLB", + "DSK" ], "filterSets": [ "AER", @@ -10304,9 +10433,11 @@ "BIG", "OTJ", "SPG", - "BLB" + "BLB", + "DSK" ], "bannedTitleIds": [ + 737878, 38310, 25409, 488847, @@ -10324,6 +10455,7 @@ 414166, 24837, 38497, + 351897, 336891, 477509, 420184, @@ -11983,7 +12115,7 @@ "AllowedCommanderTitleIds": [] }, { - "name": "HistoricBrawlWithAllowList_20240514", + "name": "HistoricBrawlWithAllowList_20240903", "legalSets": [ "2XM", "2X2", @@ -12017,6 +12149,7 @@ "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -12143,7 +12276,9 @@ "M3C", "BLB", "BLC", - "DSK" + "DSK", + "Y25", + "Y25_BLB" ], "filterSets": [ "2XM", @@ -12178,6 +12313,7 @@ "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -12304,13 +12440,16 @@ "M3C", "BLB", "BLC", - "DSK" + "DSK", + "Y25_BLB", + "Y25" ], "bannedTitleIds": [ 351741, 24405, 21415, 12194, + 760671, 427904, 352244, 76334, @@ -12319,6 +12458,7 @@ 24870, 1679, 414260, + 279584, 19674, 5159, 31558, @@ -12346,68 +12486,23 @@ "sideboardBehavior": "CompanionOnly", "useRebalancedCards": true, "AllowedCommanderTitleIds": [ - 756700, - 810848, - 756704, - 756724, - 756728, - 756732, - 756582, - 756735, - 756432, - 756746, - 810852, - 756750, - 756753, - 756200, - 756065, - 756206, - 756760, - 756339, - 793860, - 810815, - 756768, - 756989, - 756776, - 810807, - 756779, - 756351, - 756784, - 756791, - 756795, - 756799, - 756802, - 756805, - 756501, - 756810, - 756813, - 756816, - 810918, - 756820, - 756824, - 793863, - 756838, - 810854, - 756843, - 756852, - 810858, - 756859, - 756864, - 793866, - 756876, - 810844, + 763453, + 811718, + 814447, + 566475, + 811743, + 546509, + 811751, + 557748, + 702876, + 3894, 756764, - 756409, - 756422, - 756880, - 810862, - 756889, - 756894, - 793869 + 702880, + 227265 ] }, { - "name": "DirectGameLimitedRebalanced", + "name": "HistoricBrawlWithAllowList_20240514", "legalSets": [ "2XM", "2X2", @@ -12441,6 +12536,7 @@ "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -12567,7 +12663,9 @@ "M3C", "BLB", "BLC", - "DSK" + "DSK", + "Y25", + "Y25_BLB" ], "filterSets": [ "2XM", @@ -12602,6 +12700,7 @@ "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -12728,74 +12827,39 @@ "M3C", "BLB", "BLC", - "DSK" - ], - "bannedTitleIds": [], - "suspendedTitleIds": [], - "allowedTitleIds": [], - "supressedTitleIds": [], - "individualCardQuotas": {}, - "cardCountRestriction": "UnrestrictedCardCounts", - "FormatType": "Constructed", - "mainDeckQuota": { - "min": 40, - "max": 250 - }, - "sideBoardQuota": { - "max": 250 - }, - "useRebalancedCards": true, - "AllowedCommanderTitleIds": [] - }, - { - "name": "Brawl", - "legalSets": [ - "DMU", - "BRO", - "ONE", - "MOM", - "MAT", - "WOE", - "LCI", - "MKM", - "OTJ", - "BIG", - "BLB" - ], - "filterSets": [ - "DMU", - "BRO", - "ONE", - "MOM", - "MAT", - "WOE", - "LCI", - "MKM", - "OTJ", - "BIG", - "BLB" + "DSK", + "Y25_BLB", + "Y25" ], "bannedTitleIds": [ + 351741, + 24405, + 21415, + 12194, + 427904, + 352244, + 76334, + 428590, + 8628, + 24870, + 1679, + 414260, + 19674, 5159, - 3142, - 3142, - 3142, - 3142 + 31558, + 174019, + 26717, + 46453 ], "suspendedTitleIds": [], - "allowedTitleIds": [ - 414587, - 10756 - ], - "supressedTitleIds": [ - 3142 - ], + "allowedTitleIds": [], + "supressedTitleIds": [], "individualCardQuotas": {}, "cardCountRestriction": "Singleton", "FormatType": "Constructed", "mainDeckQuota": { - "min": 59, - "max": 59 + "min": 99, + "max": 99 }, "sideBoardQuota": { "max": 1 @@ -12805,10 +12869,70 @@ "max": 1 }, "sideboardBehavior": "CompanionOnly", - "AllowedCommanderTitleIds": [] + "useRebalancedCards": true, + "AllowedCommanderTitleIds": [ + 756700, + 810848, + 756704, + 756724, + 756728, + 756732, + 756582, + 756735, + 756432, + 756746, + 810852, + 756750, + 756753, + 756200, + 756065, + 756206, + 756760, + 756339, + 793860, + 810815, + 756768, + 756989, + 756776, + 810807, + 756779, + 756351, + 756784, + 756791, + 756795, + 756799, + 756802, + 756805, + 756501, + 756810, + 756813, + 756816, + 810918, + 756820, + 756824, + 793863, + 756838, + 810854, + 756843, + 756852, + 810858, + 756859, + 756864, + 793866, + 756876, + 810844, + 756764, + 756409, + 756422, + 756880, + 810862, + 756889, + 756894, + 793869 + ] }, { - "name": "HistoricShakeup", + "name": "DirectGameLimitedRebalanced", "legalSets": [ "2XM", "2X2", @@ -12842,6 +12966,7 @@ "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -12968,7 +13093,9 @@ "M3C", "BLB", "BLC", - "DSK" + "DSK", + "Y25", + "Y25_BLB" ], "filterSets": [ "2XM", @@ -13003,6 +13130,7 @@ "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -13129,69 +13257,91 @@ "M3C", "BLB", "BLC", - "DSK" - ], - "bannedTitleIds": [ - 351741, - 429999, - 272772, - 10522, - 413858, - 21415, - 47395, - 760, - 4023, - 12194, - 566299, - 497307, - 487228, - 488847, - 39661, - 352244, - 227304, - 558133, - 419691, - 28117, - 1251, - 2688, - 352248, - 428587, - 6167, - 489202, - 434348, - 24870, - 1679, - 336840, - 414260, - 414166, - 2904, - 227513, - 419870, - 17643, - 477509, - 2183, - 420429, - 352113, - 279929, - 428552 + "DSK", + "Y25_BLB", + "Y25" ], + "bannedTitleIds": [], "suspendedTitleIds": [], "allowedTitleIds": [], "supressedTitleIds": [], "individualCardQuotas": {}, + "cardCountRestriction": "UnrestrictedCardCounts", "FormatType": "Constructed", "mainDeckQuota": { - "min": 60, + "min": 40, "max": 250 }, "sideBoardQuota": { - "max": 7 + "max": 250 }, "useRebalancedCards": true, "AllowedCommanderTitleIds": [] }, { - "name": "HistoricShakeup3", + "name": "Brawl", + "legalSets": [ + "DMU", + "BRO", + "ONE", + "MOM", + "MAT", + "WOE", + "LCI", + "MKM", + "OTJ", + "BIG", + "BLB", + "DSK" + ], + "filterSets": [ + "DMU", + "BRO", + "ONE", + "MOM", + "MAT", + "WOE", + "LCI", + "MKM", + "OTJ", + "BIG", + "BLB", + "DSK" + ], + "bannedTitleIds": [ + 5159, + 3142, + 3142, + 3142, + 3142 + ], + "suspendedTitleIds": [], + "allowedTitleIds": [ + 414587, + 10756 + ], + "supressedTitleIds": [ + 3142 + ], + "individualCardQuotas": {}, + "cardCountRestriction": "Singleton", + "FormatType": "Constructed", + "mainDeckQuota": { + "min": 59, + "max": 59 + }, + "sideBoardQuota": { + "max": 1 + }, + "commandZoneQuota": { + "min": 1, + "max": 1 + }, + "sideboardBehavior": "CompanionOnly", + "AllowedCommanderTitleIds": [] + }, + { + "name": "HistoricShakeup", "legalSets": [ "2XM", "2X2", @@ -13225,6 +13375,7 @@ "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -13351,7 +13502,9 @@ "M3C", "BLB", "BLC", - "DSK" + "DSK", + "Y25", + "Y25_BLB" ], "filterSets": [ "2XM", @@ -13386,6 +13539,7 @@ "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -13512,56 +13666,53 @@ "M3C", "BLB", "BLC", - "DSK" + "DSK", + "Y25_BLB", + "Y25" ], "bannedTitleIds": [ - 173532, 351741, - 413974, - 413710, - 413986, + 429999, + 272772, + 10522, + 413858, + 21415, 47395, - 433909, - 181639, - 414227, - 229682, - 413992, - 477884, + 760, + 4023, + 12194, + 566299, + 497307, + 487228, + 488847, + 39661, 352244, - 414011, - 5526, - 336177, - 351874, + 227304, + 558133, + 419691, 28117, - 279794, - 43442, + 1251, 2688, - 433696, - 437015, + 352248, 428587, + 6167, + 489202, 434348, - 336370, - 336832, + 24870, 1679, - 336718, + 336840, 414260, 414166, - 414172, - 477049, - 125065, - 3236, + 2904, 227513, - 336891, + 419870, 17643, 477509, - 46453, + 2183, 420429, 352113, 279929, - 428552, - 414418, - 428610, - 428554 + 428552 ], "suspendedTitleIds": [], "allowedTitleIds": [], @@ -13579,76 +13730,7 @@ "AllowedCommanderTitleIds": [] }, { - "name": "Strixhaven", - "legalSets": [ - "STX" - ], - "filterSets": [ - "STX" - ], - "bannedTitleIds": [], - "suspendedTitleIds": [], - "allowedTitleIds": [], - "supressedTitleIds": [], - "individualCardQuotas": {}, - "FormatType": "Constructed", - "mainDeckQuota": { - "min": 60, - "max": 250 - }, - "sideBoardQuota": { - "max": 7 - }, - "AllowedCommanderTitleIds": [] - }, - { - "name": "StreetsOfNewCapenna", - "legalSets": [ - "SNC" - ], - "filterSets": [ - "SNC" - ], - "bannedTitleIds": [], - "suspendedTitleIds": [], - "allowedTitleIds": [], - "supressedTitleIds": [], - "individualCardQuotas": {}, - "FormatType": "Constructed", - "mainDeckQuota": { - "min": 60, - "max": 250 - }, - "sideBoardQuota": { - "max": 7 - }, - "AllowedCommanderTitleIds": [] - }, - { - "name": "BLB", - "legalSets": [ - "BLB" - ], - "filterSets": [ - "BLB" - ], - "bannedTitleIds": [], - "suspendedTitleIds": [], - "allowedTitleIds": [], - "supressedTitleIds": [], - "individualCardQuotas": {}, - "FormatType": "Constructed", - "mainDeckQuota": { - "min": 60, - "max": 250 - }, - "sideBoardQuota": { - "max": 15 - }, - "AllowedCommanderTitleIds": [] - }, - { - "name": "TraditionalTimeless", + "name": "HistoricShakeup3", "legalSets": [ "2XM", "2X2", @@ -13682,6 +13764,7 @@ "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -13789,6 +13872,7 @@ "LCC", "Y24_LCI", "MKM", + "OTJ", "Y24_MKM", "SPG", "KLD", @@ -13797,15 +13881,19 @@ "C16", "DIS", "DDU", - "BIG", + "MH3", "OTP", - "OTJ", + "OTC", + "BIG", "OTC", "Y24_OTJ", "MH3", "M3C", + "BLB", "BLC", - "BLB" + "DSK", + "Y25", + "Y25_BLB" ], "filterSets": [ "2XM", @@ -13840,6 +13928,7 @@ "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -13947,6 +14036,7 @@ "LCC", "Y24_LCI", "MKM", + "OTJ", "Y24_MKM", "SPG", "KLD", @@ -13955,50 +14045,137 @@ "C16", "DIS", "DDU", - "BIG", + "MH3", "OTP", - "OTJ", + "OTC", + "BIG", "OTC", "Y24_OTJ", "MH3", "M3C", "BLB", - "BLC" + "BLC", + "DSK", + "Y25_BLB", + "Y25" + ], + "bannedTitleIds": [ + 173532, + 351741, + 413974, + 413710, + 413986, + 47395, + 433909, + 181639, + 414227, + 229682, + 413992, + 477884, + 352244, + 414011, + 5526, + 336177, + 351874, + 28117, + 279794, + 43442, + 2688, + 433696, + 437015, + 428587, + 434348, + 336370, + 336832, + 1679, + 336718, + 414260, + 414166, + 414172, + 477049, + 125065, + 3236, + 227513, + 336891, + 17643, + 477509, + 46453, + 420429, + 352113, + 279929, + 428552, + 414418, + 428610, + 428554 + ], + "suspendedTitleIds": [], + "allowedTitleIds": [], + "supressedTitleIds": [], + "individualCardQuotas": {}, + "FormatType": "Constructed", + "mainDeckQuota": { + "min": 60, + "max": 250 + }, + "sideBoardQuota": { + "max": 7 + }, + "useRebalancedCards": true, + "AllowedCommanderTitleIds": [] + }, + { + "name": "Strixhaven", + "legalSets": [ + "STX" + ], + "filterSets": [ + "STX" ], "bannedTitleIds": [], "suspendedTitleIds": [], "allowedTitleIds": [], "supressedTitleIds": [], - "individualCardQuotas": { - "21415": { - "max": 1 - }, - "12194": { - "max": 1 - }, - "477509": { - "max": 1 - } + "individualCardQuotas": {}, + "FormatType": "Constructed", + "mainDeckQuota": { + "min": 60, + "max": 250 }, + "sideBoardQuota": { + "max": 7 + }, + "AllowedCommanderTitleIds": [] + }, + { + "name": "StreetsOfNewCapenna", + "legalSets": [ + "SNC" + ], + "filterSets": [ + "SNC" + ], + "bannedTitleIds": [], + "suspendedTitleIds": [], + "allowedTitleIds": [], + "supressedTitleIds": [], + "individualCardQuotas": {}, "FormatType": "Constructed", "mainDeckQuota": { "min": 60, "max": 250 }, "sideBoardQuota": { - "max": 15 + "max": 7 }, "AllowedCommanderTitleIds": [] }, { - "name": "OTJ", + "name": "BLB", "legalSets": [ - "OTJ", - "BIG" + "BLB" ], "filterSets": [ - "OTJ", - "BIG" + "BLB" ], "bannedTitleIds": [], "suspendedTitleIds": [], @@ -14016,7 +14193,7 @@ "AllowedCommanderTitleIds": [] }, { - "name": "DirectGameAlchemy", + "name": "TraditionalTimeless", "legalSets": [ "2XM", "2X2", @@ -14157,7 +14334,6 @@ "LCC", "Y24_LCI", "MKM", - "OTJ", "Y24_MKM", "SPG", "KLD", @@ -14166,16 +14342,17 @@ "C16", "DIS", "DDU", - "MH3", - "OTP", - "OTC", "BIG", + "OTP", + "OTJ", "OTC", "Y24_OTJ", "MH3", "M3C", - "BLB", "BLC", + "BLB", + "Y25", + "Y25_BLB", "DSK" ], "filterSets": [ @@ -14318,7 +14495,6 @@ "LCC", "Y24_LCI", "MKM", - "OTJ", "Y24_MKM", "SPG", "KLD", @@ -14327,22 +14503,58 @@ "C16", "DIS", "DDU", - "MH3", - "OTP", - "OTC", "BIG", + "OTP", + "OTJ", "OTC", "Y24_OTJ", "MH3", "M3C", "BLB", "BLC", + "Y25_BLB", + "Y25", "DSK" ], "bannedTitleIds": [], "suspendedTitleIds": [], "allowedTitleIds": [], "supressedTitleIds": [], + "individualCardQuotas": { + "21415": { + "max": 1 + }, + "12194": { + "max": 1 + }, + "477509": { + "max": 1 + } + }, + "FormatType": "Constructed", + "mainDeckQuota": { + "min": 60, + "max": 250 + }, + "sideBoardQuota": { + "max": 15 + }, + "AllowedCommanderTitleIds": [] + }, + { + "name": "OTJ", + "legalSets": [ + "OTJ", + "BIG" + ], + "filterSets": [ + "OTJ", + "BIG" + ], + "bannedTitleIds": [], + "suspendedTitleIds": [], + "allowedTitleIds": [], + "supressedTitleIds": [], "individualCardQuotas": {}, "FormatType": "Constructed", "mainDeckQuota": { @@ -14352,11 +14564,10 @@ "sideBoardQuota": { "max": 15 }, - "useRebalancedCards": true, "AllowedCommanderTitleIds": [] }, { - "name": "RetroHistoric", + "name": "DirectGameAlchemy", "legalSets": [ "2XM", "2X2", @@ -14390,6 +14601,7 @@ "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -14516,7 +14728,9 @@ "M3C", "BLB", "BLC", - "DSK" + "DSK", + "Y25", + "Y25_BLB" ], "filterSets": [ "2XM", @@ -14551,6 +14765,7 @@ "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -14677,24 +14892,372 @@ "M3C", "BLB", "BLC", - "DSK" - ], - "bannedTitleIds": [ - 1679 + "DSK", + "Y25_BLB", + "Y25" ], + "bannedTitleIds": [], "suspendedTitleIds": [], - "allowedTitleIds": [ - 4621, - 4518, - 16650, - 3201, - 2247, - 30406, - 174019, - 46205, - 46196, - 10756, - 181582, + "allowedTitleIds": [], + "supressedTitleIds": [], + "individualCardQuotas": {}, + "FormatType": "Constructed", + "mainDeckQuota": { + "min": 60, + "max": 250 + }, + "sideBoardQuota": { + "max": 15 + }, + "useRebalancedCards": true, + "AllowedCommanderTitleIds": [] + }, + { + "name": "RetroHistoric", + "legalSets": [ + "2XM", + "2X2", + "8ED", + "A25", + "AER", + "AFR", + "AKH", + "AKR", + "ALA", + "ANA", + "ANB", + "ARB", + "AVR", + "BFZ", + "BNG", + "C18", + "C20", + "C21", + "CC2", + "CHK", + "CM2", + "CMR", + "CONF", + "CSP", + "DAR", + "DGM", + "DKA", + "DMU", + "DST", + "DTK", + "ELD", + "EMN", + "FDN", + "FRF", + "G18", + "GRN", + "GTC", + "HBG", + "HOU", + "IKO", + "IMA", + "INV", + "ISD", + "J21", + "JMP", + "JOU", + "JUD", + "KHM", + "KLR", + "KTK", + "LGN", + "LRW", + "M10", + "M11", + "M12", + "M13", + "M14", + "M15", + "M19", + "M20", + "M21", + "MBS", + "MH1", + "MH2", + "MID", + "MMA", + "MMQ", + "MOR", + "MRD", + "NEC", + "NEO", + "NPH", + "ODY", + "OGW", + "ONS", + "ORI", + "PLC", + "RAV", + "RIX", + "RNA", + "ROE", + "RTR", + "SCG", + "SHM", + "SNC", + "SOI", + "SOK", + "SOM", + "STA", + "STX", + "THB", + "THS", + "TOR", + "TSP", + "USG", + "UMA", + "VOW", + "W17", + "WAR", + "WTH", + "WWK", + "XLN", + "Y22", + "Y23", + "ZEN", + "ZNR", + "BRO", + "BRR", + "ONE", + "SIR", + "SIS", + "MUL", + "MOM", + "MOC", + "MAT", + "LTR", + "WOE", + "WOT", + "LCI", + "AHA1", + "AHA2", + "AHA3", + "AHA4", + "AHA5", + "AHA6", + "AHA7", + "EA1", + "EA2", + "EA3", + "Y23_ONE", + "Y23_BRO", + "Y23_DMU", + "Y22_SNC", + "Y22_NEO", + "Y22_MID", + "Y24_WOE", + "Y24", + "LCC", + "Y24_LCI", + "MKM", + "OTJ", + "Y24_MKM", + "SPG", + "KLD", + "APC", + "CLB", + "C16", + "DIS", + "DDU", + "MH3", + "OTP", + "OTC", + "BIG", + "OTC", + "Y24_OTJ", + "MH3", + "M3C", + "BLB", + "BLC", + "DSK", + "Y25", + "Y25_BLB" + ], + "filterSets": [ + "2XM", + "2X2", + "8ED", + "A25", + "AER", + "AFR", + "AKH", + "AKR", + "ALA", + "ANA", + "ANB", + "ARB", + "AVR", + "BFZ", + "BNG", + "C18", + "C20", + "C21", + "CC2", + "CHK", + "CM2", + "CMR", + "CONF", + "CSP", + "DAR", + "DGM", + "DKA", + "DMU", + "DST", + "DTK", + "ELD", + "EMN", + "FDN", + "FRF", + "G18", + "GRN", + "GTC", + "HBG", + "HOU", + "IKO", + "IMA", + "INV", + "ISD", + "J21", + "JMP", + "JOU", + "JUD", + "KHM", + "KLR", + "KTK", + "LGN", + "LRW", + "M10", + "M11", + "M12", + "M13", + "M14", + "M15", + "M19", + "M20", + "M21", + "MBS", + "MH1", + "MH2", + "MID", + "MMA", + "MMQ", + "MOR", + "MRD", + "NEC", + "NEO", + "NPH", + "ODY", + "OGW", + "ONS", + "ORI", + "PLC", + "RAV", + "RIX", + "RNA", + "ROE", + "RTR", + "SCG", + "SHM", + "SNC", + "SOI", + "SOK", + "SOM", + "STA", + "STX", + "THB", + "THS", + "TOR", + "TSP", + "USG", + "UMA", + "VOW", + "W17", + "WAR", + "WTH", + "WWK", + "XLN", + "Y22", + "Y23", + "ZEN", + "ZNR", + "BRO", + "BRR", + "ONE", + "SIR", + "SIS", + "MUL", + "MOM", + "MOC", + "MAT", + "LTR", + "WOE", + "WOT", + "LCI", + "AHA1", + "AHA2", + "AHA3", + "AHA4", + "AHA5", + "AHA6", + "AHA7", + "EA1", + "EA2", + "EA3", + "Y23_ONE", + "Y23_BRO", + "Y23_DMU", + "Y22_SNC", + "Y22_NEO", + "Y22_MID", + "Y24_WOE", + "Y24", + "LCC", + "Y24_LCI", + "MKM", + "OTJ", + "Y24_MKM", + "SPG", + "KLD", + "APC", + "CLB", + "C16", + "DIS", + "DDU", + "MH3", + "OTP", + "OTC", + "BIG", + "OTC", + "Y24_OTJ", + "MH3", + "M3C", + "BLB", + "BLC", + "DSK", + "Y25_BLB", + "Y25" + ], + "bannedTitleIds": [ + 1679 + ], + "suspendedTitleIds": [], + "allowedTitleIds": [ + 4621, + 4518, + 16650, + 3201, + 2247, + 30406, + 174019, + 46205, + 46196, + 10756, + 181582, 40351, 2071, 15139, @@ -15328,7 +15891,10 @@ "OTJ", "BIG", "Y24_OTJ", - "BLB" + "BLB", + "Y25", + "Y25_BLB", + "DSK" ], "filterSets": [ "ANB", @@ -15343,7 +15909,10 @@ "OTJ", "BIG", "Y24_OTJ", - "BLB" + "BLB", + "Y25_BLB", + "Y25", + "DSK" ], "bannedTitleIds": [ 498276, @@ -15402,6 +15971,7 @@ "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -15528,7 +16098,9 @@ "M3C", "BLB", "BLC", - "DSK" + "DSK", + "Y25", + "Y25_BLB" ], "filterSets": [ "2XM", @@ -15563,6 +16135,7 @@ "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -15689,7 +16262,9 @@ "M3C", "BLB", "BLC", - "DSK" + "DSK", + "Y25_BLB", + "Y25" ], "bannedTitleIds": [ 351741, @@ -15805,7 +16380,8 @@ "MKM", "OTJ", "BIG", - "BLB" + "BLB", + "DSK" ], "filterSets": [ "DMU", @@ -15818,7 +16394,8 @@ "MKM", "OTJ", "BIG", - "BLB" + "BLB", + "DSK" ], "bannedTitleIds": [ 351741, @@ -15882,7 +16459,10 @@ "OTJ", "BIG", "Y24_OTJ", - "BLB" + "BLB", + "Y25", + "Y25_BLB", + "DSK" ], "filterSets": [ "ANB", @@ -15897,7 +16477,10 @@ "OTJ", "BIG", "Y24_OTJ", - "BLB" + "BLB", + "Y25_BLB", + "Y25", + "DSK" ], "bannedTitleIds": [], "suspendedTitleIds": [], @@ -15975,7 +16558,10 @@ "OTJ", "BIG", "Y24_OTJ", - "BLB" + "BLB", + "Y25", + "Y25_BLB", + "DSK" ], "filterSets": [ "ANB", @@ -15990,7 +16576,10 @@ "OTJ", "BIG", "Y24_OTJ", - "BLB" + "BLB", + "Y25_BLB", + "Y25", + "DSK" ], "bannedTitleIds": [ 478018, @@ -16048,6 +16637,7 @@ "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -16174,7 +16764,9 @@ "M3C", "BLB", "BLC", - "DSK" + "DSK", + "Y25", + "Y25_BLB" ], "filterSets": [ "2XM", @@ -16209,6 +16801,7 @@ "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -16335,7 +16928,9 @@ "M3C", "BLB", "BLC", - "DSK" + "DSK", + "Y25_BLB", + "Y25" ], "bannedTitleIds": [ 351741, @@ -16402,7 +16997,8 @@ "MKM", "OTJ", "BIG", - "BLB" + "BLB", + "DSK" ], "filterSets": [ "DMU", @@ -16415,7 +17011,8 @@ "MKM", "OTJ", "BIG", - "BLB" + "BLB", + "DSK" ], "bannedTitleIds": [ 352244, @@ -16542,6 +17139,7 @@ "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -16668,7 +17266,9 @@ "M3C", "BLB", "BLC", - "DSK" + "DSK", + "Y25", + "Y25_BLB" ], "filterSets": [ "2XM", @@ -16703,6 +17303,7 @@ "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -16829,7 +17430,9 @@ "M3C", "BLB", "BLC", - "DSK" + "DSK", + "Y25_BLB", + "Y25" ], "bannedTitleIds": [ 543133, @@ -16936,7 +17539,10 @@ "OTJ", "BIG", "Y24_OTJ", - "BLB" + "BLB", + "Y25", + "Y25_BLB", + "DSK" ], "filterSets": [ "ANB", @@ -16951,7 +17557,10 @@ "OTJ", "BIG", "Y24_OTJ", - "BLB" + "BLB", + "Y25_BLB", + "Y25", + "DSK" ], "bannedTitleIds": [ 701908, @@ -17010,6 +17619,7 @@ "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -17136,7 +17746,9 @@ "M3C", "BLB", "BLC", - "DSK" + "DSK", + "Y25", + "Y25_BLB" ], "filterSets": [ "2XM", @@ -17171,6 +17783,7 @@ "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -17297,7 +17910,9 @@ "M3C", "BLB", "BLC", - "DSK" + "DSK", + "Y25_BLB", + "Y25" ], "bannedTitleIds": [], "suspendedTitleIds": [], @@ -17351,6 +17966,7 @@ "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -17477,7 +18093,9 @@ "M3C", "BLB", "BLC", - "DSK" + "DSK", + "Y25", + "Y25_BLB" ], "filterSets": [ "2XM", @@ -17512,6 +18130,7 @@ "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -17638,7 +18257,9 @@ "M3C", "BLB", "BLC", - "DSK" + "DSK", + "Y25_BLB", + "Y25" ], "bannedTitleIds": [ 279584 @@ -17705,6 +18326,29 @@ }, "AllowedCommanderTitleIds": [] }, + { + "name": "DSK", + "legalSets": [ + "DSK" + ], + "filterSets": [ + "DSK" + ], + "bannedTitleIds": [], + "suspendedTitleIds": [], + "allowedTitleIds": [], + "supressedTitleIds": [], + "individualCardQuotas": {}, + "FormatType": "Constructed", + "mainDeckQuota": { + "min": 60, + "max": 250 + }, + "sideBoardQuota": { + "max": 15 + }, + "AllowedCommanderTitleIds": [] + }, { "name": "AdventuresintheForgottenRealms", "legalSets": [ @@ -17786,6 +18430,7 @@ "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -17912,7 +18557,9 @@ "M3C", "BLB", "BLC", - "DSK" + "DSK", + "Y25", + "Y25_BLB" ], "filterSets": [ "2XM", @@ -17947,6 +18594,7 @@ "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -18073,7 +18721,9 @@ "M3C", "BLB", "BLC", - "DSK" + "DSK", + "Y25_BLB", + "Y25" ], "bannedTitleIds": [ 351741, @@ -18144,7 +18794,10 @@ "OTJ", "BIG", "Y24_OTJ", - "BLB" + "BLB", + "Y25", + "Y25_BLB", + "DSK" ], "filterSets": [ "ANB", @@ -18159,7 +18812,10 @@ "OTJ", "BIG", "Y24_OTJ", - "BLB" + "BLB", + "Y25_BLB", + "Y25", + "DSK" ], "bannedTitleIds": [ 436934, @@ -18267,6 +18923,7 @@ "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -18393,7 +19050,9 @@ "M3C", "BLB", "BLC", - "DSK" + "DSK", + "Y25", + "Y25_BLB" ], "filterSets": [ "2XM", @@ -18428,6 +19087,7 @@ "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -18554,7 +19214,9 @@ "M3C", "BLB", "BLC", - "DSK" + "DSK", + "Y25_BLB", + "Y25" ], "bannedTitleIds": [ 351741, @@ -18675,7 +19337,10 @@ "OTJ", "BIG", "Y24_OTJ", - "BLB" + "BLB", + "Y25", + "Y25_BLB", + "DSK" ], "filterSets": [ "ANB", @@ -18690,7 +19355,10 @@ "OTJ", "BIG", "Y24_OTJ", - "BLB" + "BLB", + "Y25_BLB", + "Y25", + "DSK" ], "bannedTitleIds": [], "suspendedTitleIds": [], @@ -18765,7 +19433,10 @@ "OTJ", "BIG", "Y24_OTJ", - "BLB" + "BLB", + "Y25", + "Y25_BLB", + "DSK" ], "filterSets": [ "ANB", @@ -18780,7 +19451,10 @@ "OTJ", "BIG", "Y24_OTJ", - "BLB" + "BLB", + "Y25_BLB", + "Y25", + "DSK" ], "bannedTitleIds": [], "suspendedTitleIds": [], @@ -18855,7 +19529,8 @@ "MKM", "BIG", "OTJ", - "BLB" + "BLB", + "DSK" ], "filterSets": [ "AER", @@ -18915,9 +19590,11 @@ "BIG", "OTJ", "SPG", - "BLB" + "BLB", + "DSK" ], "bannedTitleIds": [ + 737878, 38310, 25409, 488847, @@ -18935,6 +19612,7 @@ 414166, 24837, 38497, + 351897, 336891, 477509, 420184, @@ -20621,16 +21299,16 @@ { "name": "3Sets", "legalSets": [ - "MKM", "OTJ", "BIG", - "BLB" + "BLB", + "DSK" ], "filterSets": [ - "MKM", "OTJ", "BIG", - "BLB" + "BLB", + "DSK" ], "bannedTitleIds": [], "suspendedTitleIds": [], @@ -20682,6 +21360,7 @@ "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -20808,7 +21487,9 @@ "M3C", "BLB", "BLC", - "DSK" + "DSK", + "Y25", + "Y25_BLB" ], "filterSets": [ "2XM", @@ -20843,6 +21524,7 @@ "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -20969,7 +21651,9 @@ "M3C", "BLB", "BLC", - "DSK" + "DSK", + "Y25_BLB", + "Y25" ], "bannedTitleIds": [], "suspendedTitleIds": [], @@ -21021,6 +21705,7 @@ "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -21147,7 +21832,9 @@ "M3C", "BLB", "BLC", - "DSK" + "DSK", + "Y25", + "Y25_BLB" ], "filterSets": [ "2XM", @@ -21182,6 +21869,7 @@ "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -21308,7 +21996,9 @@ "M3C", "BLB", "BLC", - "DSK" + "DSK", + "Y25_BLB", + "Y25" ], "bannedTitleIds": [], "suspendedTitleIds": [], @@ -21346,7 +22036,10 @@ "OTJ", "BIG", "Y24_OTJ", - "BLB" + "BLB", + "Y25", + "Y25_BLB", + "DSK" ], "filterSets": [ "ANB", @@ -21361,7 +22054,10 @@ "OTJ", "BIG", "Y24_OTJ", - "BLB" + "BLB", + "Y25_BLB", + "Y25", + "DSK" ], "bannedTitleIds": [ 3142, @@ -21401,7 +22097,10 @@ "OTJ", "BIG", "Y24_OTJ", - "BLB" + "BLB", + "Y25", + "Y25_BLB", + "DSK" ], "filterSets": [ "ANB", @@ -21416,7 +22115,10 @@ "OTJ", "BIG", "Y24_OTJ", - "BLB" + "BLB", + "Y25_BLB", + "Y25", + "DSK" ], "bannedTitleIds": [], "suspendedTitleIds": [], @@ -21502,7 +22204,8 @@ "MKM", "OTJ", "BIG", - "BLB" + "BLB", + "DSK" ], "filterSets": [ "DMU", @@ -21515,7 +22218,8 @@ "MKM", "OTJ", "BIG", - "BLB" + "BLB", + "DSK" ], "bannedTitleIds": [ 3142, @@ -21613,40 +22317,388 @@ "MKM", "OTJ", "BIG", - "BLB" + "BLB", + "DSK" + ], + "filterSets": [ + "DMU", + "BRO", + "ONE", + "MOM", + "MAT", + "WOE", + "LCI", + "MKM", + "OTJ", + "BIG", + "BLB", + "DSK" + ], + "bannedTitleIds": [ + 437805 + ], + "suspendedTitleIds": [], + "allowedTitleIds": [], + "supressedTitleIds": [], + "individualCardQuotas": {}, + "FormatType": "Constructed", + "mainDeckQuota": { + "min": 100, + "max": 250 + }, + "sideBoardQuota": { + "max": 7 + }, + "AllowedCommanderTitleIds": [] + }, + { + "name": "DirectGameLimited", + "legalSets": [ + "2XM", + "2X2", + "8ED", + "A25", + "AER", + "AFR", + "AKH", + "AKR", + "ALA", + "ANA", + "ANB", + "ARB", + "AVR", + "BFZ", + "BNG", + "C18", + "C20", + "C21", + "CC2", + "CHK", + "CM2", + "CMR", + "CONF", + "CSP", + "DAR", + "DGM", + "DKA", + "DMU", + "DST", + "DTK", + "ELD", + "EMN", + "FDN", + "FRF", + "G18", + "GRN", + "GTC", + "HBG", + "HOU", + "IKO", + "IMA", + "INV", + "ISD", + "J21", + "JMP", + "JOU", + "JUD", + "KHM", + "KLR", + "KTK", + "LGN", + "LRW", + "M10", + "M11", + "M12", + "M13", + "M14", + "M15", + "M19", + "M20", + "M21", + "MBS", + "MH1", + "MH2", + "MID", + "MMA", + "MMQ", + "MOR", + "MRD", + "NEC", + "NEO", + "NPH", + "ODY", + "OGW", + "ONS", + "ORI", + "PLC", + "RAV", + "RIX", + "RNA", + "ROE", + "RTR", + "SCG", + "SHM", + "SNC", + "SOI", + "SOK", + "SOM", + "STA", + "STX", + "THB", + "THS", + "TOR", + "TSP", + "USG", + "UMA", + "VOW", + "W17", + "WAR", + "WTH", + "WWK", + "XLN", + "Y22", + "Y23", + "ZEN", + "ZNR", + "BRO", + "BRR", + "ONE", + "SIR", + "SIS", + "MUL", + "MOM", + "MOC", + "MAT", + "LTR", + "WOE", + "WOT", + "LCI", + "AHA1", + "AHA2", + "AHA3", + "AHA4", + "AHA5", + "AHA6", + "AHA7", + "EA1", + "EA2", + "EA3", + "Y23_ONE", + "Y23_BRO", + "Y23_DMU", + "Y22_SNC", + "Y22_NEO", + "Y22_MID", + "Y24_WOE", + "Y24", + "LCC", + "Y24_LCI", + "MKM", + "OTJ", + "Y24_MKM", + "SPG", + "KLD", + "APC", + "CLB", + "C16", + "DIS", + "DDU", + "MH3", + "OTP", + "OTC", + "BIG", + "OTC", + "Y24_OTJ", + "MH3", + "M3C", + "BLB", + "BLC", + "DSK", + "Y25", + "Y25_BLB" ], "filterSets": [ + "2XM", + "2X2", + "8ED", + "A25", + "AER", + "AFR", + "AKH", + "AKR", + "ALA", + "ANA", + "ANB", + "ARB", + "AVR", + "BFZ", + "BNG", + "C18", + "C20", + "C21", + "CC2", + "CHK", + "CM2", + "CMR", + "CONF", + "CSP", + "DAR", + "DGM", + "DKA", "DMU", + "DST", + "DTK", + "ELD", + "EMN", + "FDN", + "FRF", + "G18", + "GRN", + "GTC", + "HBG", + "HOU", + "IKO", + "IMA", + "INV", + "ISD", + "J21", + "JMP", + "JOU", + "JUD", + "KHM", + "KLR", + "KTK", + "LGN", + "LRW", + "M10", + "M11", + "M12", + "M13", + "M14", + "M15", + "M19", + "M20", + "M21", + "MBS", + "MH1", + "MH2", + "MID", + "MMA", + "MMQ", + "MOR", + "MRD", + "NEC", + "NEO", + "NPH", + "ODY", + "OGW", + "ONS", + "ORI", + "PLC", + "RAV", + "RIX", + "RNA", + "ROE", + "RTR", + "SCG", + "SHM", + "SNC", + "SOI", + "SOK", + "SOM", + "STA", + "STX", + "THB", + "THS", + "TOR", + "TSP", + "USG", + "UMA", + "VOW", + "W17", + "WAR", + "WTH", + "WWK", + "XLN", + "Y22", + "Y23", + "ZEN", + "ZNR", "BRO", + "BRR", "ONE", + "SIR", + "SIS", + "MUL", "MOM", + "MOC", "MAT", + "LTR", "WOE", + "WOT", "LCI", + "AHA1", + "AHA2", + "AHA3", + "AHA4", + "AHA5", + "AHA6", + "AHA7", + "EA1", + "EA2", + "EA3", + "Y23_ONE", + "Y23_BRO", + "Y23_DMU", + "Y22_SNC", + "Y22_NEO", + "Y22_MID", + "Y24_WOE", + "Y24", + "LCC", + "Y24_LCI", "MKM", "OTJ", + "Y24_MKM", + "SPG", + "KLD", + "APC", + "CLB", + "C16", + "DIS", + "DDU", + "MH3", + "OTP", + "OTC", "BIG", - "BLB" - ], - "bannedTitleIds": [ - 437805 + "OTC", + "Y24_OTJ", + "MH3", + "M3C", + "BLB", + "BLC", + "DSK", + "Y25_BLB", + "Y25" ], + "bannedTitleIds": [], "suspendedTitleIds": [], "allowedTitleIds": [], "supressedTitleIds": [], "individualCardQuotas": {}, + "cardCountRestriction": "UnrestrictedCardCounts", "FormatType": "Constructed", "mainDeckQuota": { - "min": 100, + "min": 40, "max": 250 }, "sideBoardQuota": { - "max": 7 + "max": 250 }, "AllowedCommanderTitleIds": [] }, { - "name": "DirectGameLimited", + "name": "HistoricBrawlWithAllowList_20241008", "legalSets": [ "2XM", "2X2", @@ -21680,6 +22732,7 @@ "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -21806,7 +22859,9 @@ "M3C", "BLB", "BLC", - "DSK" + "DSK", + "Y25", + "Y25_BLB" ], "filterSets": [ "2XM", @@ -21841,6 +22896,7 @@ "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -21967,23 +23023,73 @@ "M3C", "BLB", "BLC", - "DSK" + "DSK", + "Y25_BLB", + "Y25" + ], + "bannedTitleIds": [ + 351741, + 24405, + 21415, + 12194, + 760671, + 427904, + 352244, + 76334, + 428590, + 8628, + 24870, + 1679, + 414260, + 279584, + 19674, + 5159, + 31558, + 174019, + 26717, + 46453 ], - "bannedTitleIds": [], "suspendedTitleIds": [], "allowedTitleIds": [], "supressedTitleIds": [], "individualCardQuotas": {}, - "cardCountRestriction": "UnrestrictedCardCounts", + "cardCountRestriction": "Singleton", "FormatType": "Constructed", "mainDeckQuota": { - "min": 40, - "max": 250 + "min": 99, + "max": 99 }, "sideBoardQuota": { - "max": 250 + "max": 1 }, - "AllowedCommanderTitleIds": [] + "commandZoneQuota": { + "min": 1, + "max": 1 + }, + "sideboardBehavior": "CompanionOnly", + "useRebalancedCards": true, + "AllowedCommanderTitleIds": [ + 812854, + 813005, + 813050, + 812929, + 813056, + 813170, + 813063, + 813067, + 812776, + 813081, + 813048, + 812480, + 813113, + 812395, + 812369, + 812984, + 812680, + 813121, + 813126, + 813129 + ] }, { "name": "LastCall", diff --git a/src/cards-worker/allFormats.ts b/src/cards-worker/allFormats.ts index 261a660..6fc503d 100644 --- a/src/cards-worker/allFormats.ts +++ b/src/cards-worker/allFormats.ts @@ -26,6 +26,7 @@ const formatsJson: FormatsJSON = { "OTJ", "BIG", "BLB", + "DSK", ], filterSets: [ "DMU", @@ -39,6 +40,7 @@ const formatsJson: FormatsJSON = { "OTJ", "BIG", "BLB", + "DSK", ], bannedTitleIds: [3142], suspendedTitleIds: [], @@ -46,13 +48,8 @@ const formatsJson: FormatsJSON = { supressedTitleIds: [3142], individualCardQuotas: {}, FormatType: "Constructed", - mainDeckQuota: { - min: 60, - max: 250, - }, - sideBoardQuota: { - max: 7, - }, + mainDeckQuota: { min: 60, max: 250 }, + sideBoardQuota: { max: 7 }, AllowedCommanderTitleIds: [], }, { @@ -69,6 +66,7 @@ const formatsJson: FormatsJSON = { "OTJ", "BIG", "BLB", + "DSK", ], filterSets: [ "DMU", @@ -82,6 +80,7 @@ const formatsJson: FormatsJSON = { "OTJ", "BIG", "BLB", + "DSK", ], bannedTitleIds: [ 352252, 351660, 420337, 420492, 420351, 351930, 351934, 336561, 352296, @@ -95,13 +94,8 @@ const formatsJson: FormatsJSON = { supressedTitleIds: [], individualCardQuotas: {}, FormatType: "Constructed", - mainDeckQuota: { - min: 60, - max: 250, - }, - sideBoardQuota: { - max: 7, - }, + mainDeckQuota: { min: 60, max: 250 }, + sideBoardQuota: { max: 7 }, AllowedCommanderTitleIds: [], }, { @@ -120,6 +114,9 @@ const formatsJson: FormatsJSON = { "BIG", "Y24_OTJ", "BLB", + "Y25", + "Y25_BLB", + "DSK", ], filterSets: [ "ANB", @@ -135,6 +132,9 @@ const formatsJson: FormatsJSON = { "BIG", "Y24_OTJ", "BLB", + "Y25_BLB", + "Y25", + "DSK", ], bannedTitleIds: [], suspendedTitleIds: [], @@ -142,13 +142,8 @@ const formatsJson: FormatsJSON = { supressedTitleIds: [], individualCardQuotas: {}, FormatType: "Constructed", - mainDeckQuota: { - min: 60, - max: 250, - }, - sideBoardQuota: { - max: 7, - }, + mainDeckQuota: { min: 60, max: 250 }, + sideBoardQuota: { max: 7 }, useRebalancedCards: true, AllowedCommanderTitleIds: [], }, @@ -162,13 +157,8 @@ const formatsJson: FormatsJSON = { supressedTitleIds: [], individualCardQuotas: {}, FormatType: "Constructed", - mainDeckQuota: { - min: 60, - max: 250, - }, - sideBoardQuota: { - max: 15, - }, + mainDeckQuota: { min: 60, max: 250 }, + sideBoardQuota: { max: 15 }, AllowedCommanderTitleIds: [], }, { @@ -206,6 +196,7 @@ const formatsJson: FormatsJSON = { "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -333,6 +324,8 @@ const formatsJson: FormatsJSON = { "BLB", "BLC", "DSK", + "Y25", + "Y25_BLB", ], filterSets: [ "2XM", @@ -367,6 +360,7 @@ const formatsJson: FormatsJSON = { "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -494,6 +488,8 @@ const formatsJson: FormatsJSON = { "BLB", "BLC", "DSK", + "Y25_BLB", + "Y25", ], bannedTitleIds: [], suspendedTitleIds: [], @@ -502,17 +498,9 @@ const formatsJson: FormatsJSON = { individualCardQuotas: {}, cardCountRestriction: "Singleton", FormatType: "Constructed", - mainDeckQuota: { - min: 39, - max: 249, - }, - sideBoardQuota: { - max: 7, - }, - commandZoneQuota: { - min: 1, - max: 1, - }, + mainDeckQuota: { min: 39, max: 249 }, + sideBoardQuota: { max: 7 }, + commandZoneQuota: { min: 1, max: 1 }, sideboardBehavior: "CompanionOnly", useRebalancedCards: true, AllowedCommanderTitleIds: [], @@ -703,17 +691,9 @@ const formatsJson: FormatsJSON = { individualCardQuotas: {}, cardCountRestriction: "Singleton", FormatType: "Constructed", - mainDeckQuota: { - min: 59, - max: 59, - }, - sideBoardQuota: { - max: 1, - }, - commandZoneQuota: { - min: 1, - max: 1, - }, + mainDeckQuota: { min: 59, max: 59 }, + sideBoardQuota: { max: 1 }, + commandZoneQuota: { min: 1, max: 1 }, sideboardBehavior: "CompanionOnly", AllowedCommanderTitleIds: [], }, @@ -727,13 +707,8 @@ const formatsJson: FormatsJSON = { supressedTitleIds: [], individualCardQuotas: {}, FormatType: "Constructed", - mainDeckQuota: { - min: 60, - max: 250, - }, - sideBoardQuota: { - max: 7, - }, + mainDeckQuota: { min: 60, max: 250 }, + sideBoardQuota: { max: 7 }, AllowedCommanderTitleIds: [], }, { @@ -771,13 +746,8 @@ const formatsJson: FormatsJSON = { supressedTitleIds: [], individualCardQuotas: {}, FormatType: "Constructed", - mainDeckQuota: { - min: 60, - max: 250, - }, - sideBoardQuota: { - max: 15, - }, + mainDeckQuota: { min: 60, max: 250 }, + sideBoardQuota: { max: 15 }, AllowedCommanderTitleIds: [], }, { @@ -790,13 +760,8 @@ const formatsJson: FormatsJSON = { supressedTitleIds: [], individualCardQuotas: {}, FormatType: "Constructed", - mainDeckQuota: { - min: 60, - max: 250, - }, - sideBoardQuota: { - max: 7, - }, + mainDeckQuota: { min: 60, max: 250 }, + sideBoardQuota: { max: 7 }, AllowedCommanderTitleIds: [], }, { @@ -815,6 +780,9 @@ const formatsJson: FormatsJSON = { "BIG", "Y24_OTJ", "BLB", + "Y25", + "Y25_BLB", + "DSK", ], filterSets: [ "ANB", @@ -830,6 +798,9 @@ const formatsJson: FormatsJSON = { "BIG", "Y24_OTJ", "BLB", + "Y25_BLB", + "Y25", + "DSK", ], bannedTitleIds: [488856, 437805, 437834], suspendedTitleIds: [], @@ -838,13 +809,8 @@ const formatsJson: FormatsJSON = { individualCardQuotas: {}, cardCountRestriction: "Singleton", FormatType: "Constructed", - mainDeckQuota: { - min: 60, - max: 250, - }, - sideBoardQuota: { - max: 15, - }, + mainDeckQuota: { min: 60, max: 250 }, + sideBoardQuota: { max: 15 }, useRebalancedCards: true, AllowedCommanderTitleIds: [], }, @@ -883,6 +849,7 @@ const formatsJson: FormatsJSON = { "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -1010,6 +977,8 @@ const formatsJson: FormatsJSON = { "BLB", "BLC", "DSK", + "Y25", + "Y25_BLB", ], filterSets: [ "2XM", @@ -1044,6 +1013,7 @@ const formatsJson: FormatsJSON = { "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -1171,6 +1141,8 @@ const formatsJson: FormatsJSON = { "BLB", "BLC", "DSK", + "Y25_BLB", + "Y25", ], bannedTitleIds: [ 21415, 760, 4023, 12194, 1251, 24870, 1679, 414260, 2904, @@ -1181,13 +1153,8 @@ const formatsJson: FormatsJSON = { individualCardQuotas: {}, cardCountRestriction: "Singleton", FormatType: "Constructed", - mainDeckQuota: { - min: 100, - max: 250, - }, - sideBoardQuota: { - max: 7, - }, + mainDeckQuota: { min: 100, max: 250 }, + sideBoardQuota: { max: 7 }, useRebalancedCards: true, AllowedCommanderTitleIds: [], }, @@ -1226,6 +1193,7 @@ const formatsJson: FormatsJSON = { "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -1353,6 +1321,8 @@ const formatsJson: FormatsJSON = { "BLB", "BLC", "DSK", + "Y25", + "Y25_BLB", ], filterSets: [ "2XM", @@ -1387,6 +1357,7 @@ const formatsJson: FormatsJSON = { "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -1514,6 +1485,8 @@ const formatsJson: FormatsJSON = { "BLB", "BLC", "DSK", + "Y25_BLB", + "Y25", ], bannedTitleIds: [ 351741, 10522, 21415, 760, 4023, 12194, 352244, 507, 336177, 414577, @@ -1527,13 +1500,8 @@ const formatsJson: FormatsJSON = { individualCardQuotas: {}, cardCountRestriction: "Singleton", FormatType: "Constructed", - mainDeckQuota: { - min: 60, - max: 250, - }, - sideBoardQuota: { - max: 7, - }, + mainDeckQuota: { min: 60, max: 250 }, + sideBoardQuota: { max: 7 }, AllowedCommanderTitleIds: [], }, { @@ -1571,6 +1539,7 @@ const formatsJson: FormatsJSON = { "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -1698,6 +1667,8 @@ const formatsJson: FormatsJSON = { "BLB", "BLC", "DSK", + "Y25", + "Y25_BLB", ], filterSets: [ "2XM", @@ -1732,6 +1703,7 @@ const formatsJson: FormatsJSON = { "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -1859,6 +1831,8 @@ const formatsJson: FormatsJSON = { "BLB", "BLC", "DSK", + "Y25_BLB", + "Y25", ], bannedTitleIds: [21415, 12194, 477509], suspendedTitleIds: [], @@ -1866,13 +1840,8 @@ const formatsJson: FormatsJSON = { supressedTitleIds: [21415, 12194, 477509], individualCardQuotas: {}, FormatType: "Constructed", - mainDeckQuota: { - min: 60, - max: 250, - }, - sideBoardQuota: { - max: 7, - }, + mainDeckQuota: { min: 60, max: 250 }, + sideBoardQuota: { max: 7 }, AllowedCommanderTitleIds: [], }, { @@ -1910,6 +1879,7 @@ const formatsJson: FormatsJSON = { "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -2037,6 +2007,8 @@ const formatsJson: FormatsJSON = { "BLB", "BLC", "DSK", + "Y25", + "Y25_BLB", ], filterSets: [ "2XM", @@ -2071,6 +2043,7 @@ const formatsJson: FormatsJSON = { "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -2198,6 +2171,8 @@ const formatsJson: FormatsJSON = { "BLB", "BLC", "DSK", + "Y25_BLB", + "Y25", ], bannedTitleIds: [ 351741, 24405, 21415, 12194, 427904, 352244, 76334, 428590, 8628, 24870, @@ -2209,17 +2184,9 @@ const formatsJson: FormatsJSON = { individualCardQuotas: {}, cardCountRestriction: "Singleton", FormatType: "Constructed", - mainDeckQuota: { - min: 99, - max: 99, - }, - sideBoardQuota: { - max: 1, - }, - commandZoneQuota: { - min: 1, - max: 1, - }, + mainDeckQuota: { min: 99, max: 99 }, + sideBoardQuota: { max: 1 }, + commandZoneQuota: { min: 1, max: 1 }, sideboardBehavior: "CompanionOnly", AllowedCommanderTitleIds: [], }, @@ -2258,6 +2225,7 @@ const formatsJson: FormatsJSON = { "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -2385,6 +2353,8 @@ const formatsJson: FormatsJSON = { "BLB", "BLC", "DSK", + "Y25", + "Y25_BLB", ], filterSets: [ "2XM", @@ -2419,6 +2389,7 @@ const formatsJson: FormatsJSON = { "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -2546,6 +2517,8 @@ const formatsJson: FormatsJSON = { "BLB", "BLC", "DSK", + "Y25_BLB", + "Y25", ], bannedTitleIds: [ 351741, 21415, 760, 4023, 12194, 352244, 414011, 1251, 24870, 1679, @@ -2557,13 +2530,8 @@ const formatsJson: FormatsJSON = { supressedTitleIds: [], individualCardQuotas: {}, FormatType: "Constructed", - mainDeckQuota: { - min: 60, - max: 250, - }, - sideBoardQuota: { - max: 7, - }, + mainDeckQuota: { min: 60, max: 250 }, + sideBoardQuota: { max: 7 }, useRebalancedCards: true, AllowedCommanderTitleIds: [], }, @@ -2602,6 +2570,7 @@ const formatsJson: FormatsJSON = { "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -2729,6 +2698,8 @@ const formatsJson: FormatsJSON = { "BLB", "BLC", "DSK", + "Y25", + "Y25_BLB", ], filterSets: [ "2XM", @@ -2763,6 +2734,7 @@ const formatsJson: FormatsJSON = { "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -2890,6 +2862,8 @@ const formatsJson: FormatsJSON = { "BLB", "BLC", "DSK", + "Y25_BLB", + "Y25", ], bannedTitleIds: [ 351741, 10522, 21415, 760, 4023, 12194, 352244, 1251, 428590, 6167, @@ -2902,13 +2876,8 @@ const formatsJson: FormatsJSON = { individualCardQuotas: {}, cardCountRestriction: "Singleton", FormatType: "Constructed", - mainDeckQuota: { - min: 60, - max: 250, - }, - sideBoardQuota: { - max: 7, - }, + mainDeckQuota: { min: 60, max: 250 }, + sideBoardQuota: { max: 7 }, useRebalancedCards: true, AllowedCommanderTitleIds: [], }, @@ -2968,13 +2937,8 @@ const formatsJson: FormatsJSON = { supressedTitleIds: [], individualCardQuotas: {}, FormatType: "Constructed", - mainDeckQuota: { - min: 60, - max: 250, - }, - sideBoardQuota: { - max: 7, - }, + mainDeckQuota: { min: 60, max: 250 }, + sideBoardQuota: { max: 7 }, AllowedCommanderTitleIds: [], }, { @@ -2987,13 +2951,8 @@ const formatsJson: FormatsJSON = { supressedTitleIds: [], individualCardQuotas: {}, FormatType: "Constructed", - mainDeckQuota: { - min: 60, - max: 250, - }, - sideBoardQuota: { - max: 15, - }, + mainDeckQuota: { min: 60, max: 250 }, + sideBoardQuota: { max: 15 }, AllowedCommanderTitleIds: [], }, { @@ -3012,6 +2971,9 @@ const formatsJson: FormatsJSON = { "BIG", "Y24_OTJ", "BLB", + "Y25", + "Y25_BLB", + "DSK", ], filterSets: [ "ANB", @@ -3027,6 +2989,9 @@ const formatsJson: FormatsJSON = { "BIG", "Y24_OTJ", "BLB", + "Y25_BLB", + "Y25", + "DSK", ], bannedTitleIds: [], suspendedTitleIds: [], @@ -3035,13 +3000,8 @@ const formatsJson: FormatsJSON = { individualCardQuotas: {}, cardCountRestriction: "Singleton", FormatType: "Constructed", - mainDeckQuota: { - min: 60, - max: 250, - }, - sideBoardQuota: { - max: 15, - }, + mainDeckQuota: { min: 60, max: 250 }, + sideBoardQuota: { max: 15 }, AllowedCommanderTitleIds: [], }, { @@ -3054,13 +3014,8 @@ const formatsJson: FormatsJSON = { supressedTitleIds: [], individualCardQuotas: {}, FormatType: "Constructed", - mainDeckQuota: { - min: 60, - max: 250, - }, - sideBoardQuota: { - max: 7, - }, + mainDeckQuota: { min: 60, max: 250 }, + sideBoardQuota: { max: 7 }, AllowedCommanderTitleIds: [], }, { @@ -3098,6 +3053,7 @@ const formatsJson: FormatsJSON = { "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -3225,6 +3181,8 @@ const formatsJson: FormatsJSON = { "BLB", "BLC", "DSK", + "Y25", + "Y25_BLB", ], filterSets: [ "2XM", @@ -3259,6 +3217,7 @@ const formatsJson: FormatsJSON = { "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -3386,6 +3345,8 @@ const formatsJson: FormatsJSON = { "BLB", "BLC", "DSK", + "Y25_BLB", + "Y25", ], bannedTitleIds: [ 487194, 351741, 10522, 413858, 21415, 760, 4023, 12194, 352244, 279773, @@ -3397,13 +3358,8 @@ const formatsJson: FormatsJSON = { supressedTitleIds: [], individualCardQuotas: {}, FormatType: "Constructed", - mainDeckQuota: { - min: 60, - max: 250, - }, - sideBoardQuota: { - max: 7, - }, + mainDeckQuota: { min: 60, max: 250 }, + sideBoardQuota: { max: 7 }, useRebalancedCards: true, AllowedCommanderTitleIds: [], }, @@ -3442,6 +3398,7 @@ const formatsJson: FormatsJSON = { "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -3569,6 +3526,8 @@ const formatsJson: FormatsJSON = { "BLB", "BLC", "DSK", + "Y25", + "Y25_BLB", ], filterSets: [ "2XM", @@ -3603,6 +3562,7 @@ const formatsJson: FormatsJSON = { "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -3730,6 +3690,8 @@ const formatsJson: FormatsJSON = { "BLB", "BLC", "DSK", + "Y25_BLB", + "Y25", ], bannedTitleIds: [ 351741, 24405, 21415, 12194, 760671, 427904, 352244, 76334, 428590, @@ -3741,17 +3703,9 @@ const formatsJson: FormatsJSON = { individualCardQuotas: {}, cardCountRestriction: "Singleton", FormatType: "Constructed", - mainDeckQuota: { - min: 99, - max: 99, - }, - sideBoardQuota: { - max: 1, - }, - commandZoneQuota: { - min: 1, - max: 1, - }, + mainDeckQuota: { min: 99, max: 99 }, + sideBoardQuota: { max: 1 }, + commandZoneQuota: { min: 1, max: 1 }, sideboardBehavior: "CompanionOnly", useRebalancedCards: true, AllowedCommanderTitleIds: [], @@ -3767,13 +3721,8 @@ const formatsJson: FormatsJSON = { individualCardQuotas: {}, cardCountRestriction: "UnrestrictedCardCounts", FormatType: "Draft", - mainDeckQuota: { - min: 40, - max: 250, - }, - sideBoardQuota: { - max: 250, - }, + mainDeckQuota: { min: 40, max: 250 }, + sideBoardQuota: { max: 250 }, useRebalancedCards: true, AllowedCommanderTitleIds: [], }, @@ -3812,6 +3761,7 @@ const formatsJson: FormatsJSON = { "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -3939,6 +3889,8 @@ const formatsJson: FormatsJSON = { "BLB", "BLC", "DSK", + "Y25", + "Y25_BLB", ], filterSets: [ "2XM", @@ -3973,6 +3925,7 @@ const formatsJson: FormatsJSON = { "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -4100,6 +4053,8 @@ const formatsJson: FormatsJSON = { "BLB", "BLC", "DSK", + "Y25_BLB", + "Y25", ], bannedTitleIds: [12194, 352244, 604511, 24870, 414260], suspendedTitleIds: [], @@ -4108,10 +4063,7 @@ const formatsJson: FormatsJSON = { individualCardQuotas: {}, cardCountRestriction: "Singleton", FormatType: "Constructed", - mainDeckQuota: { - min: 100, - max: 250, - }, + mainDeckQuota: { min: 100, max: 250 }, AllowedCommanderTitleIds: [], }, { @@ -4149,6 +4101,7 @@ const formatsJson: FormatsJSON = { "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -4276,6 +4229,8 @@ const formatsJson: FormatsJSON = { "BLB", "BLC", "DSK", + "Y25", + "Y25_BLB", ], filterSets: [ "2XM", @@ -4310,6 +4265,7 @@ const formatsJson: FormatsJSON = { "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -4437,6 +4393,8 @@ const formatsJson: FormatsJSON = { "BLB", "BLC", "DSK", + "Y25_BLB", + "Y25", ], bannedTitleIds: [ 487194, 351741, 413858, 24405, 21415, 12194, 427904, 352244, 279773, @@ -4449,17 +4407,9 @@ const formatsJson: FormatsJSON = { individualCardQuotas: {}, cardCountRestriction: "Singleton", FormatType: "Constructed", - mainDeckQuota: { - min: 99, - max: 99, - }, - sideBoardQuota: { - max: 1, - }, - commandZoneQuota: { - min: 1, - max: 1, - }, + mainDeckQuota: { min: 99, max: 99 }, + sideBoardQuota: { max: 1 }, + commandZoneQuota: { min: 1, max: 1 }, sideboardBehavior: "CompanionOnly", AllowedCommanderTitleIds: [], }, @@ -4474,13 +4424,8 @@ const formatsJson: FormatsJSON = { individualCardQuotas: {}, cardCountRestriction: "UnrestrictedCardCounts", FormatType: "Sealed", - mainDeckQuota: { - min: 40, - max: 250, - }, - sideBoardQuota: { - max: 250, - }, + mainDeckQuota: { min: 40, max: 250 }, + sideBoardQuota: { max: 250 }, useRebalancedCards: true, AllowedCommanderTitleIds: [], }, @@ -4498,6 +4443,7 @@ const formatsJson: FormatsJSON = { "OTJ", "BIG", "BLB", + "DSK", ], filterSets: [ "DMU", @@ -4511,6 +4457,7 @@ const formatsJson: FormatsJSON = { "OTJ", "BIG", "BLB", + "DSK", ], bannedTitleIds: [], suspendedTitleIds: [], @@ -4518,13 +4465,8 @@ const formatsJson: FormatsJSON = { supressedTitleIds: [], individualCardQuotas: {}, FormatType: "Constructed", - mainDeckQuota: { - min: 60, - max: 250, - }, - sideBoardQuota: { - max: 7, - }, + mainDeckQuota: { min: 60, max: 250 }, + sideBoardQuota: { max: 7 }, useRebalancedCards: true, AllowedCommanderTitleIds: [], }, @@ -4538,13 +4480,8 @@ const formatsJson: FormatsJSON = { supressedTitleIds: [], individualCardQuotas: {}, FormatType: "Constructed", - mainDeckQuota: { - min: 60, - max: 250, - }, - sideBoardQuota: { - max: 15, - }, + mainDeckQuota: { min: 60, max: 250 }, + sideBoardQuota: { max: 15 }, AllowedCommanderTitleIds: [], }, { @@ -4563,6 +4500,9 @@ const formatsJson: FormatsJSON = { "BIG", "Y24_OTJ", "BLB", + "Y25", + "Y25_BLB", + "DSK", ], filterSets: [ "ANB", @@ -4578,6 +4518,9 @@ const formatsJson: FormatsJSON = { "BIG", "Y24_OTJ", "BLB", + "Y25_BLB", + "Y25", + "DSK", ], bannedTitleIds: [3142, 3142, 3142, 3142], suspendedTitleIds: [], @@ -4585,13 +4528,8 @@ const formatsJson: FormatsJSON = { supressedTitleIds: [3142], individualCardQuotas: {}, FormatType: "Constructed", - mainDeckQuota: { - min: 60, - max: 250, - }, - sideBoardQuota: { - max: 7, - }, + mainDeckQuota: { min: 60, max: 250 }, + sideBoardQuota: { max: 7 }, useRebalancedCards: true, AllowedCommanderTitleIds: [], }, @@ -4605,13 +4543,8 @@ const formatsJson: FormatsJSON = { supressedTitleIds: [], individualCardQuotas: {}, FormatType: "Constructed", - mainDeckQuota: { - min: 60, - max: 250, - }, - sideBoardQuota: { - max: 7, - }, + mainDeckQuota: { min: 60, max: 250 }, + sideBoardQuota: { max: 7 }, AllowedCommanderTitleIds: [], }, { @@ -4630,6 +4563,9 @@ const formatsJson: FormatsJSON = { "BIG", "Y24_OTJ", "BLB", + "Y25", + "Y25_BLB", + "DSK", ], filterSets: [ "ANB", @@ -4645,6 +4581,9 @@ const formatsJson: FormatsJSON = { "BIG", "Y24_OTJ", "BLB", + "Y25_BLB", + "Y25", + "DSK", ], bannedTitleIds: [181902, 173836, 1094, 229715, 173615], suspendedTitleIds: [], @@ -4652,13 +4591,8 @@ const formatsJson: FormatsJSON = { supressedTitleIds: [], individualCardQuotas: {}, FormatType: "Constructed", - mainDeckQuota: { - min: 60, - max: 250, - }, - sideBoardQuota: { - max: 15, - }, + mainDeckQuota: { min: 60, max: 250 }, + sideBoardQuota: { max: 15 }, AllowedCommanderTitleIds: [], }, { @@ -4696,6 +4630,7 @@ const formatsJson: FormatsJSON = { "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -4823,6 +4758,8 @@ const formatsJson: FormatsJSON = { "BLB", "BLC", "DSK", + "Y25", + "Y25_BLB", ], filterSets: [ "2XM", @@ -4857,6 +4794,7 @@ const formatsJson: FormatsJSON = { "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -4984,6 +4922,8 @@ const formatsJson: FormatsJSON = { "BLB", "BLC", "DSK", + "Y25_BLB", + "Y25", ], bannedTitleIds: [ 351741, 38310, 429, 25409, 10522, 21415, 11851, 760, 4023, 12194, @@ -5003,13 +4943,8 @@ const formatsJson: FormatsJSON = { ], individualCardQuotas: {}, FormatType: "Constructed", - mainDeckQuota: { - min: 60, - max: 250, - }, - sideBoardQuota: { - max: 15, - }, + mainDeckQuota: { min: 60, max: 250 }, + sideBoardQuota: { max: 15 }, useRebalancedCards: true, AllowedCommanderTitleIds: [], }, @@ -5029,6 +4964,9 @@ const formatsJson: FormatsJSON = { "BIG", "Y24_OTJ", "BLB", + "Y25", + "Y25_BLB", + "DSK", ], filterSets: [ "ANB", @@ -5044,6 +4982,9 @@ const formatsJson: FormatsJSON = { "BIG", "Y24_OTJ", "BLB", + "Y25_BLB", + "Y25", + "DSK", ], bannedTitleIds: [336370, 1679], suspendedTitleIds: [], @@ -5051,13 +4992,8 @@ const formatsJson: FormatsJSON = { supressedTitleIds: [], individualCardQuotas: {}, FormatType: "Constructed", - mainDeckQuota: { - min: 60, - max: 250, - }, - sideBoardQuota: { - max: 15, - }, + mainDeckQuota: { min: 60, max: 250 }, + sideBoardQuota: { max: 15 }, AllowedCommanderTitleIds: [], }, { @@ -5219,6 +5155,9 @@ const formatsJson: FormatsJSON = { "M3C", "BLC", "BLB", + "Y25", + "Y25_BLB", + "DSK", ], filterSets: [ "2XM", @@ -5377,30 +5316,22 @@ const formatsJson: FormatsJSON = { "M3C", "BLB", "BLC", + "Y25_BLB", + "Y25", + "DSK", ], bannedTitleIds: [], suspendedTitleIds: [], allowedTitleIds: [], supressedTitleIds: [21415, 12194, 477509], individualCardQuotas: { - "21415": { - max: 1, - }, - "12194": { - max: 1, - }, - "477509": { - max: 1, - }, + "21415": { max: 1 }, + "12194": { max: 1 }, + "477509": { max: 1 }, }, FormatType: "Constructed", - mainDeckQuota: { - min: 60, - max: 250, - }, - sideBoardQuota: { - max: 7, - }, + mainDeckQuota: { min: 60, max: 250 }, + sideBoardQuota: { max: 7 }, AllowedCommanderTitleIds: [], }, { @@ -5413,13 +5344,8 @@ const formatsJson: FormatsJSON = { supressedTitleIds: [], individualCardQuotas: {}, FormatType: "Constructed", - mainDeckQuota: { - min: 60, - max: 250, - }, - sideBoardQuota: { - max: 15, - }, + mainDeckQuota: { min: 60, max: 250 }, + sideBoardQuota: { max: 15 }, AllowedCommanderTitleIds: [], }, { @@ -5432,13 +5358,8 @@ const formatsJson: FormatsJSON = { supressedTitleIds: [], individualCardQuotas: {}, FormatType: "Constructed", - mainDeckQuota: { - min: 60, - max: 250, - }, - sideBoardQuota: { - max: 7, - }, + mainDeckQuota: { min: 60, max: 250 }, + sideBoardQuota: { max: 7 }, AllowedCommanderTitleIds: [], }, { @@ -5727,37 +5648,24 @@ const formatsJson: FormatsJSON = { individualCardQuotas: {}, cardCountRestriction: "Singleton", FormatType: "Constructed", - mainDeckQuota: { - min: 59, - max: 59, - }, - sideBoardQuota: { - max: 15, - }, - commandZoneQuota: { - min: 1, - max: 1, - }, + mainDeckQuota: { min: 59, max: 59 }, + sideBoardQuota: { max: 15 }, + commandZoneQuota: { min: 1, max: 1 }, useRebalancedCards: true, AllowedCommanderTitleIds: [], }, { name: "Standard_Recent", - legalSets: ["BLB", "OTJ", "BIG", "MKM", "LCI", "WOE"], - filterSets: ["BLB", "OTJ", "BIG", "MKM", "LCI", "WOE"], + legalSets: ["WOE", "LCI", "MKM", "OTJ", "BIG", "BLB", "DSK"], + filterSets: ["WOE", "LCI", "MKM", "OTJ", "BIG", "BLB", "DSK"], bannedTitleIds: [557819, 557663, 558273, 530112, 3142], suspendedTitleIds: [], allowedTitleIds: [], supressedTitleIds: [], individualCardQuotas: {}, FormatType: "Constructed", - mainDeckQuota: { - min: 60, - max: 250, - }, - sideBoardQuota: { - max: 7, - }, + mainDeckQuota: { min: 60, max: 250 }, + sideBoardQuota: { max: 7 }, AllowedCommanderTitleIds: [], }, { @@ -5771,13 +5679,8 @@ const formatsJson: FormatsJSON = { individualCardQuotas: {}, cardCountRestriction: "UnrestrictedCardCounts", FormatType: "Sealed", - mainDeckQuota: { - min: 40, - max: 250, - }, - sideBoardQuota: { - max: 250, - }, + mainDeckQuota: { min: 40, max: 250 }, + sideBoardQuota: { max: 250 }, AllowedCommanderTitleIds: [], }, { @@ -5815,6 +5718,7 @@ const formatsJson: FormatsJSON = { "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -5942,6 +5846,8 @@ const formatsJson: FormatsJSON = { "BLB", "BLC", "DSK", + "Y25", + "Y25_BLB", ], filterSets: [ "2XM", @@ -5976,6 +5882,7 @@ const formatsJson: FormatsJSON = { "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -6103,6 +6010,8 @@ const formatsJson: FormatsJSON = { "BLB", "BLC", "DSK", + "Y25_BLB", + "Y25", ], bannedTitleIds: [], suspendedTitleIds: [], @@ -6111,13 +6020,8 @@ const formatsJson: FormatsJSON = { individualCardQuotas: {}, cardCountRestriction: "Singleton", FormatType: "Constructed", - mainDeckQuota: { - min: 60, - max: 250, - }, - sideBoardQuota: { - max: 7, - }, + mainDeckQuota: { min: 60, max: 250 }, + sideBoardQuota: { max: 7 }, useRebalancedCards: true, AllowedCommanderTitleIds: [], }, @@ -6131,13 +6035,8 @@ const formatsJson: FormatsJSON = { supressedTitleIds: [], individualCardQuotas: {}, FormatType: "Constructed", - mainDeckQuota: { - min: 60, - max: 250, - }, - sideBoardQuota: { - max: 7, - }, + mainDeckQuota: { min: 60, max: 250 }, + sideBoardQuota: { max: 7 }, AllowedCommanderTitleIds: [], }, { @@ -6150,13 +6049,8 @@ const formatsJson: FormatsJSON = { supressedTitleIds: [], individualCardQuotas: {}, FormatType: "Constructed", - mainDeckQuota: { - min: 60, - max: 250, - }, - sideBoardQuota: { - max: 15, - }, + mainDeckQuota: { min: 60, max: 250 }, + sideBoardQuota: { max: 15 }, AllowedCommanderTitleIds: [], }, { @@ -6169,13 +6063,8 @@ const formatsJson: FormatsJSON = { supressedTitleIds: [], individualCardQuotas: {}, FormatType: "Constructed", - mainDeckQuota: { - min: 60, - max: 250, - }, - sideBoardQuota: { - max: 7, - }, + mainDeckQuota: { min: 60, max: 250 }, + sideBoardQuota: { max: 7 }, AllowedCommanderTitleIds: [], }, { @@ -6236,6 +6125,7 @@ const formatsJson: FormatsJSON = { "BIG", "OTJ", "BLB", + "DSK", ], filterSets: [ "AER", @@ -6296,11 +6186,13 @@ const formatsJson: FormatsJSON = { "OTJ", "SPG", "BLB", + "DSK", ], bannedTitleIds: [ - 38310, 25409, 488847, 352244, 24807, 737615, 336177, 352156, 352080, - 428587, 38551, 38526, 1679, 414260, 414166, 24837, 38497, 336891, - 477509, 420184, 420429, 352113, 38622, 279929, 24888, 428552, 3179, + 737878, 38310, 25409, 488847, 352244, 24807, 737615, 336177, 352156, + 352080, 428587, 38551, 38526, 1679, 414260, 414166, 24837, 38497, + 351897, 336891, 477509, 420184, 420429, 352113, 38622, 279929, 24888, + 428552, 3179, ], suspendedTitleIds: [], allowedTitleIds: [ @@ -6469,17 +6361,12 @@ const formatsJson: FormatsJSON = { supressedTitleIds: [], individualCardQuotas: {}, FormatType: "Constructed", - mainDeckQuota: { - min: 60, - max: 250, - }, - sideBoardQuota: { - max: 15, - }, + mainDeckQuota: { min: 60, max: 250 }, + sideBoardQuota: { max: 15 }, AllowedCommanderTitleIds: [], }, { - name: "HistoricBrawlWithAllowList_20240514", + name: "HistoricBrawlWithAllowList_20240903", legalSets: [ "2XM", "2X2", @@ -6513,6 +6400,7 @@ const formatsJson: FormatsJSON = { "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -6640,6 +6528,8 @@ const formatsJson: FormatsJSON = { "BLB", "BLC", "DSK", + "Y25", + "Y25_BLB", ], filterSets: [ "2XM", @@ -6674,6 +6564,7 @@ const formatsJson: FormatsJSON = { "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -6801,10 +6692,13 @@ const formatsJson: FormatsJSON = { "BLB", "BLC", "DSK", + "Y25_BLB", + "Y25", ], bannedTitleIds: [ - 351741, 24405, 21415, 12194, 427904, 352244, 76334, 428590, 8628, 24870, - 1679, 414260, 19674, 5159, 31558, 174019, 26717, 46453, + 351741, 24405, 21415, 12194, 760671, 427904, 352244, 76334, 428590, + 8628, 24870, 1679, 414260, 279584, 19674, 5159, 31558, 174019, 26717, + 46453, ], suspendedTitleIds: [], allowedTitleIds: [], @@ -6812,31 +6706,18 @@ const formatsJson: FormatsJSON = { individualCardQuotas: {}, cardCountRestriction: "Singleton", FormatType: "Constructed", - mainDeckQuota: { - min: 99, - max: 99, - }, - sideBoardQuota: { - max: 1, - }, - commandZoneQuota: { - min: 1, - max: 1, - }, + mainDeckQuota: { min: 99, max: 99 }, + sideBoardQuota: { max: 1 }, + commandZoneQuota: { min: 1, max: 1 }, sideboardBehavior: "CompanionOnly", useRebalancedCards: true, AllowedCommanderTitleIds: [ - 756700, 810848, 756704, 756724, 756728, 756732, 756582, 756735, 756432, - 756746, 810852, 756750, 756753, 756200, 756065, 756206, 756760, 756339, - 793860, 810815, 756768, 756989, 756776, 810807, 756779, 756351, 756784, - 756791, 756795, 756799, 756802, 756805, 756501, 756810, 756813, 756816, - 810918, 756820, 756824, 793863, 756838, 810854, 756843, 756852, 810858, - 756859, 756864, 793866, 756876, 810844, 756764, 756409, 756422, 756880, - 810862, 756889, 756894, 793869, + 763453, 811718, 814447, 566475, 811743, 546509, 811751, 557748, 702876, + 3894, 756764, 702880, 227265, ], }, { - name: "DirectGameLimitedRebalanced", + name: "HistoricBrawlWithAllowList_20240514", legalSets: [ "2XM", "2X2", @@ -6870,6 +6751,7 @@ const formatsJson: FormatsJSON = { "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -6997,6 +6879,8 @@ const formatsJson: FormatsJSON = { "BLB", "BLC", "DSK", + "Y25", + "Y25_BLB", ], filterSets: [ "2XM", @@ -7031,6 +6915,7 @@ const formatsJson: FormatsJSON = { "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -7158,75 +7043,36 @@ const formatsJson: FormatsJSON = { "BLB", "BLC", "DSK", + "Y25_BLB", + "Y25", + ], + bannedTitleIds: [ + 351741, 24405, 21415, 12194, 427904, 352244, 76334, 428590, 8628, 24870, + 1679, 414260, 19674, 5159, 31558, 174019, 26717, 46453, ], - bannedTitleIds: [], suspendedTitleIds: [], allowedTitleIds: [], supressedTitleIds: [], individualCardQuotas: {}, - cardCountRestriction: "UnrestrictedCardCounts", - FormatType: "Constructed", - mainDeckQuota: { - min: 40, - max: 250, - }, - sideBoardQuota: { - max: 250, - }, - useRebalancedCards: true, - AllowedCommanderTitleIds: [], - }, - { - name: "Brawl", - legalSets: [ - "DMU", - "BRO", - "ONE", - "MOM", - "MAT", - "WOE", - "LCI", - "MKM", - "OTJ", - "BIG", - "BLB", - ], - filterSets: [ - "DMU", - "BRO", - "ONE", - "MOM", - "MAT", - "WOE", - "LCI", - "MKM", - "OTJ", - "BIG", - "BLB", - ], - bannedTitleIds: [5159, 3142, 3142, 3142, 3142], - suspendedTitleIds: [], - allowedTitleIds: [414587, 10756], - supressedTitleIds: [3142], - individualCardQuotas: {}, cardCountRestriction: "Singleton", FormatType: "Constructed", - mainDeckQuota: { - min: 59, - max: 59, - }, - sideBoardQuota: { - max: 1, - }, - commandZoneQuota: { - min: 1, - max: 1, - }, + mainDeckQuota: { min: 99, max: 99 }, + sideBoardQuota: { max: 1 }, + commandZoneQuota: { min: 1, max: 1 }, sideboardBehavior: "CompanionOnly", - AllowedCommanderTitleIds: [], + useRebalancedCards: true, + AllowedCommanderTitleIds: [ + 756700, 810848, 756704, 756724, 756728, 756732, 756582, 756735, 756432, + 756746, 810852, 756750, 756753, 756200, 756065, 756206, 756760, 756339, + 793860, 810815, 756768, 756989, 756776, 810807, 756779, 756351, 756784, + 756791, 756795, 756799, 756802, 756805, 756501, 756810, 756813, 756816, + 810918, 756820, 756824, 793863, 756838, 810854, 756843, 756852, 810858, + 756859, 756864, 793866, 756876, 810844, 756764, 756409, 756422, 756880, + 810862, 756889, 756894, 793869, + ], }, { - name: "HistoricShakeup", + name: "DirectGameLimitedRebalanced", legalSets: [ "2XM", "2X2", @@ -7260,6 +7106,7 @@ const formatsJson: FormatsJSON = { "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -7387,6 +7234,8 @@ const formatsJson: FormatsJSON = { "BLB", "BLC", "DSK", + "Y25", + "Y25_BLB", ], filterSets: [ "2XM", @@ -7421,6 +7270,7 @@ const formatsJson: FormatsJSON = { "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -7548,31 +7398,66 @@ const formatsJson: FormatsJSON = { "BLB", "BLC", "DSK", + "Y25_BLB", + "Y25", ], - bannedTitleIds: [ - 351741, 429999, 272772, 10522, 413858, 21415, 47395, 760, 4023, 12194, - 566299, 497307, 487228, 488847, 39661, 352244, 227304, 558133, 419691, - 28117, 1251, 2688, 352248, 428587, 6167, 489202, 434348, 24870, 1679, - 336840, 414260, 414166, 2904, 227513, 419870, 17643, 477509, 2183, - 420429, 352113, 279929, 428552, - ], + bannedTitleIds: [], suspendedTitleIds: [], allowedTitleIds: [], supressedTitleIds: [], individualCardQuotas: {}, + cardCountRestriction: "UnrestrictedCardCounts", FormatType: "Constructed", - mainDeckQuota: { - min: 60, - max: 250, - }, - sideBoardQuota: { - max: 7, - }, + mainDeckQuota: { min: 40, max: 250 }, + sideBoardQuota: { max: 250 }, useRebalancedCards: true, AllowedCommanderTitleIds: [], }, { - name: "HistoricShakeup3", + name: "Brawl", + legalSets: [ + "DMU", + "BRO", + "ONE", + "MOM", + "MAT", + "WOE", + "LCI", + "MKM", + "OTJ", + "BIG", + "BLB", + "DSK", + ], + filterSets: [ + "DMU", + "BRO", + "ONE", + "MOM", + "MAT", + "WOE", + "LCI", + "MKM", + "OTJ", + "BIG", + "BLB", + "DSK", + ], + bannedTitleIds: [5159, 3142, 3142, 3142, 3142], + suspendedTitleIds: [], + allowedTitleIds: [414587, 10756], + supressedTitleIds: [3142], + individualCardQuotas: {}, + cardCountRestriction: "Singleton", + FormatType: "Constructed", + mainDeckQuota: { min: 59, max: 59 }, + sideBoardQuota: { max: 1 }, + commandZoneQuota: { min: 1, max: 1 }, + sideboardBehavior: "CompanionOnly", + AllowedCommanderTitleIds: [], + }, + { + name: "HistoricShakeup", legalSets: [ "2XM", "2X2", @@ -7606,6 +7491,7 @@ const formatsJson: FormatsJSON = { "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -7733,6 +7619,8 @@ const formatsJson: FormatsJSON = { "BLB", "BLC", "DSK", + "Y25", + "Y25_BLB", ], filterSets: [ "2XM", @@ -7767,6 +7655,7 @@ const formatsJson: FormatsJSON = { "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -7894,89 +7783,28 @@ const formatsJson: FormatsJSON = { "BLB", "BLC", "DSK", + "Y25_BLB", + "Y25", ], bannedTitleIds: [ - 173532, 351741, 413974, 413710, 413986, 47395, 433909, 181639, 414227, - 229682, 413992, 477884, 352244, 414011, 5526, 336177, 351874, 28117, - 279794, 43442, 2688, 433696, 437015, 428587, 434348, 336370, 336832, - 1679, 336718, 414260, 414166, 414172, 477049, 125065, 3236, 227513, - 336891, 17643, 477509, 46453, 420429, 352113, 279929, 428552, 414418, - 428610, 428554, + 351741, 429999, 272772, 10522, 413858, 21415, 47395, 760, 4023, 12194, + 566299, 497307, 487228, 488847, 39661, 352244, 227304, 558133, 419691, + 28117, 1251, 2688, 352248, 428587, 6167, 489202, 434348, 24870, 1679, + 336840, 414260, 414166, 2904, 227513, 419870, 17643, 477509, 2183, + 420429, 352113, 279929, 428552, ], suspendedTitleIds: [], allowedTitleIds: [], supressedTitleIds: [], individualCardQuotas: {}, FormatType: "Constructed", - mainDeckQuota: { - min: 60, - max: 250, - }, - sideBoardQuota: { - max: 7, - }, + mainDeckQuota: { min: 60, max: 250 }, + sideBoardQuota: { max: 7 }, useRebalancedCards: true, AllowedCommanderTitleIds: [], }, { - name: "Strixhaven", - legalSets: ["STX"], - filterSets: ["STX"], - bannedTitleIds: [], - suspendedTitleIds: [], - allowedTitleIds: [], - supressedTitleIds: [], - individualCardQuotas: {}, - FormatType: "Constructed", - mainDeckQuota: { - min: 60, - max: 250, - }, - sideBoardQuota: { - max: 7, - }, - AllowedCommanderTitleIds: [], - }, - { - name: "StreetsOfNewCapenna", - legalSets: ["SNC"], - filterSets: ["SNC"], - bannedTitleIds: [], - suspendedTitleIds: [], - allowedTitleIds: [], - supressedTitleIds: [], - individualCardQuotas: {}, - FormatType: "Constructed", - mainDeckQuota: { - min: 60, - max: 250, - }, - sideBoardQuota: { - max: 7, - }, - AllowedCommanderTitleIds: [], - }, - { - name: "BLB", - legalSets: ["BLB"], - filterSets: ["BLB"], - bannedTitleIds: [], - suspendedTitleIds: [], - allowedTitleIds: [], - supressedTitleIds: [], - individualCardQuotas: {}, - FormatType: "Constructed", - mainDeckQuota: { - min: 60, - max: 250, - }, - sideBoardQuota: { - max: 15, - }, - AllowedCommanderTitleIds: [], - }, - { - name: "TraditionalTimeless", + name: "HistoricShakeup3", legalSets: [ "2XM", "2X2", @@ -8010,6 +7838,7 @@ const formatsJson: FormatsJSON = { "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -8117,6 +7946,7 @@ const formatsJson: FormatsJSON = { "LCC", "Y24_LCI", "MKM", + "OTJ", "Y24_MKM", "SPG", "KLD", @@ -8125,15 +7955,19 @@ const formatsJson: FormatsJSON = { "C16", "DIS", "DDU", - "BIG", + "MH3", "OTP", - "OTJ", + "OTC", + "BIG", "OTC", "Y24_OTJ", "MH3", "M3C", - "BLC", "BLB", + "BLC", + "DSK", + "Y25", + "Y25_BLB", ], filterSets: [ "2XM", @@ -8168,6 +8002,7 @@ const formatsJson: FormatsJSON = { "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -8275,6 +8110,7 @@ const formatsJson: FormatsJSON = { "LCC", "Y24_LCI", "MKM", + "OTJ", "Y24_MKM", "SPG", "KLD", @@ -8283,62 +8119,82 @@ const formatsJson: FormatsJSON = { "C16", "DIS", "DDU", - "BIG", + "MH3", "OTP", - "OTJ", + "OTC", + "BIG", "OTC", "Y24_OTJ", "MH3", "M3C", "BLB", "BLC", + "DSK", + "Y25_BLB", + "Y25", + ], + bannedTitleIds: [ + 173532, 351741, 413974, 413710, 413986, 47395, 433909, 181639, 414227, + 229682, 413992, 477884, 352244, 414011, 5526, 336177, 351874, 28117, + 279794, 43442, 2688, 433696, 437015, 428587, 434348, 336370, 336832, + 1679, 336718, 414260, 414166, 414172, 477049, 125065, 3236, 227513, + 336891, 17643, 477509, 46453, 420429, 352113, 279929, 428552, 414418, + 428610, 428554, ], + suspendedTitleIds: [], + allowedTitleIds: [], + supressedTitleIds: [], + individualCardQuotas: {}, + FormatType: "Constructed", + mainDeckQuota: { min: 60, max: 250 }, + sideBoardQuota: { max: 7 }, + useRebalancedCards: true, + AllowedCommanderTitleIds: [], + }, + { + name: "Strixhaven", + legalSets: ["STX"], + filterSets: ["STX"], bannedTitleIds: [], suspendedTitleIds: [], allowedTitleIds: [], supressedTitleIds: [], - individualCardQuotas: { - "21415": { - max: 1, - }, - "12194": { - max: 1, - }, - "477509": { - max: 1, - }, - }, + individualCardQuotas: {}, FormatType: "Constructed", - mainDeckQuota: { - min: 60, - max: 250, - }, - sideBoardQuota: { - max: 15, - }, + mainDeckQuota: { min: 60, max: 250 }, + sideBoardQuota: { max: 7 }, AllowedCommanderTitleIds: [], }, { - name: "OTJ", - legalSets: ["OTJ", "BIG"], - filterSets: ["OTJ", "BIG"], + name: "StreetsOfNewCapenna", + legalSets: ["SNC"], + filterSets: ["SNC"], bannedTitleIds: [], suspendedTitleIds: [], allowedTitleIds: [], supressedTitleIds: [], individualCardQuotas: {}, FormatType: "Constructed", - mainDeckQuota: { - min: 60, - max: 250, - }, - sideBoardQuota: { - max: 15, - }, + mainDeckQuota: { min: 60, max: 250 }, + sideBoardQuota: { max: 7 }, AllowedCommanderTitleIds: [], }, { - name: "DirectGameAlchemy", + name: "BLB", + legalSets: ["BLB"], + filterSets: ["BLB"], + bannedTitleIds: [], + suspendedTitleIds: [], + allowedTitleIds: [], + supressedTitleIds: [], + individualCardQuotas: {}, + FormatType: "Constructed", + mainDeckQuota: { min: 60, max: 250 }, + sideBoardQuota: { max: 15 }, + AllowedCommanderTitleIds: [], + }, + { + name: "TraditionalTimeless", legalSets: [ "2XM", "2X2", @@ -8479,7 +8335,6 @@ const formatsJson: FormatsJSON = { "LCC", "Y24_LCI", "MKM", - "OTJ", "Y24_MKM", "SPG", "KLD", @@ -8488,16 +8343,17 @@ const formatsJson: FormatsJSON = { "C16", "DIS", "DDU", - "MH3", - "OTP", - "OTC", "BIG", + "OTP", + "OTJ", "OTC", "Y24_OTJ", "MH3", "M3C", - "BLB", "BLC", + "BLB", + "Y25", + "Y25_BLB", "DSK", ], filterSets: [ @@ -8640,7 +8496,6 @@ const formatsJson: FormatsJSON = { "LCC", "Y24_LCI", "MKM", - "OTJ", "Y24_MKM", "SPG", "KLD", @@ -8649,36 +8504,49 @@ const formatsJson: FormatsJSON = { "C16", "DIS", "DDU", - "MH3", - "OTP", - "OTC", "BIG", + "OTP", + "OTJ", "OTC", "Y24_OTJ", "MH3", "M3C", "BLB", "BLC", + "Y25_BLB", + "Y25", "DSK", ], bannedTitleIds: [], suspendedTitleIds: [], allowedTitleIds: [], supressedTitleIds: [], + individualCardQuotas: { + "21415": { max: 1 }, + "12194": { max: 1 }, + "477509": { max: 1 }, + }, + FormatType: "Constructed", + mainDeckQuota: { min: 60, max: 250 }, + sideBoardQuota: { max: 15 }, + AllowedCommanderTitleIds: [], + }, + { + name: "OTJ", + legalSets: ["OTJ", "BIG"], + filterSets: ["OTJ", "BIG"], + bannedTitleIds: [], + suspendedTitleIds: [], + allowedTitleIds: [], + supressedTitleIds: [], individualCardQuotas: {}, FormatType: "Constructed", - mainDeckQuota: { - min: 60, - max: 250, - }, - sideBoardQuota: { - max: 15, - }, - useRebalancedCards: true, + mainDeckQuota: { min: 60, max: 250 }, + sideBoardQuota: { max: 15 }, AllowedCommanderTitleIds: [], }, { - name: "RetroHistoric", + name: "DirectGameAlchemy", legalSets: [ "2XM", "2X2", @@ -8712,6 +8580,7 @@ const formatsJson: FormatsJSON = { "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -8839,6 +8708,8 @@ const formatsJson: FormatsJSON = { "BLB", "BLC", "DSK", + "Y25", + "Y25_BLB", ], filterSets: [ "2XM", @@ -8873,6 +8744,7 @@ const formatsJson: FormatsJSON = { "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -9000,135 +8872,22 @@ const formatsJson: FormatsJSON = { "BLB", "BLC", "DSK", + "Y25_BLB", + "Y25", ], - bannedTitleIds: [1679], - suspendedTitleIds: [], - allowedTitleIds: [ - 4621, 4518, 16650, 3201, 2247, 30406, 174019, 46205, 46196, 10756, - 181582, 40351, 2071, 15139, 229520, 2700, 3675, 11338, 48571, 173891, - 48014, 17103, 3338, 38854, 29752, 41355, 25192, 15507, 41542, 42256, - 42260, 41578, 1275, 30140, 30138, 41594, 15530, 30142, 30133, 2227, - 47051, 29944, 2774, 45188, 49074, 227180, 76606, 51221, 910, 227373, - 229667, 10467, 76726, 26520, 19403, 2413, 46157, 46161, 46164, 10621, - 46171, 46184, 46190, 46193, 46202, 229363, 30707, 2541, 4390, 690, 1144, - 5798, 2265, 38039, 47634, 49397, 40466, 38733, 600, 7399, 43115, 434414, - 40011, 26143, 30, 45573, 9660, 18858, 3533, 10151, 229401, 40946, 28117, - 229405, 46992, 30737, 50365, 39370, 227044, 39494, 39054, 42772, 10517, - 47681, 3011, 40618, 11841, 2686, 48303, 46532, 40332, 39292, 227086, - 2692, 173624, 227090, 6734, 34772, 76414, 6961, 181639, 229460, 49556, - 16151, 229467, 9421, 181654, 51728, 42336, 229484, 30474, 50476, 2819, - 4056, 173671, 3628, 38408, 28962, 23526, 173681, 30625, 39223, 19825, - 7513, 44352, 173706, 49021, 40682, 40685, 12561, 39838, 24252, 29588, - 43295, 42833, 181700, 43898, 42836, 227158, 41064, 12218, 39519, 22989, - 76501, 40341, 229524, 45238, 48433, 40703, 42854, 76504, 8005, 28112, - 50504, 42857, 39997, 3673, 41774, 15652, 41086, 48444, 47188, 3070, - 2829, 1540, 39033, 229536, 42867, 46299, 49701, 38802, 52040, 1885, - 1639, 11612, 40039, 26774, 48458, 47843, 3291, 41094, 51155, 50540, - 42878, 3702, 48461, 40739, 76557, 17649, 11280, 41805, 23949, 25845, - 12359, 12368, 7207, 4951, 35991, 15754, 181754, 4051, 42885, 19645, - 49763, 2603, 227239, 47238, 25033, 41814, 227242, 41119, 45769, 229586, - 50593, 41830, 2437, 2323, 39226, 42916, 46709, 28275, 76611, 4596, - 14913, 3210, 45334, 43405, 39130, 23452, 46718, 3746, 229612, 7588, - 40774, 47291, 12744, 46340, 181798, 181801, 121660, 40782, 44476, 39537, - 5143, 2316, 45016, 17381, 229618, 41166, 38402, 2694, 17986, 841, 41860, - 51805, 229632, 30585, 40788, 229634, 3776, 1251, 44493, 2375, 46753, - 5557, 24916, 173829, 43448, 76667, 38413, 41876, 643, 40071, 43471, - 15198, 47331, 229645, 47969, 3786, 1601, 50705, 39599, 4317, 229664, - 76696, 50715, 42975, 4831, 23937, 227379, 51327, 47382, 18340, 28267, - 41226, 30023, 40536, 173888, 40102, 39572, 1035, 47997, 49210, 2329, - 42985, 37927, 7632, 43530, 125317, 181872, 51356, 39137, 2560, 76741, - 47433, 30243, 17686, 52106, 18496, 30342, 51371, 173917, 38452, 181895, - 30497, 8215, 76755, 31702, 43020, 30065, 261491, 685, 51861, 43026, - 173932, 434433, 50778, 610, 43031, 18614, 2753, 173939, 50074, 37979, - 34944, 25273, 18670, 30195, 14491, 43042, 14436, 48062, 41301, 42024, - 3240, 11480, 181982, 12588, 25861, 47562, 229765, 43044, 16495, 47571, - 10624, 18672, 5526, 48749, 434436, 5082, 1535, 1539, 19388, 32242, - 174010, 2024, 45504, 12536, 14319, 40228, 31228, 227574, 229791, 29574, - 46417, 30591, 2572, 13677, 4193, 27795, 1580, 5250, 48218, 229387, 5930, - 1283, 46976, 43141, 40600, 2177, 18689, 43795, 26180, 40390, 2181, 5091, - 42785, 43200, 4402, 3185, 39687, 47739, 39232, 229469, 18719, 41723, - 2259, 46590, 41736, 49621, 398, 42839, 18702, 4294, 5924, 229534, - 173751, 227203, 2240, 15743, 947, 763, 47887, 2419, 18754, 30807, 767, - 5993, 8293, 227328, 3783, 41879, 2221, 2597, 49921, 2748, 76725, 229697, - 13186, 227420, 40185, 45423, 125345, 49240, 3848, 43578, 181912, 40519, - 50810, 43683, 39932, 46129, 12539, 18826, 47597, 44665, 44668, 43722, - 43725, 43728, 261483, 51673, 40933, 229804, 40622, 2343, 229442, 2341, - 4889, 229811, 5215, 229527, 2179, 229573, 2648, 39348, 229630, 261489, - 4932, 2654, 229841, 4488, 125319, 18359, 18335, 1293, 46453, 2203, - 46236, 45557, 227011, 12197, 45564, 4214, 173572, 229429, 31558, 47707, - 2278, 2557, 45645, 6640, 125126, 984, 227152, 227183, 47825, 3129, - 21339, 47834, 173757, 19365, 41121, 30382, 125247, 51795, 39237, 2369, - 229639, 38998, 32681, 22721, 1656, 1016, 3242, 10851, 51858, 125333, - 4600, 39463, 10708, 8744, 50137, 45490, 32738, 227572, 229789, 10867, - 2853, 45524, 125321, 229708, 41969, 148, 10978, 29907, 24700, 41573, - 12837, 12807, 15550, 42264, 12780, 42267, 41588, 42271, 15499, 1769, - 45118, 23908, 32275, 4061, 5051, 43457, 30439, 39298, 174033, 43716, - 43719, 44192, 44195, 44198, 43731, 18841, 40642, 41757, 51230, 4987, - 4416, 227435, 11807, 32484, 4069, 430272, 4583, - ], - supressedTitleIds: [], - individualCardQuotas: {}, - FormatType: "Constructed", - mainDeckQuota: { - min: 60, - max: 250, - }, - sideBoardQuota: { - max: 7, - }, - useRebalancedCards: true, - AllowedCommanderTitleIds: [], - }, - { - name: "Tripleton", - legalSets: [ - "ANB", - "ANC", - "WOE", - "Y24", - "Y24_WOE", - "LCI", - "Y24_LCI", - "MKM", - "Y24_MKM", - "OTJ", - "BIG", - "Y24_OTJ", - "BLB", - ], - filterSets: [ - "ANB", - "ANC", - "WOE", - "Y24", - "Y24_WOE", - "LCI", - "Y24_LCI", - "MKM", - "Y24_MKM", - "OTJ", - "BIG", - "Y24_OTJ", - "BLB", - ], - bannedTitleIds: [498276, 437011, 437805, 545895, 437834], + bannedTitleIds: [], suspendedTitleIds: [], allowedTitleIds: [], supressedTitleIds: [], individualCardQuotas: {}, FormatType: "Constructed", - mainDeckQuota: { - min: 60, - max: 250, - }, - sideBoardQuota: { - max: 7, - }, + mainDeckQuota: { min: 60, max: 250 }, + sideBoardQuota: { max: 15 }, useRebalancedCards: true, AllowedCommanderTitleIds: [], }, { - name: "Historic", + name: "RetroHistoric", legalSets: [ "2XM", "2X2", @@ -9162,6 +8921,7 @@ const formatsJson: FormatsJSON = { "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -9289,6 +9049,8 @@ const formatsJson: FormatsJSON = { "BLB", "BLC", "DSK", + "Y25", + "Y25_BLB", ], filterSets: [ "2XM", @@ -9323,6 +9085,7 @@ const formatsJson: FormatsJSON = { "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -9450,181 +9213,84 @@ const formatsJson: FormatsJSON = { "BLB", "BLC", "DSK", + "Y25_BLB", + "Y25", ], - bannedTitleIds: [ - 351741, 38310, 429, 25409, 10522, 21415, 11851, 760, 4023, 12194, - 487177, 352244, 760465, 760127, 760330, 759990, 760245, 24807, 430376, - 487165, 487156, 760130, 7042, 20966, 1251, 20972, 38551, 6167, 11983, - 38526, 24870, 4244, 1679, 414260, 414166, 24837, 487169, 4051, 38497, - 36359, 36631, 487142, 38516, 487146, 2904, 419870, 477509, 2183, 420429, - 352113, 38622, 279929, 24888, 760689, 3179, - ], - suspendedTitleIds: [], - allowedTitleIds: [], - supressedTitleIds: [ - 38310, 25409, 11851, 487177, 760465, 760127, 760330, 759990, 760245, - 24807, 430376, 487165, 487156, 760130, 20972, 38551, 11983, 38526, - 24837, 4051, 38497, 36359, 487142, 487146, 38622, 24888, 760689, 3179, - ], - individualCardQuotas: {}, - FormatType: "Constructed", - mainDeckQuota: { - min: 60, - max: 250, - }, - sideBoardQuota: { - max: 7, - }, - useRebalancedCards: true, - AllowedCommanderTitleIds: [], - }, - { - name: "StandardTreasures", - legalSets: [ - "DMU", - "BRO", - "ONE", - "MOM", - "MAT", - "WOE", - "LCI", - "MKM", - "OTJ", - "BIG", - "BLB", - ], - filterSets: [ - "DMU", - "BRO", - "ONE", - "MOM", - "MAT", - "WOE", - "LCI", - "MKM", - "OTJ", - "BIG", - "BLB", - ], - bannedTitleIds: [ - 351741, 420056, 352244, 336177, 414577, 280078, 336824, 414260, 414166, - 352113, 352134, - ], - suspendedTitleIds: [], - allowedTitleIds: [], - supressedTitleIds: [], - individualCardQuotas: {}, - FormatType: "Constructed", - mainDeckQuota: { - min: 60, - max: 250, - }, - sideBoardQuota: { - max: 7, - }, - AllowedCommanderTitleIds: [], - }, - { - name: "Draft", - legalSets: [], - filterSets: [], - bannedTitleIds: [], + bannedTitleIds: [1679], suspendedTitleIds: [], - allowedTitleIds: [], - supressedTitleIds: [], - individualCardQuotas: {}, - cardCountRestriction: "UnrestrictedCardCounts", - FormatType: "Draft", - mainDeckQuota: { - min: 40, - max: 250, - }, - sideBoardQuota: { - max: 250, - }, - AllowedCommanderTitleIds: [], - }, - { - name: "TCConstructed", - legalSets: [ - "ANB", - "ANC", - "WOE", - "Y24", - "Y24_WOE", - "LCI", - "Y24_LCI", - "MKM", - "Y24_MKM", - "OTJ", - "BIG", - "Y24_OTJ", - "BLB", - ], - filterSets: [ - "ANB", - "ANC", - "WOE", - "Y24", - "Y24_WOE", - "LCI", - "Y24_LCI", - "MKM", - "Y24_MKM", - "OTJ", - "BIG", - "Y24_OTJ", - "BLB", + allowedTitleIds: [ + 4621, 4518, 16650, 3201, 2247, 30406, 174019, 46205, 46196, 10756, + 181582, 40351, 2071, 15139, 229520, 2700, 3675, 11338, 48571, 173891, + 48014, 17103, 3338, 38854, 29752, 41355, 25192, 15507, 41542, 42256, + 42260, 41578, 1275, 30140, 30138, 41594, 15530, 30142, 30133, 2227, + 47051, 29944, 2774, 45188, 49074, 227180, 76606, 51221, 910, 227373, + 229667, 10467, 76726, 26520, 19403, 2413, 46157, 46161, 46164, 10621, + 46171, 46184, 46190, 46193, 46202, 229363, 30707, 2541, 4390, 690, 1144, + 5798, 2265, 38039, 47634, 49397, 40466, 38733, 600, 7399, 43115, 434414, + 40011, 26143, 30, 45573, 9660, 18858, 3533, 10151, 229401, 40946, 28117, + 229405, 46992, 30737, 50365, 39370, 227044, 39494, 39054, 42772, 10517, + 47681, 3011, 40618, 11841, 2686, 48303, 46532, 40332, 39292, 227086, + 2692, 173624, 227090, 6734, 34772, 76414, 6961, 181639, 229460, 49556, + 16151, 229467, 9421, 181654, 51728, 42336, 229484, 30474, 50476, 2819, + 4056, 173671, 3628, 38408, 28962, 23526, 173681, 30625, 39223, 19825, + 7513, 44352, 173706, 49021, 40682, 40685, 12561, 39838, 24252, 29588, + 43295, 42833, 181700, 43898, 42836, 227158, 41064, 12218, 39519, 22989, + 76501, 40341, 229524, 45238, 48433, 40703, 42854, 76504, 8005, 28112, + 50504, 42857, 39997, 3673, 41774, 15652, 41086, 48444, 47188, 3070, + 2829, 1540, 39033, 229536, 42867, 46299, 49701, 38802, 52040, 1885, + 1639, 11612, 40039, 26774, 48458, 47843, 3291, 41094, 51155, 50540, + 42878, 3702, 48461, 40739, 76557, 17649, 11280, 41805, 23949, 25845, + 12359, 12368, 7207, 4951, 35991, 15754, 181754, 4051, 42885, 19645, + 49763, 2603, 227239, 47238, 25033, 41814, 227242, 41119, 45769, 229586, + 50593, 41830, 2437, 2323, 39226, 42916, 46709, 28275, 76611, 4596, + 14913, 3210, 45334, 43405, 39130, 23452, 46718, 3746, 229612, 7588, + 40774, 47291, 12744, 46340, 181798, 181801, 121660, 40782, 44476, 39537, + 5143, 2316, 45016, 17381, 229618, 41166, 38402, 2694, 17986, 841, 41860, + 51805, 229632, 30585, 40788, 229634, 3776, 1251, 44493, 2375, 46753, + 5557, 24916, 173829, 43448, 76667, 38413, 41876, 643, 40071, 43471, + 15198, 47331, 229645, 47969, 3786, 1601, 50705, 39599, 4317, 229664, + 76696, 50715, 42975, 4831, 23937, 227379, 51327, 47382, 18340, 28267, + 41226, 30023, 40536, 173888, 40102, 39572, 1035, 47997, 49210, 2329, + 42985, 37927, 7632, 43530, 125317, 181872, 51356, 39137, 2560, 76741, + 47433, 30243, 17686, 52106, 18496, 30342, 51371, 173917, 38452, 181895, + 30497, 8215, 76755, 31702, 43020, 30065, 261491, 685, 51861, 43026, + 173932, 434433, 50778, 610, 43031, 18614, 2753, 173939, 50074, 37979, + 34944, 25273, 18670, 30195, 14491, 43042, 14436, 48062, 41301, 42024, + 3240, 11480, 181982, 12588, 25861, 47562, 229765, 43044, 16495, 47571, + 10624, 18672, 5526, 48749, 434436, 5082, 1535, 1539, 19388, 32242, + 174010, 2024, 45504, 12536, 14319, 40228, 31228, 227574, 229791, 29574, + 46417, 30591, 2572, 13677, 4193, 27795, 1580, 5250, 48218, 229387, 5930, + 1283, 46976, 43141, 40600, 2177, 18689, 43795, 26180, 40390, 2181, 5091, + 42785, 43200, 4402, 3185, 39687, 47739, 39232, 229469, 18719, 41723, + 2259, 46590, 41736, 49621, 398, 42839, 18702, 4294, 5924, 229534, + 173751, 227203, 2240, 15743, 947, 763, 47887, 2419, 18754, 30807, 767, + 5993, 8293, 227328, 3783, 41879, 2221, 2597, 49921, 2748, 76725, 229697, + 13186, 227420, 40185, 45423, 125345, 49240, 3848, 43578, 181912, 40519, + 50810, 43683, 39932, 46129, 12539, 18826, 47597, 44665, 44668, 43722, + 43725, 43728, 261483, 51673, 40933, 229804, 40622, 2343, 229442, 2341, + 4889, 229811, 5215, 229527, 2179, 229573, 2648, 39348, 229630, 261489, + 4932, 2654, 229841, 4488, 125319, 18359, 18335, 1293, 46453, 2203, + 46236, 45557, 227011, 12197, 45564, 4214, 173572, 229429, 31558, 47707, + 2278, 2557, 45645, 6640, 125126, 984, 227152, 227183, 47825, 3129, + 21339, 47834, 173757, 19365, 41121, 30382, 125247, 51795, 39237, 2369, + 229639, 38998, 32681, 22721, 1656, 1016, 3242, 10851, 51858, 125333, + 4600, 39463, 10708, 8744, 50137, 45490, 32738, 227572, 229789, 10867, + 2853, 45524, 125321, 229708, 41969, 148, 10978, 29907, 24700, 41573, + 12837, 12807, 15550, 42264, 12780, 42267, 41588, 42271, 15499, 1769, + 45118, 23908, 32275, 4061, 5051, 43457, 30439, 39298, 174033, 43716, + 43719, 44192, 44195, 44198, 43731, 18841, 40642, 41757, 51230, 4987, + 4416, 227435, 11807, 32484, 4069, 430272, 4583, ], - bannedTitleIds: [], - suspendedTitleIds: [], - allowedTitleIds: [], - supressedTitleIds: [], - individualCardQuotas: {}, - FormatType: "Constructed", - mainDeckQuota: { - min: 60, - max: 250, - }, - sideBoardQuota: { - max: 15, - }, - AllowedCommanderTitleIds: [], - }, - { - name: "InnistradConstructed", - legalSets: ["MID", "VOW", "SIR", "SIS"], - filterSets: ["MID", "VOW", "SIR", "SIS"], - bannedTitleIds: [530112], - suspendedTitleIds: [], - allowedTitleIds: [], - supressedTitleIds: [530112], - individualCardQuotas: {}, - FormatType: "Constructed", - mainDeckQuota: { - min: 60, - max: 250, - }, - sideBoardQuota: { - max: 7, - }, - AllowedCommanderTitleIds: [], - }, - { - name: "AllZeroes", - legalSets: [], - filterSets: [], - bannedTitleIds: [], - suspendedTitleIds: [], - allowedTitleIds: [], supressedTitleIds: [], individualCardQuotas: {}, - cardCountRestriction: "UnrestrictedCardCounts", FormatType: "Constructed", + mainDeckQuota: { min: 60, max: 250 }, + sideBoardQuota: { max: 7 }, + useRebalancedCards: true, AllowedCommanderTitleIds: [], }, { - name: "TreasureSingleton", + name: "Tripleton", legalSets: [ "ANB", "ANC", @@ -9639,6 +9305,9 @@ const formatsJson: FormatsJSON = { "BIG", "Y24_OTJ", "BLB", + "Y25", + "Y25_BLB", + "DSK", ], filterSets: [ "ANB", @@ -9654,25 +9323,23 @@ const formatsJson: FormatsJSON = { "BIG", "Y24_OTJ", "BLB", + "Y25_BLB", + "Y25", + "DSK", ], - bannedTitleIds: [478018, 477471, 437805, 437834], + bannedTitleIds: [498276, 437011, 437805, 545895, 437834], suspendedTitleIds: [], allowedTitleIds: [], supressedTitleIds: [], individualCardQuotas: {}, - cardCountRestriction: "Singleton", FormatType: "Constructed", - mainDeckQuota: { - min: 60, - max: 250, - }, - sideBoardQuota: { - max: 7, - }, + mainDeckQuota: { min: 60, max: 250 }, + sideBoardQuota: { max: 7 }, + useRebalancedCards: true, AllowedCommanderTitleIds: [], }, { - name: "HistoricShakeup2", + name: "Historic", legalSets: [ "2XM", "2X2", @@ -9706,6 +9373,7 @@ const formatsJson: FormatsJSON = { "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -9833,6 +9501,8 @@ const formatsJson: FormatsJSON = { "BLB", "BLC", "DSK", + "Y25", + "Y25_BLB", ], filterSets: [ "2XM", @@ -9867,6 +9537,7 @@ const formatsJson: FormatsJSON = { "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -9994,30 +9665,33 @@ const formatsJson: FormatsJSON = { "BLB", "BLC", "DSK", + "Y25_BLB", + "Y25", ], bannedTitleIds: [ - 351741, 413974, 413710, 413986, 47395, 433909, 181639, 229682, 413992, - 477884, 352244, 414011, 5526, 28117, 279794, 433696, 428587, 434348, - 336832, 1679, 414260, 414166, 414172, 125065, 3236, 227513, 336891, - 17643, 477509, 420429, 352113, 279929, 428552, 414418, 428610, + 351741, 38310, 429, 25409, 10522, 21415, 11851, 760, 4023, 12194, + 487177, 352244, 760465, 760127, 760330, 759990, 760245, 24807, 430376, + 487165, 487156, 760130, 7042, 20966, 1251, 20972, 38551, 6167, 11983, + 38526, 24870, 4244, 1679, 414260, 414166, 24837, 487169, 4051, 38497, + 36359, 36631, 487142, 38516, 487146, 2904, 419870, 477509, 2183, 420429, + 352113, 38622, 279929, 24888, 760689, 3179, ], suspendedTitleIds: [], allowedTitleIds: [], - supressedTitleIds: [], + supressedTitleIds: [ + 38310, 25409, 11851, 487177, 760465, 760127, 760330, 759990, 760245, + 24807, 430376, 487165, 487156, 760130, 20972, 38551, 11983, 38526, + 24837, 4051, 38497, 36359, 487142, 487146, 38622, 24888, 760689, 3179, + ], individualCardQuotas: {}, FormatType: "Constructed", - mainDeckQuota: { - min: 60, - max: 250, - }, - sideBoardQuota: { - max: 7, - }, + mainDeckQuota: { min: 60, max: 250 }, + sideBoardQuota: { max: 7 }, useRebalancedCards: true, AllowedCommanderTitleIds: [], }, { - name: "StandardGiantMonsters", + name: "StandardTreasures", legalSets: [ "DMU", "BRO", @@ -10030,6 +9704,7 @@ const formatsJson: FormatsJSON = { "OTJ", "BIG", "BLB", + "DSK", ], filterSets: [ "DMU", @@ -10043,81 +9718,162 @@ const formatsJson: FormatsJSON = { "OTJ", "BIG", "BLB", + "DSK", + ], + bannedTitleIds: [ + 351741, 420056, 352244, 336177, 414577, 280078, 336824, 414260, 414166, + 352113, 352134, ], - bannedTitleIds: [352244, 336370, 414260, 414166, 352113], suspendedTitleIds: [], allowedTitleIds: [], supressedTitleIds: [], individualCardQuotas: {}, FormatType: "Constructed", - mainDeckQuota: { - min: 60, - max: 250, - }, - sideBoardQuota: { - max: 7, - }, + mainDeckQuota: { min: 60, max: 250 }, + sideBoardQuota: { max: 7 }, AllowedCommanderTitleIds: [], }, { - name: "MOM", - legalSets: ["MOM"], - filterSets: ["MOM"], + name: "Draft", + legalSets: [], + filterSets: [], bannedTitleIds: [], suspendedTitleIds: [], allowedTitleIds: [], supressedTitleIds: [], individualCardQuotas: {}, - FormatType: "Constructed", - mainDeckQuota: { - min: 60, - max: 250, - }, - sideBoardQuota: { - max: 15, - }, + cardCountRestriction: "UnrestrictedCardCounts", + FormatType: "Draft", + mainDeckQuota: { min: 40, max: 250 }, + sideBoardQuota: { max: 250 }, AllowedCommanderTitleIds: [], }, { - name: "MH3", - legalSets: ["MH3"], - filterSets: ["MH3"], - bannedTitleIds: [], + name: "TCConstructed", + legalSets: [ + "ANB", + "ANC", + "WOE", + "Y24", + "Y24_WOE", + "LCI", + "Y24_LCI", + "MKM", + "Y24_MKM", + "OTJ", + "BIG", + "Y24_OTJ", + "BLB", + "Y25", + "Y25_BLB", + "DSK", + ], + filterSets: [ + "ANB", + "ANC", + "WOE", + "Y24", + "Y24_WOE", + "LCI", + "Y24_LCI", + "MKM", + "Y24_MKM", + "OTJ", + "BIG", + "Y24_OTJ", + "BLB", + "Y25_BLB", + "Y25", + "DSK", + ], + bannedTitleIds: [], suspendedTitleIds: [], allowedTitleIds: [], supressedTitleIds: [], individualCardQuotas: {}, FormatType: "Constructed", - mainDeckQuota: { - min: 60, - max: 250, - }, - sideBoardQuota: { - max: 15, - }, + mainDeckQuota: { min: 60, max: 250 }, + sideBoardQuota: { max: 15 }, AllowedCommanderTitleIds: [], }, { - name: "LCI", - legalSets: ["LCI"], - filterSets: ["LCI"], + name: "InnistradConstructed", + legalSets: ["MID", "VOW", "SIR", "SIS"], + filterSets: ["MID", "VOW", "SIR", "SIS"], + bannedTitleIds: [530112], + suspendedTitleIds: [], + allowedTitleIds: [], + supressedTitleIds: [530112], + individualCardQuotas: {}, + FormatType: "Constructed", + mainDeckQuota: { min: 60, max: 250 }, + sideBoardQuota: { max: 7 }, + AllowedCommanderTitleIds: [], + }, + { + name: "AllZeroes", + legalSets: [], + filterSets: [], bannedTitleIds: [], suspendedTitleIds: [], allowedTitleIds: [], supressedTitleIds: [], individualCardQuotas: {}, + cardCountRestriction: "UnrestrictedCardCounts", FormatType: "Constructed", - mainDeckQuota: { - min: 60, - max: 250, - }, - sideBoardQuota: { - max: 15, - }, AllowedCommanderTitleIds: [], }, { - name: "HistoricCascadeAndChimil", + name: "TreasureSingleton", + legalSets: [ + "ANB", + "ANC", + "WOE", + "Y24", + "Y24_WOE", + "LCI", + "Y24_LCI", + "MKM", + "Y24_MKM", + "OTJ", + "BIG", + "Y24_OTJ", + "BLB", + "Y25", + "Y25_BLB", + "DSK", + ], + filterSets: [ + "ANB", + "ANC", + "WOE", + "Y24", + "Y24_WOE", + "LCI", + "Y24_LCI", + "MKM", + "Y24_MKM", + "OTJ", + "BIG", + "Y24_OTJ", + "BLB", + "Y25_BLB", + "Y25", + "DSK", + ], + bannedTitleIds: [478018, 477471, 437805, 437834], + suspendedTitleIds: [], + allowedTitleIds: [], + supressedTitleIds: [], + individualCardQuotas: {}, + cardCountRestriction: "Singleton", + FormatType: "Constructed", + mainDeckQuota: { min: 60, max: 250 }, + sideBoardQuota: { max: 7 }, + AllowedCommanderTitleIds: [], + }, + { + name: "HistoricShakeup2", legalSets: [ "2XM", "2X2", @@ -10151,6 +9907,7 @@ const formatsJson: FormatsJSON = { "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -10278,6 +10035,8 @@ const formatsJson: FormatsJSON = { "BLB", "BLC", "DSK", + "Y25", + "Y25_BLB", ], filterSets: [ "2XM", @@ -10312,6 +10071,7 @@ const formatsJson: FormatsJSON = { "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -10439,82 +10199,109 @@ const formatsJson: FormatsJSON = { "BLB", "BLC", "DSK", + "Y25_BLB", + "Y25", ], bannedTitleIds: [ - 543133, 543133, 351741, 436934, 38310, 756034, 429, 25409, 703039, - 703039, 10522, 21415, 11851, 760, 4023, 413629, 12194, 427904, 487177, - 352244, 760465, 760127, 760330, 759990, 760245, 24807, 430376, 487165, - 487156, 760130, 756077, 7042, 20966, 280078, 1251, 20972, 38551, 6167, - 11983, 38526, 24870, 4244, 1679, 414260, 414166, 701908, 24837, 487169, - 4051, 437527, 5091, 38497, 36359, 36631, 487142, 683716, 683716, 38516, - 487146, 2904, 336891, 336891, 419870, 477509, 2183, 420429, 352113, - 38622, 760685, 279929, 24888, 760689, 3179, + 351741, 413974, 413710, 413986, 47395, 433909, 181639, 229682, 413992, + 477884, 352244, 414011, 5526, 28117, 279794, 433696, 428587, 434348, + 336832, 1679, 414260, 414166, 414172, 125065, 3236, 227513, 336891, + 17643, 477509, 420429, 352113, 279929, 428552, 414418, 428610, ], suspendedTitleIds: [], allowedTitleIds: [], supressedTitleIds: [], individualCardQuotas: {}, FormatType: "Constructed", - mainDeckQuota: { - min: 60, - max: 250, - }, - sideBoardQuota: { - max: 7, - }, + mainDeckQuota: { min: 60, max: 250 }, + sideBoardQuota: { max: 7 }, useRebalancedCards: true, AllowedCommanderTitleIds: [], }, { - name: "Cascade", + name: "StandardGiantMonsters", legalSets: [ - "ANB", - "ANC", + "DMU", + "BRO", + "ONE", + "MOM", + "MAT", "WOE", - "Y24", - "Y24_WOE", "LCI", - "Y24_LCI", "MKM", - "Y24_MKM", "OTJ", "BIG", - "Y24_OTJ", "BLB", + "DSK", ], filterSets: [ - "ANB", - "ANC", + "DMU", + "BRO", + "ONE", + "MOM", + "MAT", "WOE", - "Y24", - "Y24_WOE", "LCI", - "Y24_LCI", "MKM", - "Y24_MKM", "OTJ", "BIG", - "Y24_OTJ", "BLB", + "DSK", ], - bannedTitleIds: [701908, 683716, 3142], + bannedTitleIds: [352244, 336370, 414260, 414166, 352113], suspendedTitleIds: [], allowedTitleIds: [], - supressedTitleIds: [3142], + supressedTitleIds: [], individualCardQuotas: {}, FormatType: "Constructed", - mainDeckQuota: { - min: 60, - max: 250, - }, - sideBoardQuota: { - max: 7, - }, - useRebalancedCards: true, + mainDeckQuota: { min: 60, max: 250 }, + sideBoardQuota: { max: 7 }, AllowedCommanderTitleIds: [], }, { - name: "HistoricAprilFoolLimited", + name: "MOM", + legalSets: ["MOM"], + filterSets: ["MOM"], + bannedTitleIds: [], + suspendedTitleIds: [], + allowedTitleIds: [], + supressedTitleIds: [], + individualCardQuotas: {}, + FormatType: "Constructed", + mainDeckQuota: { min: 60, max: 250 }, + sideBoardQuota: { max: 15 }, + AllowedCommanderTitleIds: [], + }, + { + name: "MH3", + legalSets: ["MH3"], + filterSets: ["MH3"], + bannedTitleIds: [], + suspendedTitleIds: [], + allowedTitleIds: [], + supressedTitleIds: [], + individualCardQuotas: {}, + FormatType: "Constructed", + mainDeckQuota: { min: 60, max: 250 }, + sideBoardQuota: { max: 15 }, + AllowedCommanderTitleIds: [], + }, + { + name: "LCI", + legalSets: ["LCI"], + filterSets: ["LCI"], + bannedTitleIds: [], + suspendedTitleIds: [], + allowedTitleIds: [], + supressedTitleIds: [], + individualCardQuotas: {}, + FormatType: "Constructed", + mainDeckQuota: { min: 60, max: 250 }, + sideBoardQuota: { max: 15 }, + AllowedCommanderTitleIds: [], + }, + { + name: "HistoricCascadeAndChimil", legalSets: [ "2XM", "2X2", @@ -10548,6 +10335,7 @@ const formatsJson: FormatsJSON = { "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -10675,6 +10463,8 @@ const formatsJson: FormatsJSON = { "BLB", "BLC", "DSK", + "Y25", + "Y25_BLB", ], filterSets: [ "2XM", @@ -10709,6 +10499,7 @@ const formatsJson: FormatsJSON = { "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -10836,26 +10627,80 @@ const formatsJson: FormatsJSON = { "BLB", "BLC", "DSK", + "Y25_BLB", + "Y25", + ], + bannedTitleIds: [ + 543133, 543133, 351741, 436934, 38310, 756034, 429, 25409, 703039, + 703039, 10522, 21415, 11851, 760, 4023, 413629, 12194, 427904, 487177, + 352244, 760465, 760127, 760330, 759990, 760245, 24807, 430376, 487165, + 487156, 760130, 756077, 7042, 20966, 280078, 1251, 20972, 38551, 6167, + 11983, 38526, 24870, 4244, 1679, 414260, 414166, 701908, 24837, 487169, + 4051, 437527, 5091, 38497, 36359, 36631, 487142, 683716, 683716, 38516, + 487146, 2904, 336891, 336891, 419870, 477509, 2183, 420429, 352113, + 38622, 760685, 279929, 24888, 760689, 3179, ], - bannedTitleIds: [], suspendedTitleIds: [], allowedTitleIds: [], supressedTitleIds: [], individualCardQuotas: {}, - cardCountRestriction: "UnrestrictedCardCounts", FormatType: "Constructed", - mainDeckQuota: { - min: 40, - max: 250, - }, - sideBoardQuota: { - max: 7, - }, + mainDeckQuota: { min: 60, max: 250 }, + sideBoardQuota: { max: 7 }, useRebalancedCards: true, AllowedCommanderTitleIds: [], }, { - name: "HistoricPauper", + name: "Cascade", + legalSets: [ + "ANB", + "ANC", + "WOE", + "Y24", + "Y24_WOE", + "LCI", + "Y24_LCI", + "MKM", + "Y24_MKM", + "OTJ", + "BIG", + "Y24_OTJ", + "BLB", + "Y25", + "Y25_BLB", + "DSK", + ], + filterSets: [ + "ANB", + "ANC", + "WOE", + "Y24", + "Y24_WOE", + "LCI", + "Y24_LCI", + "MKM", + "Y24_MKM", + "OTJ", + "BIG", + "Y24_OTJ", + "BLB", + "Y25_BLB", + "Y25", + "DSK", + ], + bannedTitleIds: [701908, 683716, 3142], + suspendedTitleIds: [], + allowedTitleIds: [], + supressedTitleIds: [3142], + individualCardQuotas: {}, + FormatType: "Constructed", + mainDeckQuota: { min: 60, max: 250 }, + sideBoardQuota: { max: 7 }, + useRebalancedCards: true, + AllowedCommanderTitleIds: [], + }, + { + name: "HistoricAprilFoolLimited", legalSets: [ "2XM", "2X2", @@ -10889,6 +10734,7 @@ const formatsJson: FormatsJSON = { "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -11016,6 +10862,8 @@ const formatsJson: FormatsJSON = { "BLB", "BLC", "DSK", + "Y25", + "Y25_BLB", ], filterSets: [ "2XM", @@ -11050,6 +10898,7 @@ const formatsJson: FormatsJSON = { "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -11177,102 +11026,23 @@ const formatsJson: FormatsJSON = { "BLB", "BLC", "DSK", + "Y25_BLB", + "Y25", ], - bannedTitleIds: [279584], + bannedTitleIds: [], suspendedTitleIds: [], allowedTitleIds: [], supressedTitleIds: [], individualCardQuotas: {}, + cardCountRestriction: "UnrestrictedCardCounts", FormatType: "Constructed", - mainDeckQuota: { - min: 60, - max: 250, - }, - sideBoardQuota: { - max: 7, - }, + mainDeckQuota: { min: 40, max: 250 }, + sideBoardQuota: { max: 7 }, useRebalancedCards: true, AllowedCommanderTitleIds: [], }, { - name: "BaldursGate", - legalSets: ["HBG"], - filterSets: ["HBG"], - bannedTitleIds: [], - suspendedTitleIds: [], - allowedTitleIds: [], - supressedTitleIds: [], - individualCardQuotas: {}, - FormatType: "Constructed", - mainDeckQuota: { - min: 60, - max: 250, - }, - sideBoardQuota: { - max: 7, - }, - useRebalancedCards: true, - AllowedCommanderTitleIds: [], - }, - { - name: "ONE", - legalSets: ["ONE"], - filterSets: ["ONE"], - bannedTitleIds: [], - suspendedTitleIds: [], - allowedTitleIds: [], - supressedTitleIds: [], - individualCardQuotas: {}, - FormatType: "Constructed", - mainDeckQuota: { - min: 60, - max: 250, - }, - sideBoardQuota: { - max: 15, - }, - AllowedCommanderTitleIds: [], - }, - { - name: "AdventuresintheForgottenRealms", - legalSets: ["AFR"], - filterSets: ["AFR"], - bannedTitleIds: [], - suspendedTitleIds: [], - allowedTitleIds: [], - supressedTitleIds: [], - individualCardQuotas: {}, - FormatType: "Constructed", - mainDeckQuota: { - min: 60, - max: 250, - }, - sideBoardQuota: { - max: 7, - }, - AllowedCommanderTitleIds: [], - }, - { - name: "Theros", - legalSets: ["THB"], - filterSets: ["THB"], - bannedTitleIds: [], - suspendedTitleIds: [], - allowedTitleIds: [], - supressedTitleIds: [], - individualCardQuotas: {}, - FormatType: "Constructed", - mainDeckQuota: { - min: 60, - max: 250, - }, - sideBoardQuota: { - max: 7, - }, - AllowedCommanderTitleIds: [], - }, - { - name: "PreHistoricTEST", + name: "HistoricPauper", legalSets: [ "2XM", "2X2", @@ -11306,6 +11076,7 @@ const formatsJson: FormatsJSON = { "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -11433,6 +11204,8 @@ const formatsJson: FormatsJSON = { "BLB", "BLC", "DSK", + "Y25", + "Y25_BLB", ], filterSets: [ "2XM", @@ -11467,6 +11240,7 @@ const formatsJson: FormatsJSON = { "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -11594,125 +11368,93 @@ const formatsJson: FormatsJSON = { "BLB", "BLC", "DSK", + "Y25_BLB", + "Y25", ], - bannedTitleIds: [ - 351741, 429, 10522, 21415, 4023, 12194, 352244, 7042, 20966, 6167, - 11983, 24870, 1679, 414260, 414166, 487169, 36631, 38516, 2904, 419870, - 477509, 2183, 420429, 352113, 279929, - ], + bannedTitleIds: [279584], suspendedTitleIds: [], allowedTitleIds: [], - supressedTitleIds: [11983], - individualCardQuotas: { - "1251": { - max: 1, - }, - "4244": { - max: 2, - }, - "760": { - max: 3, - }, - }, + supressedTitleIds: [], + individualCardQuotas: {}, FormatType: "Constructed", - mainDeckQuota: { - min: 60, - max: 250, - }, - sideBoardQuota: { - max: 7, - }, + mainDeckQuota: { min: 60, max: 250 }, + sideBoardQuota: { max: 7 }, useRebalancedCards: true, AllowedCommanderTitleIds: [], }, { - name: "CascadeSingleton", - legalSets: [ - "ANB", - "ANC", - "WOE", - "Y24", - "Y24_WOE", - "LCI", - "Y24_LCI", - "MKM", - "Y24_MKM", - "OTJ", - "BIG", - "Y24_OTJ", - "BLB", - ], - filterSets: [ - "ANB", - "ANC", - "WOE", - "Y24", - "Y24_WOE", - "LCI", - "Y24_LCI", - "MKM", - "Y24_MKM", - "OTJ", - "BIG", - "Y24_OTJ", - "BLB", - ], - bannedTitleIds: [436934, 437805], + name: "BaldursGate", + legalSets: ["HBG"], + filterSets: ["HBG"], + bannedTitleIds: [], suspendedTitleIds: [], allowedTitleIds: [], supressedTitleIds: [], individualCardQuotas: {}, - cardCountRestriction: "Singleton", FormatType: "Constructed", - mainDeckQuota: { - min: 60, - max: 250, - }, - sideBoardQuota: { - max: 7, - }, + mainDeckQuota: { min: 60, max: 250 }, + sideBoardQuota: { max: 7 }, + useRebalancedCards: true, AllowedCommanderTitleIds: [], }, { - name: "NeonDynasty", - legalSets: ["NEO"], - filterSets: ["NEO"], + name: "ONE", + legalSets: ["ONE"], + filterSets: ["ONE"], bannedTitleIds: [], suspendedTitleIds: [], allowedTitleIds: [], supressedTitleIds: [], individualCardQuotas: {}, FormatType: "Constructed", - mainDeckQuota: { - min: 60, - max: 250, - }, - sideBoardQuota: { - max: 7, - }, + mainDeckQuota: { min: 60, max: 250 }, + sideBoardQuota: { max: 15 }, AllowedCommanderTitleIds: [], }, { - name: "Ravnica", - legalSets: ["GRN", "RNA", "WAR"], - filterSets: ["GRN", "RNA", "WAR"], - bannedTitleIds: [279773], + name: "DSK", + legalSets: ["DSK"], + filterSets: ["DSK"], + bannedTitleIds: [], suspendedTitleIds: [], allowedTitleIds: [], supressedTitleIds: [], individualCardQuotas: {}, FormatType: "Constructed", - mainDeckQuota: { - min: 60, - max: 250, - }, - sideBoardQuota: { - max: 15, - }, + mainDeckQuota: { min: 60, max: 250 }, + sideBoardQuota: { max: 15 }, AllowedCommanderTitleIds: [], }, { - name: "HistoricBrawlWithAllowList_20240604", + name: "AdventuresintheForgottenRealms", + legalSets: ["AFR"], + filterSets: ["AFR"], + bannedTitleIds: [], + suspendedTitleIds: [], + allowedTitleIds: [], + supressedTitleIds: [], + individualCardQuotas: {}, + FormatType: "Constructed", + mainDeckQuota: { min: 60, max: 250 }, + sideBoardQuota: { max: 7 }, + AllowedCommanderTitleIds: [], + }, + { + name: "Theros", + legalSets: ["THB"], + filterSets: ["THB"], + bannedTitleIds: [], + suspendedTitleIds: [], + allowedTitleIds: [], + supressedTitleIds: [], + individualCardQuotas: {}, + FormatType: "Constructed", + mainDeckQuota: { min: 60, max: 250 }, + sideBoardQuota: { max: 7 }, + AllowedCommanderTitleIds: [], + }, + { + name: "PreHistoricTEST", legalSets: [ "2XM", "2X2", @@ -11746,6 +11488,7 @@ const formatsJson: FormatsJSON = { "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -11873,6 +11616,8 @@ const formatsJson: FormatsJSON = { "BLB", "BLC", "DSK", + "Y25", + "Y25_BLB", ], filterSets: [ "2XM", @@ -11907,6 +11652,7 @@ const formatsJson: FormatsJSON = { "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -12034,42 +11780,30 @@ const formatsJson: FormatsJSON = { "BLB", "BLC", "DSK", + "Y25_BLB", + "Y25", ], bannedTitleIds: [ - 351741, 24405, 21415, 12194, 427904, 352244, 76334, 428590, 8628, 24870, - 1679, 414260, 19674, 5159, 31558, 174019, 26717, 46453, + 351741, 429, 10522, 21415, 4023, 12194, 352244, 7042, 20966, 6167, + 11983, 24870, 1679, 414260, 414166, 487169, 36631, 38516, 2904, 419870, + 477509, 2183, 420429, 352113, 279929, ], suspendedTitleIds: [], allowedTitleIds: [], - supressedTitleIds: [], - individualCardQuotas: {}, - cardCountRestriction: "Singleton", - FormatType: "Constructed", - mainDeckQuota: { - min: 99, - max: 99, - }, - sideBoardQuota: { - max: 1, - }, - commandZoneQuota: { - min: 1, - max: 1, + supressedTitleIds: [11983], + individualCardQuotas: { + "1251": { max: 1 }, + "4244": { max: 2 }, + "760": { max: 3 }, }, - sideboardBehavior: "CompanionOnly", + FormatType: "Constructed", + mainDeckQuota: { min: 60, max: 250 }, + sideBoardQuota: { max: 7 }, useRebalancedCards: true, - AllowedCommanderTitleIds: [ - 610848, 610850, 610852, 610854, 610856, 673942, 756700, 557291, 229729, - 557791, 488767, 10846, 1455, 227472, 676042, 351960, 498623, 433919, - 488856, 498276, 702732, 498290, 498850, 498463, 557666, 557514, 604458, - 414577, 558053, 557372, 229634, 604702, 604500, 498319, 336834, 125391, - 229741, 336840, 749062, 273039, 704259, 499042, 229747, 618947, 615236, - 336638, 1648, 229641, 45839, 548242, 489003, 610846, 32844, 489040, - 604461, 499212, 336181, 229760, 489056, 227363, 567811, 702887, - ], + AllowedCommanderTitleIds: [], }, { - name: "Singleton", + name: "CascadeSingleton", legalSets: [ "ANB", "ANC", @@ -12084,6 +11818,9 @@ const formatsJson: FormatsJSON = { "BIG", "Y24_OTJ", "BLB", + "Y25", + "Y25_BLB", + "DSK", ], filterSets: [ "ANB", @@ -12099,270 +11836,699 @@ const formatsJson: FormatsJSON = { "BIG", "Y24_OTJ", "BLB", + "Y25_BLB", + "Y25", + "DSK", ], - bannedTitleIds: [], + bannedTitleIds: [436934, 437805], suspendedTitleIds: [], allowedTitleIds: [], supressedTitleIds: [], individualCardQuotas: {}, cardCountRestriction: "Singleton", FormatType: "Constructed", - mainDeckQuota: { - min: 60, - max: 250, - }, - sideBoardQuota: { - max: 7, - }, - useRebalancedCards: true, + mainDeckQuota: { min: 60, max: 250 }, + sideBoardQuota: { max: 7 }, AllowedCommanderTitleIds: [], }, { - name: "ArtisanFuture", - legalSets: ["ANB", "ANC", "HBG", "MID", "NEO", "SNC", "VOW", "Y22"], - filterSets: ["ANB", "ANC", "HBG", "MID", "NEO", "SNC", "VOW", "Y22"], - bannedTitleIds: [413858, 413858, 428554], + name: "NeonDynasty", + legalSets: ["NEO"], + filterSets: ["NEO"], + bannedTitleIds: [], suspendedTitleIds: [], allowedTitleIds: [], supressedTitleIds: [], individualCardQuotas: {}, FormatType: "Constructed", - mainDeckQuota: { - min: 60, - max: 250, - }, - sideBoardQuota: { - max: 7, - }, + mainDeckQuota: { min: 60, max: 250 }, + sideBoardQuota: { max: 7 }, AllowedCommanderTitleIds: [], }, { - name: "IdentityTest", - legalSets: [ - "ANB", - "ANC", - "WOE", - "Y24", - "Y24_WOE", - "LCI", - "Y24_LCI", - "MKM", - "Y24_MKM", - "OTJ", - "BIG", - "Y24_OTJ", - "BLB", - ], - filterSets: [ - "ANB", - "ANC", - "WOE", - "Y24", - "Y24_WOE", - "LCI", - "Y24_LCI", - "MKM", - "Y24_MKM", - "OTJ", - "BIG", - "Y24_OTJ", - "BLB", - ], - bannedTitleIds: [], + name: "Ravnica", + legalSets: ["GRN", "RNA", "WAR"], + filterSets: ["GRN", "RNA", "WAR"], + bannedTitleIds: [279773], suspendedTitleIds: [], allowedTitleIds: [], supressedTitleIds: [], individualCardQuotas: {}, FormatType: "Constructed", - mainDeckQuota: { - min: 60, - max: 250, - }, - sideBoardQuota: { - max: 7, - }, - useRebalancedCards: true, + mainDeckQuota: { min: 60, max: 250 }, + sideBoardQuota: { max: 15 }, AllowedCommanderTitleIds: [], }, { - name: "Explorer", + name: "HistoricBrawlWithAllowList_20240604", legalSets: [ + "2XM", + "2X2", + "8ED", + "A25", "AER", "AFR", "AKH", + "AKR", + "ALA", + "ANA", + "ANB", + "ARB", + "AVR", "BFZ", "BNG", + "C18", + "C20", + "C21", + "CC2", + "CHK", + "CM2", + "CMR", + "CONF", + "CSP", "DAR", "DGM", + "DKA", "DMU", + "DST", "DTK", "ELD", "EMN", + "FDN", "FRF", + "G18", "GRN", "GTC", + "HBG", "HOU", "IKO", + "IMA", + "INV", + "ISD", + "J21", + "JMP", "JOU", + "JUD", "KHM", - "KLD", + "KLR", "KTK", + "LGN", + "LRW", + "M10", + "M11", + "M12", + "M13", "M14", "M15", "M19", "M20", "M21", + "MBS", + "MH1", + "MH2", "MID", + "MMA", + "MMQ", + "MOR", + "MRD", + "NEC", "NEO", + "NPH", + "ODY", "OGW", + "ONS", "ORI", + "PLC", + "RAV", "RIX", "RNA", + "ROE", "RTR", + "SCG", + "SHM", "SNC", "SOI", + "SOK", + "SOM", + "STA", "STX", "THB", "THS", + "TOR", + "TSP", + "USG", + "UMA", "VOW", + "W17", "WAR", + "WTH", + "WWK", "XLN", + "Y22", + "Y23", + "ZEN", "ZNR", "BRO", + "BRR", "ONE", "SIR", + "SIS", + "MUL", "MOM", + "MOC", "MAT", + "LTR", "WOE", + "WOT", + "LCI", + "AHA1", + "AHA2", + "AHA3", + "AHA4", + "AHA5", + "AHA6", + "AHA7", "EA1", "EA2", "EA3", - "LCI", + "Y23_ONE", + "Y23_BRO", + "Y23_DMU", + "Y22_SNC", + "Y22_NEO", + "Y22_MID", + "Y24_WOE", + "Y24", + "LCC", + "Y24_LCI", "MKM", - "BIG", "OTJ", + "Y24_MKM", + "SPG", + "KLD", + "APC", + "CLB", + "C16", + "DIS", + "DDU", + "MH3", + "OTP", + "OTC", + "BIG", + "OTC", + "Y24_OTJ", + "MH3", + "M3C", "BLB", + "BLC", + "DSK", + "Y25", + "Y25_BLB", ], filterSets: [ + "2XM", + "2X2", + "8ED", + "A25", "AER", "AFR", "AKH", + "AKR", + "ALA", + "ANA", + "ANB", + "ARB", + "AVR", "BFZ", "BNG", + "C18", + "C20", + "C21", + "CC2", + "CHK", + "CM2", + "CMR", + "CONF", + "CSP", "DAR", "DGM", + "DKA", "DMU", + "DST", "DTK", "ELD", "EMN", + "FDN", "FRF", + "G18", "GRN", "GTC", + "HBG", "HOU", "IKO", + "IMA", + "INV", + "ISD", + "J21", + "JMP", "JOU", + "JUD", "KHM", - "KLD", + "KLR", "KTK", + "LGN", + "LRW", + "M10", + "M11", + "M12", + "M13", "M14", "M15", "M19", "M20", "M21", + "MBS", + "MH1", + "MH2", "MID", + "MMA", + "MMQ", + "MOR", + "MRD", + "NEC", "NEO", + "NPH", + "ODY", "OGW", + "ONS", "ORI", + "PLC", + "RAV", "RIX", "RNA", + "ROE", "RTR", + "SCG", + "SHM", "SNC", "SOI", + "SOK", + "SOM", + "STA", "STX", "THB", "THS", + "TOR", + "TSP", + "USG", + "UMA", "VOW", + "W17", "WAR", + "WTH", + "WWK", "XLN", + "Y22", + "Y23", + "ZEN", "ZNR", "BRO", + "BRR", "ONE", "SIR", + "SIS", + "MUL", "MOM", + "MOC", "MAT", + "LTR", "WOE", + "WOT", + "LCI", + "AHA1", + "AHA2", + "AHA3", + "AHA4", + "AHA5", + "AHA6", + "AHA7", "EA1", "EA2", "EA3", - "AKR", - "KLR", - "LCI", + "Y23_ONE", + "Y23_BRO", + "Y23_DMU", + "Y22_SNC", + "Y22_NEO", + "Y22_MID", + "Y24_WOE", + "Y24", + "LCC", + "Y24_LCI", "MKM", - "BIG", "OTJ", + "Y24_MKM", "SPG", + "KLD", + "APC", + "CLB", + "C16", + "DIS", + "DDU", + "MH3", + "OTP", + "OTC", + "BIG", + "OTC", + "Y24_OTJ", + "MH3", + "M3C", "BLB", + "BLC", + "DSK", + "Y25_BLB", + "Y25", ], bannedTitleIds: [ - 38310, 25409, 488847, 352244, 24807, 737615, 336177, 352156, 352080, - 428587, 38551, 38526, 1679, 414260, 414166, 24837, 38497, 336891, - 477509, 420184, 420429, 352113, 38622, 279929, 24888, 428552, 3179, + 351741, 24405, 21415, 12194, 427904, 352244, 76334, 428590, 8628, 24870, + 1679, 414260, 19674, 5159, 31558, 174019, 26717, 46453, ], suspendedTitleIds: [], - allowedTitleIds: [ - 125456, 47893, 50590, 45937, 125232, 41292, 50257, 45940, 46108, 45540, - 45943, 45544, 45946, 32614, 125155, 3662, 2323, 41908, 125012, 50409, - 125085, 50913, 51696, 52060, 51613, 51978, 51006, 52031, 52003, 51010, - 1859, 51109, 1977, 52200, 1815, 52097, 1901, 1981, 76797, 76600, 3799, - 45546, 45779, 51702, 51889, 18841, 45550, 50602, 46703, 51985, 51752, - 3665, 2082, 46112, 39065, 3878, 3497, 125157, 46939, 45949, 47562, - 48984, 50918, 76298, 125017, 1144, 48218, 49373, 43399, 261485, 50093, - 1984, 45953, 24122, 76301, 76303, 47051, 43683, 3502, 125429, 1926, - 76306, 51320, 25159, 3505, 47628, 45863, 76496, 3888, 3881, 45956, - 51327, 45782, 76402, 45785, 50160, 41064, 47382, 50605, 1592, 49666, - 47493, 51330, 51990, 41301, 41984, 50857, 50920, 3508, 3735, 45959, - 76405, 14901, 125019, 76800, 50923, 45866, 3653, 41573, 18919, 76498, - 51488, 1769, 51747, 52006, 45788, 42916, 51957, 51673, 51491, 46709, - 795, 4943, 76603, 43612, 45962, 3580, 45868, 50608, 45328, 45695, - 125307, 43209, 76309, 49675, 45697, 125309, 39519, 76606, 960, 47634, - 76501, 41627, 45619, 12837, 45238, 50611, 48433, 50721, 46157, 2076, - 45793, 50817, 40703, 76609, 49799, 76611, 45700, 51616, 51333, 46161, - 125235, 2792, 42854, 3210, 51494, 1991, 48100, 76504, 11532, 8005, 3185, - 2763, 76507, 125167, 76904, 41996, 45334, 43405, 41630, 42256, 50300, - 50617, 987, 2036, 3517, 3906, 44382, 2766, 2065, 45479, 43213, 42447, - 12807, 3802, 46115, 45796, 1929, 966, 41226, 49134, 43044, 50926, 51218, - 45799, 3738, 125238, 42194, 43688, 45965, 76615, 3520, 3805, 3668, 2278, - 646, 45802, 76953, 48437, 76510, 76408, 76312, 76705, 76618, 121693, - 76315, 1823, 49397, 51221, 4941, 50504, 76410, 51017, 50507, 76707, - 125090, 42928, 51224, 125241, 2419, 51230, 52063, 125244, 44068, 45967, - 48103, 45970, 2700, 50186, 30042, 41542, 49310, 23452, 48782, 125422, - 50724, 1519, 51418, 51499, 46718, 47395, 991, 50623, 972, 76621, 1905, - 1933, 76847, 76412, 3574, 76316, 51622, 40933, 50633, 50629, 3577, 1862, - 3811, 125419, 51502, 51948, 51421, 32926, 29944, 2341, 48356, 49074, - 42857, 5889, 125093, 51668, 50315, 44070, 45973, 46119, 125247, 45805, - 3814, 4861, 125021, 40131, 41916, 76715, 3673, 76512, 46635, 171244, - 50515, 76414, 50853, 49960, 51504, 76417, 50419, 76895, 41009, 3746, - 489, 52037, 3582, 516, 50518, 907, 10871, 125025, 49402, 43115, 50318, - 51678, 45554, 45704, 3675, 45976, 40382, 41774, 49966, 1610, 45707, - 50260, 3525, 51509, 76627, 76717, 51754, 45557, 45979, 4987, 51513, - 51115, 3696, 47806, 3585, 51424, 50636, 49408, 76631, 125485, 125486, - 125487, 125489, 125490, 125028, 24900, 76873, 51795, 3396, 49821, 49411, - 30009, 1882, 45181, 45626, 42260, 42024, 3678, 537, 2071, 46164, 45710, - 37892, 23831, 171243, 76517, 76719, 22117, 50263, 2300, 18293, 125033, - 76322, 50427, 2306, 76519, 125173, 44393, 15652, 1958, 50433, 42935, - 7588, 45807, 40774, 43418, 46122, 45810, 45631, 47571, 47291, 37919, - 45870, 41086, 76422, 48444, 76522, 125451, 50326, 47520, 50266, 3588, - 51832, 49543, 49827, 51516, 76525, 45981, 5924, 76843, 50521, 3820, - 47188, 45713, 47997, 51519, 1994, 125252, 50941, 76908, 49416, 45984, - 1787, 44471, 50269, 3122, 50733, 76633, 1997, 49210, 43122, 42040, - 42983, 7827, 49830, 45634, 51133, 45715, 1964, 50272, 45560, 51437, - 76807, 42985, 51818, 45185, 47418, 3594, 50137, 51031, 35911, 3597, - 51137, 49556, 2774, 125099, 50276, 2829, 40935, 3681, 48003, 10621, - 76721, 50140, 981, 47819, 43131, 2000, 43528, 47739, 76887, 51353, - 50944, 76527, 50336, 50338, 3753, 76325, 4069, 125416, 462, 51236, - 43134, 45564, 45873, 51760, 1283, 43530, 125317, 125255, 76530, 42867, - 47825, 76960, 3891, 50862, 50340, 47928, 25451, 51533, 50430, 76533, - 125258, 51537, 45567, 121660, 76638, 3755, 40782, 49559, 7940, 2247, + allowedTitleIds: [], + supressedTitleIds: [], + individualCardQuotas: {}, + cardCountRestriction: "Singleton", + FormatType: "Constructed", + mainDeckQuota: { min: 99, max: 99 }, + sideBoardQuota: { max: 1 }, + commandZoneQuota: { min: 1, max: 1 }, + sideboardBehavior: "CompanionOnly", + useRebalancedCards: true, + AllowedCommanderTitleIds: [ + 610848, 610850, 610852, 610854, 610856, 673942, 756700, 557291, 229729, + 557791, 488767, 10846, 1455, 227472, 676042, 351960, 498623, 433919, + 488856, 498276, 702732, 498290, 498850, 498463, 557666, 557514, 604458, + 414577, 558053, 557372, 229634, 604702, 604500, 498319, 336834, 125391, + 229741, 336840, 749062, 273039, 704259, 499042, 229747, 618947, 615236, + 336638, 1648, 229641, 45839, 548242, 489003, 610846, 32844, 489040, + 604461, 499212, 336181, 229760, 489056, 227363, 567811, 702887, + ], + }, + { + name: "Singleton", + legalSets: [ + "ANB", + "ANC", + "WOE", + "Y24", + "Y24_WOE", + "LCI", + "Y24_LCI", + "MKM", + "Y24_MKM", + "OTJ", + "BIG", + "Y24_OTJ", + "BLB", + "Y25", + "Y25_BLB", + "DSK", + ], + filterSets: [ + "ANB", + "ANC", + "WOE", + "Y24", + "Y24_WOE", + "LCI", + "Y24_LCI", + "MKM", + "Y24_MKM", + "OTJ", + "BIG", + "Y24_OTJ", + "BLB", + "Y25_BLB", + "Y25", + "DSK", + ], + bannedTitleIds: [], + suspendedTitleIds: [], + allowedTitleIds: [], + supressedTitleIds: [], + individualCardQuotas: {}, + cardCountRestriction: "Singleton", + FormatType: "Constructed", + mainDeckQuota: { min: 60, max: 250 }, + sideBoardQuota: { max: 7 }, + useRebalancedCards: true, + AllowedCommanderTitleIds: [], + }, + { + name: "ArtisanFuture", + legalSets: ["ANB", "ANC", "HBG", "MID", "NEO", "SNC", "VOW", "Y22"], + filterSets: ["ANB", "ANC", "HBG", "MID", "NEO", "SNC", "VOW", "Y22"], + bannedTitleIds: [413858, 413858, 428554], + suspendedTitleIds: [], + allowedTitleIds: [], + supressedTitleIds: [], + individualCardQuotas: {}, + FormatType: "Constructed", + mainDeckQuota: { min: 60, max: 250 }, + sideBoardQuota: { max: 7 }, + AllowedCommanderTitleIds: [], + }, + { + name: "IdentityTest", + legalSets: [ + "ANB", + "ANC", + "WOE", + "Y24", + "Y24_WOE", + "LCI", + "Y24_LCI", + "MKM", + "Y24_MKM", + "OTJ", + "BIG", + "Y24_OTJ", + "BLB", + "Y25", + "Y25_BLB", + "DSK", + ], + filterSets: [ + "ANB", + "ANC", + "WOE", + "Y24", + "Y24_WOE", + "LCI", + "Y24_LCI", + "MKM", + "Y24_MKM", + "OTJ", + "BIG", + "Y24_OTJ", + "BLB", + "Y25_BLB", + "Y25", + "DSK", + ], + bannedTitleIds: [], + suspendedTitleIds: [], + allowedTitleIds: [], + supressedTitleIds: [], + individualCardQuotas: {}, + FormatType: "Constructed", + mainDeckQuota: { min: 60, max: 250 }, + sideBoardQuota: { max: 7 }, + useRebalancedCards: true, + AllowedCommanderTitleIds: [], + }, + { + name: "Explorer", + legalSets: [ + "AER", + "AFR", + "AKH", + "BFZ", + "BNG", + "DAR", + "DGM", + "DMU", + "DTK", + "ELD", + "EMN", + "FRF", + "GRN", + "GTC", + "HOU", + "IKO", + "JOU", + "KHM", + "KLD", + "KTK", + "M14", + "M15", + "M19", + "M20", + "M21", + "MID", + "NEO", + "OGW", + "ORI", + "RIX", + "RNA", + "RTR", + "SNC", + "SOI", + "STX", + "THB", + "THS", + "VOW", + "WAR", + "XLN", + "ZNR", + "BRO", + "ONE", + "SIR", + "MOM", + "MAT", + "WOE", + "EA1", + "EA2", + "EA3", + "LCI", + "MKM", + "BIG", + "OTJ", + "BLB", + "DSK", + ], + filterSets: [ + "AER", + "AFR", + "AKH", + "BFZ", + "BNG", + "DAR", + "DGM", + "DMU", + "DTK", + "ELD", + "EMN", + "FRF", + "GRN", + "GTC", + "HOU", + "IKO", + "JOU", + "KHM", + "KLD", + "KTK", + "M14", + "M15", + "M19", + "M20", + "M21", + "MID", + "NEO", + "OGW", + "ORI", + "RIX", + "RNA", + "RTR", + "SNC", + "SOI", + "STX", + "THB", + "THS", + "VOW", + "WAR", + "XLN", + "ZNR", + "BRO", + "ONE", + "SIR", + "MOM", + "MAT", + "WOE", + "EA1", + "EA2", + "EA3", + "AKR", + "KLR", + "LCI", + "MKM", + "BIG", + "OTJ", + "SPG", + "BLB", + "DSK", + ], + bannedTitleIds: [ + 737878, 38310, 25409, 488847, 352244, 24807, 737615, 336177, 352156, + 352080, 428587, 38551, 38526, 1679, 414260, 414166, 24837, 38497, + 351897, 336891, 477509, 420184, 420429, 352113, 38622, 279929, 24888, + 428552, 3179, + ], + suspendedTitleIds: [], + allowedTitleIds: [ + 125456, 47893, 50590, 45937, 125232, 41292, 50257, 45940, 46108, 45540, + 45943, 45544, 45946, 32614, 125155, 3662, 2323, 41908, 125012, 50409, + 125085, 50913, 51696, 52060, 51613, 51978, 51006, 52031, 52003, 51010, + 1859, 51109, 1977, 52200, 1815, 52097, 1901, 1981, 76797, 76600, 3799, + 45546, 45779, 51702, 51889, 18841, 45550, 50602, 46703, 51985, 51752, + 3665, 2082, 46112, 39065, 3878, 3497, 125157, 46939, 45949, 47562, + 48984, 50918, 76298, 125017, 1144, 48218, 49373, 43399, 261485, 50093, + 1984, 45953, 24122, 76301, 76303, 47051, 43683, 3502, 125429, 1926, + 76306, 51320, 25159, 3505, 47628, 45863, 76496, 3888, 3881, 45956, + 51327, 45782, 76402, 45785, 50160, 41064, 47382, 50605, 1592, 49666, + 47493, 51330, 51990, 41301, 41984, 50857, 50920, 3508, 3735, 45959, + 76405, 14901, 125019, 76800, 50923, 45866, 3653, 41573, 18919, 76498, + 51488, 1769, 51747, 52006, 45788, 42916, 51957, 51673, 51491, 46709, + 795, 4943, 76603, 43612, 45962, 3580, 45868, 50608, 45328, 45695, + 125307, 43209, 76309, 49675, 45697, 125309, 39519, 76606, 960, 47634, + 76501, 41627, 45619, 12837, 45238, 50611, 48433, 50721, 46157, 2076, + 45793, 50817, 40703, 76609, 49799, 76611, 45700, 51616, 51333, 46161, + 125235, 2792, 42854, 3210, 51494, 1991, 48100, 76504, 11532, 8005, 3185, + 2763, 76507, 125167, 76904, 41996, 45334, 43405, 41630, 42256, 50300, + 50617, 987, 2036, 3517, 3906, 44382, 2766, 2065, 45479, 43213, 42447, + 12807, 3802, 46115, 45796, 1929, 966, 41226, 49134, 43044, 50926, 51218, + 45799, 3738, 125238, 42194, 43688, 45965, 76615, 3520, 3805, 3668, 2278, + 646, 45802, 76953, 48437, 76510, 76408, 76312, 76705, 76618, 121693, + 76315, 1823, 49397, 51221, 4941, 50504, 76410, 51017, 50507, 76707, + 125090, 42928, 51224, 125241, 2419, 51230, 52063, 125244, 44068, 45967, + 48103, 45970, 2700, 50186, 30042, 41542, 49310, 23452, 48782, 125422, + 50724, 1519, 51418, 51499, 46718, 47395, 991, 50623, 972, 76621, 1905, + 1933, 76847, 76412, 3574, 76316, 51622, 40933, 50633, 50629, 3577, 1862, + 3811, 125419, 51502, 51948, 51421, 32926, 29944, 2341, 48356, 49074, + 42857, 5889, 125093, 51668, 50315, 44070, 45973, 46119, 125247, 45805, + 3814, 4861, 125021, 40131, 41916, 76715, 3673, 76512, 46635, 171244, + 50515, 76414, 50853, 49960, 51504, 76417, 50419, 76895, 41009, 3746, + 489, 52037, 3582, 516, 50518, 907, 10871, 125025, 49402, 43115, 50318, + 51678, 45554, 45704, 3675, 45976, 40382, 41774, 49966, 1610, 45707, + 50260, 3525, 51509, 76627, 76717, 51754, 45557, 45979, 4987, 51513, + 51115, 3696, 47806, 3585, 51424, 50636, 49408, 76631, 125485, 125486, + 125487, 125489, 125490, 125028, 24900, 76873, 51795, 3396, 49821, 49411, + 30009, 1882, 45181, 45626, 42260, 42024, 3678, 537, 2071, 46164, 45710, + 37892, 23831, 171243, 76517, 76719, 22117, 50263, 2300, 18293, 125033, + 76322, 50427, 2306, 76519, 125173, 44393, 15652, 1958, 50433, 42935, + 7588, 45807, 40774, 43418, 46122, 45810, 45631, 47571, 47291, 37919, + 45870, 41086, 76422, 48444, 76522, 125451, 50326, 47520, 50266, 3588, + 51832, 49543, 49827, 51516, 76525, 45981, 5924, 76843, 50521, 3820, + 47188, 45713, 47997, 51519, 1994, 125252, 50941, 76908, 49416, 45984, + 1787, 44471, 50269, 3122, 50733, 76633, 1997, 49210, 43122, 42040, + 42983, 7827, 49830, 45634, 51133, 45715, 1964, 50272, 45560, 51437, + 76807, 42985, 51818, 45185, 47418, 3594, 50137, 51031, 35911, 3597, + 51137, 49556, 2774, 125099, 50276, 2829, 40935, 3681, 48003, 10621, + 76721, 50140, 981, 47819, 43131, 2000, 43528, 47739, 76887, 51353, + 50944, 76527, 50336, 50338, 3753, 76325, 4069, 125416, 462, 51236, + 43134, 45564, 45873, 51760, 1283, 43530, 125317, 125255, 76530, 42867, + 47825, 76960, 3891, 50862, 50340, 47928, 25451, 51533, 50430, 76533, + 125258, 51537, 45567, 121660, 76638, 3755, 40782, 49559, 7940, 2247, 76426, 44476, 45987, 2628, 50441, 45637, 50191, 39537, 3600, 76327, 50194, 50197, 30, 51140, 50199, 51766, 51543, 51143, 1154, 51763, 50947, 125103, 51820, 51146, 125319, 46168, 52069, 2557, 45188, 1828, 51239, @@ -12472,43 +12638,373 @@ const formatsJson: FormatsJSON = { 45935, 2033, 49198, 3393, 50292, 44174, 51777, 52057, 4949, 43200, 42975, 48584, 128920, 48062, 42839, 48491, 46104, ], - supressedTitleIds: [ - 38310, 25409, 352244, 24807, 352156, 352080, 428587, 38551, 38526, 1679, - 414260, 414166, 24837, 38497, 336891, 477509, 420184, 420429, 352113, - 38622, 279929, 24888, 428552, 3179, + supressedTitleIds: [ + 38310, 25409, 352244, 24807, 352156, 352080, 428587, 38551, 38526, 1679, + 414260, 414166, 24837, 38497, 336891, 477509, 420184, 420429, 352113, + 38622, 279929, 24888, 428552, 3179, + ], + individualCardQuotas: {}, + FormatType: "Constructed", + mainDeckQuota: { min: 60, max: 250 }, + sideBoardQuota: { max: 7 }, + AllowedCommanderTitleIds: [], + }, + { + name: "3Sets", + legalSets: ["OTJ", "BIG", "BLB", "DSK"], + filterSets: ["OTJ", "BIG", "BLB", "DSK"], + bannedTitleIds: [], + suspendedTitleIds: [], + allowedTitleIds: [], + supressedTitleIds: [], + individualCardQuotas: {}, + FormatType: "Constructed", + mainDeckQuota: { min: 60, max: 250 }, + sideBoardQuota: { max: 7 }, + AllowedCommanderTitleIds: [], + }, + { + name: "DirectGame", + legalSets: [ + "2XM", + "2X2", + "8ED", + "A25", + "AER", + "AFR", + "AKH", + "AKR", + "ALA", + "ANA", + "ANB", + "ARB", + "AVR", + "BFZ", + "BNG", + "C18", + "C20", + "C21", + "CC2", + "CHK", + "CM2", + "CMR", + "CONF", + "CSP", + "DAR", + "DGM", + "DKA", + "DMU", + "DST", + "DTK", + "ELD", + "EMN", + "FDN", + "FRF", + "G18", + "GRN", + "GTC", + "HBG", + "HOU", + "IKO", + "IMA", + "INV", + "ISD", + "J21", + "JMP", + "JOU", + "JUD", + "KHM", + "KLR", + "KTK", + "LGN", + "LRW", + "M10", + "M11", + "M12", + "M13", + "M14", + "M15", + "M19", + "M20", + "M21", + "MBS", + "MH1", + "MH2", + "MID", + "MMA", + "MMQ", + "MOR", + "MRD", + "NEC", + "NEO", + "NPH", + "ODY", + "OGW", + "ONS", + "ORI", + "PLC", + "RAV", + "RIX", + "RNA", + "ROE", + "RTR", + "SCG", + "SHM", + "SNC", + "SOI", + "SOK", + "SOM", + "STA", + "STX", + "THB", + "THS", + "TOR", + "TSP", + "USG", + "UMA", + "VOW", + "W17", + "WAR", + "WTH", + "WWK", + "XLN", + "Y22", + "Y23", + "ZEN", + "ZNR", + "BRO", + "BRR", + "ONE", + "SIR", + "SIS", + "MUL", + "MOM", + "MOC", + "MAT", + "LTR", + "WOE", + "WOT", + "LCI", + "AHA1", + "AHA2", + "AHA3", + "AHA4", + "AHA5", + "AHA6", + "AHA7", + "EA1", + "EA2", + "EA3", + "Y23_ONE", + "Y23_BRO", + "Y23_DMU", + "Y22_SNC", + "Y22_NEO", + "Y22_MID", + "Y24_WOE", + "Y24", + "LCC", + "Y24_LCI", + "MKM", + "OTJ", + "Y24_MKM", + "SPG", + "KLD", + "APC", + "CLB", + "C16", + "DIS", + "DDU", + "MH3", + "OTP", + "OTC", + "BIG", + "OTC", + "Y24_OTJ", + "MH3", + "M3C", + "BLB", + "BLC", + "DSK", + "Y25", + "Y25_BLB", + ], + filterSets: [ + "2XM", + "2X2", + "8ED", + "A25", + "AER", + "AFR", + "AKH", + "AKR", + "ALA", + "ANA", + "ANB", + "ARB", + "AVR", + "BFZ", + "BNG", + "C18", + "C20", + "C21", + "CC2", + "CHK", + "CM2", + "CMR", + "CONF", + "CSP", + "DAR", + "DGM", + "DKA", + "DMU", + "DST", + "DTK", + "ELD", + "EMN", + "FDN", + "FRF", + "G18", + "GRN", + "GTC", + "HBG", + "HOU", + "IKO", + "IMA", + "INV", + "ISD", + "J21", + "JMP", + "JOU", + "JUD", + "KHM", + "KLR", + "KTK", + "LGN", + "LRW", + "M10", + "M11", + "M12", + "M13", + "M14", + "M15", + "M19", + "M20", + "M21", + "MBS", + "MH1", + "MH2", + "MID", + "MMA", + "MMQ", + "MOR", + "MRD", + "NEC", + "NEO", + "NPH", + "ODY", + "OGW", + "ONS", + "ORI", + "PLC", + "RAV", + "RIX", + "RNA", + "ROE", + "RTR", + "SCG", + "SHM", + "SNC", + "SOI", + "SOK", + "SOM", + "STA", + "STX", + "THB", + "THS", + "TOR", + "TSP", + "USG", + "UMA", + "VOW", + "W17", + "WAR", + "WTH", + "WWK", + "XLN", + "Y22", + "Y23", + "ZEN", + "ZNR", + "BRO", + "BRR", + "ONE", + "SIR", + "SIS", + "MUL", + "MOM", + "MOC", + "MAT", + "LTR", + "WOE", + "WOT", + "LCI", + "AHA1", + "AHA2", + "AHA3", + "AHA4", + "AHA5", + "AHA6", + "AHA7", + "EA1", + "EA2", + "EA3", + "Y23_ONE", + "Y23_BRO", + "Y23_DMU", + "Y22_SNC", + "Y22_NEO", + "Y22_MID", + "Y24_WOE", + "Y24", + "LCC", + "Y24_LCI", + "MKM", + "OTJ", + "Y24_MKM", + "SPG", + "KLD", + "APC", + "CLB", + "C16", + "DIS", + "DDU", + "MH3", + "OTP", + "OTC", + "BIG", + "OTC", + "Y24_OTJ", + "MH3", + "M3C", + "BLB", + "BLC", + "DSK", + "Y25_BLB", + "Y25", ], - individualCardQuotas: {}, - FormatType: "Constructed", - mainDeckQuota: { - min: 60, - max: 250, - }, - sideBoardQuota: { - max: 7, - }, - AllowedCommanderTitleIds: [], - }, - { - name: "3Sets", - legalSets: ["MKM", "OTJ", "BIG", "BLB"], - filterSets: ["MKM", "OTJ", "BIG", "BLB"], bannedTitleIds: [], suspendedTitleIds: [], allowedTitleIds: [], supressedTitleIds: [], individualCardQuotas: {}, FormatType: "Constructed", - mainDeckQuota: { - min: 60, - max: 250, - }, - sideBoardQuota: { - max: 7, - }, + mainDeckQuota: { min: 60, max: 250 }, + sideBoardQuota: { max: 15 }, AllowedCommanderTitleIds: [], }, { - name: "DirectGame", + name: "DirectGameBrawl", legalSets: [ "2XM", "2X2", @@ -12542,6 +13038,7 @@ const formatsJson: FormatsJSON = { "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -12669,6 +13166,8 @@ const formatsJson: FormatsJSON = { "BLB", "BLC", "DSK", + "Y25", + "Y25_BLB", ], filterSets: [ "2XM", @@ -12703,6 +13202,7 @@ const formatsJson: FormatsJSON = { "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -12823,31 +13323,265 @@ const formatsJson: FormatsJSON = { "OTP", "OTC", "BIG", - "OTC", - "Y24_OTJ", - "MH3", - "M3C", + "OTC", + "Y24_OTJ", + "MH3", + "M3C", + "BLB", + "BLC", + "DSK", + "Y25_BLB", + "Y25", + ], + bannedTitleIds: [], + suspendedTitleIds: [], + allowedTitleIds: [], + supressedTitleIds: [], + individualCardQuotas: {}, + cardCountRestriction: "Singleton", + FormatType: "Constructed", + mainDeckQuota: { min: 39, max: 249 }, + sideBoardQuota: { max: 7 }, + commandZoneQuota: { min: 1, max: 1 }, + sideboardBehavior: "CompanionOnly", + AllowedCommanderTitleIds: [], + }, + { + name: "TraditionalAlchemy", + legalSets: [ + "ANB", + "ANC", + "WOE", + "Y24", + "Y24_WOE", + "LCI", + "Y24_LCI", + "MKM", + "Y24_MKM", + "OTJ", + "BIG", + "Y24_OTJ", + "BLB", + "Y25", + "Y25_BLB", + "DSK", + ], + filterSets: [ + "ANB", + "ANC", + "WOE", + "Y24", + "Y24_WOE", + "LCI", + "Y24_LCI", + "MKM", + "Y24_MKM", + "OTJ", + "BIG", + "Y24_OTJ", + "BLB", + "Y25_BLB", + "Y25", + "DSK", + ], + bannedTitleIds: [3142, 3142, 3142, 3142], + suspendedTitleIds: [], + allowedTitleIds: [], + supressedTitleIds: [3142], + individualCardQuotas: {}, + FormatType: "Constructed", + mainDeckQuota: { min: 60, max: 250 }, + sideBoardQuota: { max: 15 }, + useRebalancedCards: true, + AllowedCommanderTitleIds: [], + }, + { + name: "Pauper", + legalSets: [ + "ANB", + "ANC", + "WOE", + "Y24", + "Y24_WOE", + "LCI", + "Y24_LCI", + "MKM", + "Y24_MKM", + "OTJ", + "BIG", + "Y24_OTJ", + "BLB", + "Y25", + "Y25_BLB", + "DSK", + ], + filterSets: [ + "ANB", + "ANC", + "WOE", + "Y24", + "Y24_WOE", + "LCI", + "Y24_LCI", + "MKM", + "Y24_MKM", + "OTJ", + "BIG", + "Y24_OTJ", + "BLB", + "Y25_BLB", + "Y25", + "DSK", + ], + bannedTitleIds: [], + suspendedTitleIds: [], + allowedTitleIds: [], + supressedTitleIds: [], + individualCardQuotas: {}, + FormatType: "Constructed", + mainDeckQuota: { min: 60, max: 250 }, + sideBoardQuota: { max: 7 }, + AllowedCommanderTitleIds: [], + }, + { + name: "Zendikar", + legalSets: ["ZNR"], + filterSets: ["ZNR"], + bannedTitleIds: [], + suspendedTitleIds: [], + allowedTitleIds: [], + supressedTitleIds: [], + individualCardQuotas: {}, + FormatType: "Constructed", + mainDeckQuota: { min: 60, max: 250 }, + sideBoardQuota: { max: 7 }, + AllowedCommanderTitleIds: [], + }, + { + name: "Renewal", + legalSets: ["AFR", "ANB", "KHM", "STX", "ZNR"], + filterSets: ["AFR", "ANB", "KHM", "STX", "ZNR"], + bannedTitleIds: [437805], + suspendedTitleIds: [], + allowedTitleIds: [], + supressedTitleIds: [], + individualCardQuotas: {}, + FormatType: "Constructed", + mainDeckQuota: { min: 60, max: 250 }, + sideBoardQuota: { max: 7 }, + AllowedCommanderTitleIds: [], + }, + { + name: "TraditionalStandard", + legalSets: [ + "DMU", + "BRO", + "ONE", + "MOM", + "MAT", + "WOE", + "LCI", + "MKM", + "OTJ", + "BIG", + "BLB", + "DSK", + ], + filterSets: [ + "DMU", + "BRO", + "ONE", + "MOM", + "MAT", + "WOE", + "LCI", + "MKM", + "OTJ", + "BIG", + "BLB", + "DSK", + ], + bannedTitleIds: [3142, 3142, 3142, 3142], + suspendedTitleIds: [], + allowedTitleIds: [], + supressedTitleIds: [3142], + individualCardQuotas: {}, + FormatType: "Constructed", + mainDeckQuota: { min: 60, max: 250 }, + sideBoardQuota: { max: 15 }, + AllowedCommanderTitleIds: [], + }, + { + name: "FutureAlchemy", + legalSets: ["ANB", "ANC", "HBG", "MID", "NEO", "SNC", "VOW", "Y22"], + filterSets: ["ANB", "ANC", "HBG", "MID", "NEO", "SNC", "VOW", "Y22"], + bannedTitleIds: [], + suspendedTitleIds: [], + allowedTitleIds: [], + supressedTitleIds: [], + individualCardQuotas: {}, + FormatType: "Constructed", + mainDeckQuota: { min: 60, max: 250 }, + sideBoardQuota: { max: 7 }, + useRebalancedCards: true, + AllowedCommanderTitleIds: [], + }, + { + name: "GRN", + legalSets: ["GRN"], + filterSets: ["GRN"], + bannedTitleIds: [], + suspendedTitleIds: [], + allowedTitleIds: [], + supressedTitleIds: [], + individualCardQuotas: {}, + FormatType: "Constructed", + mainDeckQuota: { min: 60, max: 250 }, + sideBoardQuota: { max: 15 }, + AllowedCommanderTitleIds: [], + }, + { + name: "100CardStandard", + legalSets: [ + "DMU", + "BRO", + "ONE", + "MOM", + "MAT", + "WOE", + "LCI", + "MKM", + "OTJ", + "BIG", + "BLB", + "DSK", + ], + filterSets: [ + "DMU", + "BRO", + "ONE", + "MOM", + "MAT", + "WOE", + "LCI", + "MKM", + "OTJ", + "BIG", "BLB", - "BLC", "DSK", ], - bannedTitleIds: [], + bannedTitleIds: [437805], suspendedTitleIds: [], allowedTitleIds: [], supressedTitleIds: [], individualCardQuotas: {}, FormatType: "Constructed", - mainDeckQuota: { - min: 60, - max: 250, - }, - sideBoardQuota: { - max: 15, - }, + mainDeckQuota: { min: 100, max: 250 }, + sideBoardQuota: { max: 7 }, AllowedCommanderTitleIds: [], }, { - name: "DirectGameBrawl", + name: "DirectGameLimited", legalSets: [ "2XM", "2X2", @@ -12881,6 +13615,7 @@ const formatsJson: FormatsJSON = { "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -13008,6 +13743,8 @@ const formatsJson: FormatsJSON = { "BLB", "BLC", "DSK", + "Y25", + "Y25_BLB", ], filterSets: [ "2XM", @@ -13042,6 +13779,7 @@ const formatsJson: FormatsJSON = { "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -13169,288 +13907,22 @@ const formatsJson: FormatsJSON = { "BLB", "BLC", "DSK", + "Y25_BLB", + "Y25", ], bannedTitleIds: [], suspendedTitleIds: [], allowedTitleIds: [], supressedTitleIds: [], individualCardQuotas: {}, - cardCountRestriction: "Singleton", - FormatType: "Constructed", - mainDeckQuota: { - min: 39, - max: 249, - }, - sideBoardQuota: { - max: 7, - }, - commandZoneQuota: { - min: 1, - max: 1, - }, - sideboardBehavior: "CompanionOnly", - AllowedCommanderTitleIds: [], - }, - { - name: "TraditionalAlchemy", - legalSets: [ - "ANB", - "ANC", - "WOE", - "Y24", - "Y24_WOE", - "LCI", - "Y24_LCI", - "MKM", - "Y24_MKM", - "OTJ", - "BIG", - "Y24_OTJ", - "BLB", - ], - filterSets: [ - "ANB", - "ANC", - "WOE", - "Y24", - "Y24_WOE", - "LCI", - "Y24_LCI", - "MKM", - "Y24_MKM", - "OTJ", - "BIG", - "Y24_OTJ", - "BLB", - ], - bannedTitleIds: [3142, 3142, 3142, 3142], - suspendedTitleIds: [], - allowedTitleIds: [], - supressedTitleIds: [3142], - individualCardQuotas: {}, - FormatType: "Constructed", - mainDeckQuota: { - min: 60, - max: 250, - }, - sideBoardQuota: { - max: 15, - }, - useRebalancedCards: true, - AllowedCommanderTitleIds: [], - }, - { - name: "Pauper", - legalSets: [ - "ANB", - "ANC", - "WOE", - "Y24", - "Y24_WOE", - "LCI", - "Y24_LCI", - "MKM", - "Y24_MKM", - "OTJ", - "BIG", - "Y24_OTJ", - "BLB", - ], - filterSets: [ - "ANB", - "ANC", - "WOE", - "Y24", - "Y24_WOE", - "LCI", - "Y24_LCI", - "MKM", - "Y24_MKM", - "OTJ", - "BIG", - "Y24_OTJ", - "BLB", - ], - bannedTitleIds: [], - suspendedTitleIds: [], - allowedTitleIds: [], - supressedTitleIds: [], - individualCardQuotas: {}, - FormatType: "Constructed", - mainDeckQuota: { - min: 60, - max: 250, - }, - sideBoardQuota: { - max: 7, - }, - AllowedCommanderTitleIds: [], - }, - { - name: "Zendikar", - legalSets: ["ZNR"], - filterSets: ["ZNR"], - bannedTitleIds: [], - suspendedTitleIds: [], - allowedTitleIds: [], - supressedTitleIds: [], - individualCardQuotas: {}, - FormatType: "Constructed", - mainDeckQuota: { - min: 60, - max: 250, - }, - sideBoardQuota: { - max: 7, - }, - AllowedCommanderTitleIds: [], - }, - { - name: "Renewal", - legalSets: ["AFR", "ANB", "KHM", "STX", "ZNR"], - filterSets: ["AFR", "ANB", "KHM", "STX", "ZNR"], - bannedTitleIds: [437805], - suspendedTitleIds: [], - allowedTitleIds: [], - supressedTitleIds: [], - individualCardQuotas: {}, - FormatType: "Constructed", - mainDeckQuota: { - min: 60, - max: 250, - }, - sideBoardQuota: { - max: 7, - }, - AllowedCommanderTitleIds: [], - }, - { - name: "TraditionalStandard", - legalSets: [ - "DMU", - "BRO", - "ONE", - "MOM", - "MAT", - "WOE", - "LCI", - "MKM", - "OTJ", - "BIG", - "BLB", - ], - filterSets: [ - "DMU", - "BRO", - "ONE", - "MOM", - "MAT", - "WOE", - "LCI", - "MKM", - "OTJ", - "BIG", - "BLB", - ], - bannedTitleIds: [3142, 3142, 3142, 3142], - suspendedTitleIds: [], - allowedTitleIds: [], - supressedTitleIds: [3142], - individualCardQuotas: {}, - FormatType: "Constructed", - mainDeckQuota: { - min: 60, - max: 250, - }, - sideBoardQuota: { - max: 15, - }, - AllowedCommanderTitleIds: [], - }, - { - name: "FutureAlchemy", - legalSets: ["ANB", "ANC", "HBG", "MID", "NEO", "SNC", "VOW", "Y22"], - filterSets: ["ANB", "ANC", "HBG", "MID", "NEO", "SNC", "VOW", "Y22"], - bannedTitleIds: [], - suspendedTitleIds: [], - allowedTitleIds: [], - supressedTitleIds: [], - individualCardQuotas: {}, - FormatType: "Constructed", - mainDeckQuota: { - min: 60, - max: 250, - }, - sideBoardQuota: { - max: 7, - }, - useRebalancedCards: true, - AllowedCommanderTitleIds: [], - }, - { - name: "GRN", - legalSets: ["GRN"], - filterSets: ["GRN"], - bannedTitleIds: [], - suspendedTitleIds: [], - allowedTitleIds: [], - supressedTitleIds: [], - individualCardQuotas: {}, - FormatType: "Constructed", - mainDeckQuota: { - min: 60, - max: 250, - }, - sideBoardQuota: { - max: 15, - }, - AllowedCommanderTitleIds: [], - }, - { - name: "100CardStandard", - legalSets: [ - "DMU", - "BRO", - "ONE", - "MOM", - "MAT", - "WOE", - "LCI", - "MKM", - "OTJ", - "BIG", - "BLB", - ], - filterSets: [ - "DMU", - "BRO", - "ONE", - "MOM", - "MAT", - "WOE", - "LCI", - "MKM", - "OTJ", - "BIG", - "BLB", - ], - bannedTitleIds: [437805], - suspendedTitleIds: [], - allowedTitleIds: [], - supressedTitleIds: [], - individualCardQuotas: {}, + cardCountRestriction: "UnrestrictedCardCounts", FormatType: "Constructed", - mainDeckQuota: { - min: 100, - max: 250, - }, - sideBoardQuota: { - max: 7, - }, + mainDeckQuota: { min: 40, max: 250 }, + sideBoardQuota: { max: 250 }, AllowedCommanderTitleIds: [], }, { - name: "DirectGameLimited", + name: "HistoricBrawlWithAllowList_20241008", legalSets: [ "2XM", "2X2", @@ -13484,6 +13956,7 @@ const formatsJson: FormatsJSON = { "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -13611,6 +14084,8 @@ const formatsJson: FormatsJSON = { "BLB", "BLC", "DSK", + "Y25", + "Y25_BLB", ], filterSets: [ "2XM", @@ -13645,6 +14120,7 @@ const formatsJson: FormatsJSON = { "DTK", "ELD", "EMN", + "FDN", "FRF", "G18", "GRN", @@ -13772,22 +14248,30 @@ const formatsJson: FormatsJSON = { "BLB", "BLC", "DSK", + "Y25_BLB", + "Y25", + ], + bannedTitleIds: [ + 351741, 24405, 21415, 12194, 760671, 427904, 352244, 76334, 428590, + 8628, 24870, 1679, 414260, 279584, 19674, 5159, 31558, 174019, 26717, + 46453, ], - bannedTitleIds: [], suspendedTitleIds: [], allowedTitleIds: [], supressedTitleIds: [], individualCardQuotas: {}, - cardCountRestriction: "UnrestrictedCardCounts", + cardCountRestriction: "Singleton", FormatType: "Constructed", - mainDeckQuota: { - min: 40, - max: 250, - }, - sideBoardQuota: { - max: 250, - }, - AllowedCommanderTitleIds: [], + mainDeckQuota: { min: 99, max: 99 }, + sideBoardQuota: { max: 1 }, + commandZoneQuota: { min: 1, max: 1 }, + sideboardBehavior: "CompanionOnly", + useRebalancedCards: true, + AllowedCommanderTitleIds: [ + 812854, 813005, 813050, 812929, 813056, 813170, 813063, 813067, 812776, + 813081, 813048, 812480, 813113, 812395, 812369, 812984, 812680, 813121, + 813126, 813129, + ], }, { name: "LastCall", @@ -13799,13 +14283,8 @@ const formatsJson: FormatsJSON = { supressedTitleIds: [], individualCardQuotas: {}, FormatType: "Constructed", - mainDeckQuota: { - min: 60, - max: 250, - }, - sideBoardQuota: { - max: 7, - }, + mainDeckQuota: { min: 60, max: 250 }, + sideBoardQuota: { max: 7 }, useRebalancedCards: true, AllowedCommanderTitleIds: [], }, diff --git a/src/info.json b/src/info.json index abf1587..450eab1 100644 --- a/src/info.json +++ b/src/info.json @@ -1 +1 @@ -{"version":"6.7.1","branch":"dev","timestamp":1724090906606} \ No newline at end of file +{"version":"6.7.4","branch":"dev","timestamp":1728101146397} \ No newline at end of file