Created
May 9, 2018 10:45
-
-
Save S3bb1/a666be07c8528f79133488dc24bd36e6 to your computer and use it in GitHub Desktop.
This file has been truncated, but you can view the full file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.lightwallet = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){ | |
'use strict'; | |
module.exports = { | |
txutils: require('./lib/txutils.js'), | |
encryption: require('./lib/encryption.js'), | |
signing: require('./lib/signing.js'), | |
keystore: require('./lib/keystore.js'), | |
upgrade: require('./lib/upgrade.js') | |
}; | |
},{"./lib/encryption.js":2,"./lib/keystore.js":3,"./lib/signing.js":4,"./lib/txutils.js":5,"./lib/upgrade.js":6}],2:[function(require,module,exports){ | |
(function (Buffer){ | |
'use strict'; | |
var util = require("ethereumjs-util"); | |
var nacl = require('tweetnacl'); | |
function nacl_encodeHex(msgUInt8Arr) { | |
var msgBase64 = nacl.util.encodeBase64(msgUInt8Arr); | |
return new Buffer(msgBase64, 'base64').toString('hex'); | |
} | |
function nacl_decodeHex(msgHex) { | |
var msgBase64 = new Buffer(msgHex, 'hex').toString('base64'); | |
return nacl.util.decodeBase64(msgBase64); | |
} | |
function addressToPublicEncKey(keystore, pwDerivedKey, address) { | |
var privKey = keystore.exportPrivateKey(address, pwDerivedKey); | |
var privKeyUInt8Array = nacl_decodeHex(privKey); | |
var pubKeyUInt8Array = nacl.box.keyPair.fromSecretKey(privKeyUInt8Array).publicKey; | |
return nacl_encodeHex(pubKeyUInt8Array); | |
} | |
function _asymEncryptRaw(keystore, pwDerivedKey, msgUint8Array, myAddress, theirPubKey) { | |
if (!keystore.isDerivedKeyCorrect(pwDerivedKey)) { | |
throw new Error("Incorrect derived key!"); | |
} | |
var privKey = keystore.exportPrivateKey(myAddress, pwDerivedKey); | |
var privKeyUInt8Array = nacl_decodeHex(privKey); | |
var pubKeyUInt8Array = nacl_decodeHex(theirPubKey); | |
var nonce = nacl.randomBytes(nacl.box.nonceLength); | |
var encryptedMessage = nacl.box(msgUint8Array, nonce, pubKeyUInt8Array, privKeyUInt8Array); | |
var output = { | |
alg: 'curve25519-xsalsa20-poly1305', | |
nonce: nacl.util.encodeBase64(nonce), | |
ciphertext: nacl.util.encodeBase64(encryptedMessage) | |
}; | |
return output; | |
} | |
function _asymDecryptRaw(keystore, pwDerivedKey, encMsg, theirPubKey, myAddress) { | |
if (!keystore.isDerivedKeyCorrect(pwDerivedKey)) { | |
throw new Error("Incorrect derived key!"); | |
} | |
var privKey = keystore.exportPrivateKey(myAddress, pwDerivedKey); | |
var privKeyUInt8Array = nacl_decodeHex(privKey); | |
var pubKeyUInt8Array = nacl_decodeHex(theirPubKey); | |
var nonce = nacl.util.decodeBase64(encMsg.nonce); | |
var ciphertext = nacl.util.decodeBase64(encMsg.ciphertext); | |
var cleartext = nacl.box.open(ciphertext, nonce, pubKeyUInt8Array, privKeyUInt8Array); | |
return cleartext; | |
} | |
var asymEncryptString = function asymEncryptString(keystore, pwDerivedKey, msg, myAddress, theirPubKey) { | |
if (!keystore.isDerivedKeyCorrect(pwDerivedKey)) { | |
throw new Error("Incorrect derived key!"); | |
} | |
var messageUInt8Array = nacl.util.decodeUTF8(msg); | |
return _asymEncryptRaw(keystore, pwDerivedKey, messageUInt8Array, myAddress, theirPubKey); | |
}; | |
var asymDecryptString = function asymDecryptString(keystore, pwDerivedKey, encMsg, theirPubKey, myAddress) { | |
if (!keystore.isDerivedKeyCorrect(pwDerivedKey)) { | |
throw new Error("Incorrect derived key!"); | |
} | |
var cleartext = _asymDecryptRaw(keystore, pwDerivedKey, encMsg, theirPubKey, myAddress); | |
if (cleartext === false) { | |
return false; | |
} else { | |
return nacl.util.encodeUTF8(cleartext); | |
} | |
}; | |
var multiEncryptString = function multiEncryptString(keystore, pwDerivedKey, msg, myAddress, theirPubKeyArray) { | |
if (!keystore.isDerivedKeyCorrect(pwDerivedKey)) { | |
throw new Error("Incorrect derived key!"); | |
} | |
var messageUInt8Array = nacl.util.decodeUTF8(msg); | |
var symEncryptionKey = nacl.randomBytes(nacl.secretbox.keyLength); | |
var symNonce = nacl.randomBytes(nacl.secretbox.nonceLength); | |
var symEncMessage = nacl.secretbox(messageUInt8Array, symNonce, symEncryptionKey); | |
if (theirPubKeyArray.length < 1) { | |
throw new Error('Found no pubkeys to encrypt to.'); | |
} | |
var encryptedSymKey = {}; | |
encryptedSymKey = []; | |
for (var i = 0; i < theirPubKeyArray.length; i++) { | |
var encSymKey = _asymEncryptRaw(keystore, pwDerivedKey, symEncryptionKey, myAddress, theirPubKeyArray[i]); | |
delete encSymKey['alg']; | |
encryptedSymKey.push(encSymKey); | |
} | |
var output = {}; | |
output.version = 1; | |
output.asymAlg = 'curve25519-xsalsa20-poly1305'; | |
output.symAlg = 'xsalsa20-poly1305'; | |
output.symNonce = nacl.util.encodeBase64(symNonce); | |
output.symEncMessage = nacl.util.encodeBase64(symEncMessage); | |
output.encryptedSymKey = encryptedSymKey; | |
return output; | |
}; | |
var multiDecryptString = function multiDecryptString(keystore, pwDerivedKey, encMsg, theirPubKey, myAddress) { | |
if (!keystore.isDerivedKeyCorrect(pwDerivedKey)) { | |
throw new Error("Incorrect derived key!"); | |
} | |
var symKey = false; | |
for (var i = 0; i < encMsg.encryptedSymKey.length; i++) { | |
var result = _asymDecryptRaw(keystore, pwDerivedKey, encMsg.encryptedSymKey[i], theirPubKey, myAddress); | |
if (result !== false) { | |
symKey = result; | |
break; | |
} | |
} | |
if (symKey === false) { | |
return false; | |
} else { | |
var symNonce = nacl.util.decodeBase64(encMsg.symNonce); | |
var symEncMessage = nacl.util.decodeBase64(encMsg.symEncMessage); | |
var msg = nacl.secretbox.open(symEncMessage, symNonce, symKey); | |
if (msg === false) { | |
return false; | |
} else { | |
return nacl.util.encodeUTF8(msg); | |
} | |
} | |
}; | |
module.exports = { | |
asymEncryptString: asymEncryptString, | |
asymDecryptString: asymDecryptString, | |
multiEncryptString: multiEncryptString, | |
multiDecryptString: multiDecryptString, | |
addressToPublicEncKey: addressToPublicEncKey | |
}; | |
}).call(this,require("buffer").Buffer) | |
},{"buffer":148,"ethereumjs-util":235,"tweetnacl":349}],3:[function(require,module,exports){ | |
(function (Buffer){ | |
'use strict'; | |
var CryptoJS = require('crypto-js'); | |
var Transaction = require('ethereumjs-tx'); | |
var EC = require('elliptic').ec; | |
var ec = new EC('secp256k1'); | |
var bitcore = require('bitcore-lib'); | |
var Random = bitcore.crypto.Random; | |
var Hash = bitcore.crypto.Hash; | |
var Mnemonic = require('bitcore-mnemonic'); | |
var nacl = require('tweetnacl'); | |
var scrypt = require('scrypt-async'); | |
var encryption = require('./encryption'); | |
var signing = require('./signing'); | |
function strip0x(input) { | |
if (typeof input !== 'string') { | |
return input; | |
} else if (input.length >= 2 && input.slice(0, 2) === '0x') { | |
return input.slice(2); | |
} else { | |
return input; | |
} | |
} | |
function add0x(input) { | |
if (typeof input !== 'string') { | |
return input; | |
} else if (input.length < 2 || input.slice(0, 2) !== '0x') { | |
return '0x' + input; | |
} else { | |
return input; | |
} | |
} | |
function leftPadString(stringToPad, padChar, length) { | |
var repreatedPadChar = ''; | |
for (var i = 0; i < length; i++) { | |
repreatedPadChar += padChar; | |
} | |
return (repreatedPadChar + stringToPad).slice(-length); | |
} | |
function nacl_encodeHex(msgUInt8Arr) { | |
var msgBase64 = nacl.util.encodeBase64(msgUInt8Arr); | |
return new Buffer(msgBase64, 'base64').toString('hex'); | |
} | |
function nacl_decodeHex(msgHex) { | |
var msgBase64 = new Buffer(msgHex, 'hex').toString('base64'); | |
return nacl.util.decodeBase64(msgBase64); | |
} | |
var KeyStore = function KeyStore() {}; | |
KeyStore.prototype.init = function (mnemonic, pwDerivedKey, hdPathString, salt) { | |
this.salt = salt; | |
this.hdPathString = hdPathString; | |
this.encSeed = undefined; | |
this.encHdRootPriv = undefined; | |
this.version = 3; | |
this.hdIndex = 0; | |
this.encPrivKeys = {}; | |
this.addresses = []; | |
if (typeof pwDerivedKey !== 'undefined' && typeof mnemonic !== 'undefined') { | |
var words = mnemonic.split(' '); | |
if (!Mnemonic.isValid(mnemonic, Mnemonic.Words.ENGLISH) || words.length !== 12) { | |
throw new Error('KeyStore: Invalid mnemonic'); | |
} | |
// Pad the seed to length 120 before encrypting | |
var paddedSeed = leftPadString(mnemonic, ' ', 120); | |
this.encSeed = encryptString(paddedSeed, pwDerivedKey); | |
// hdRoot is the relative root from which we derive the keys using | |
// generateNewAddress(). The derived keys are then | |
// `hdRoot/hdIndex`. | |
var hdRoot = new Mnemonic(mnemonic).toHDPrivateKey().xprivkey; | |
var hdRootKey = new bitcore.HDPrivateKey(hdRoot); | |
var hdPathKey = hdRootKey.derive(hdPathString).xprivkey; | |
this.encHdRootPriv = encryptString(hdPathKey, pwDerivedKey); | |
} | |
}; | |
KeyStore.createVault = function (opts, cb) { | |
// Default hdPathString | |
if (!('hdPathString' in opts)) { | |
var err = new Error("Keystore: Must include hdPathString in createVault inputs. Suggested alternatives are m/0'/0'/0' for previous lightwallet default, or m/44'/60'/0'/0 for BIP44 (used by Jaxx & MetaMask)"); | |
return cb(err); | |
} | |
if (!('seedPhrase' in opts)) { | |
var err = new Error('Keystore: Must include seedPhrase in createVault inputs.'); | |
return cb(err); | |
} | |
if (!('salt' in opts)) { | |
opts.salt = generateSalt(32); | |
} | |
KeyStore.deriveKeyFromPasswordAndSalt(opts.password, opts.salt, function (err, pwDerivedKey) { | |
if (err) return cb(err); | |
var ks = new KeyStore(); | |
ks.init(opts.seedPhrase, pwDerivedKey, opts.hdPathString, opts.salt); | |
cb(null, ks); | |
}); | |
}; | |
KeyStore.generateSalt = generateSalt; | |
function generateSalt(byteCount) { | |
return bitcore.crypto.Random.getRandomBuffer(byteCount || 32).toString('base64'); | |
} | |
KeyStore.prototype.isDerivedKeyCorrect = function (pwDerivedKey) { | |
var paddedSeed = KeyStore._decryptString(this.encSeed, pwDerivedKey); | |
if (paddedSeed.length > 0) { | |
return true; | |
} | |
return false; | |
}; | |
function encryptString(string, pwDerivedKey) { | |
var nonce = nacl.randomBytes(nacl.secretbox.nonceLength); | |
var encObj = nacl.secretbox(nacl.util.decodeUTF8(string), nonce, pwDerivedKey); | |
var encString = { 'encStr': nacl.util.encodeBase64(encObj), | |
'nonce': nacl.util.encodeBase64(nonce) }; | |
return encString; | |
}; | |
KeyStore._encryptString = encryptString; | |
KeyStore._decryptString = function (encryptedStr, pwDerivedKey) { | |
var secretbox = nacl.util.decodeBase64(encryptedStr.encStr); | |
var nonce = nacl.util.decodeBase64(encryptedStr.nonce); | |
var decryptedStr = nacl.secretbox.open(secretbox, nonce, pwDerivedKey); | |
if (decryptedStr === undefined) { | |
throw new Error("Decryption failed!"); | |
} | |
return nacl.util.encodeUTF8(decryptedStr); | |
}; | |
KeyStore._encryptKey = function (privKey, pwDerivedKey) { | |
var privKeyArray = nacl_decodeHex(privKey); | |
var nonce = nacl.randomBytes(nacl.secretbox.nonceLength); | |
var encKey = nacl.secretbox(privKeyArray, nonce, pwDerivedKey); | |
encKey = { 'key': nacl.util.encodeBase64(encKey), 'nonce': nacl.util.encodeBase64(nonce) }; | |
return encKey; | |
}; | |
KeyStore._decryptKey = function (encryptedKey, pwDerivedKey) { | |
var secretbox = nacl.util.decodeBase64(encryptedKey.key); | |
var nonce = nacl.util.decodeBase64(encryptedKey.nonce); | |
var decryptedKey = nacl.secretbox.open(secretbox, nonce, pwDerivedKey); | |
if (decryptedKey === undefined) { | |
throw new Error("Decryption failed!"); | |
} | |
return nacl_encodeHex(decryptedKey); | |
}; | |
KeyStore._computeAddressFromPrivKey = function (privKey) { | |
var keyPair = ec.genKeyPair(); | |
keyPair._importPrivate(privKey, 'hex'); | |
var compact = false; | |
var pubKey = keyPair.getPublic(compact, 'hex').slice(2); | |
var pubKeyWordArray = CryptoJS.enc.Hex.parse(pubKey); | |
var hash = CryptoJS.SHA3(pubKeyWordArray, { outputLength: 256 }); | |
var address = hash.toString(CryptoJS.enc.Hex).slice(24); | |
return address; | |
}; | |
KeyStore._computePubkeyFromPrivKey = function (privKey, curve) { | |
if (curve !== 'curve25519') { | |
throw new Error('KeyStore._computePubkeyFromPrivKey: Only "curve25519" supported.'); | |
} | |
var privKeyBase64 = new Buffer(privKey, 'hex').toString('base64'); | |
var privKeyUInt8Array = nacl.util.decodeBase64(privKeyBase64); | |
var pubKey = nacl.box.keyPair.fromSecretKey(privKeyUInt8Array).publicKey; | |
var pubKeyBase64 = nacl.util.encodeBase64(pubKey); | |
var pubKeyHex = new Buffer(pubKeyBase64, 'base64').toString('hex'); | |
return pubKeyHex; | |
}; | |
KeyStore.prototype._generatePrivKeys = function (pwDerivedKey, n) { | |
if (!this.isDerivedKeyCorrect(pwDerivedKey)) { | |
throw new Error("Incorrect derived key!"); | |
} | |
var hdRoot = KeyStore._decryptString(this.encHdRootPriv, pwDerivedKey); | |
if (hdRoot.length === 0) { | |
throw new Error('Provided password derived key is wrong'); | |
} | |
var keys = []; | |
for (var i = 0; i < n; i++) { | |
var hdprivkey = new bitcore.HDPrivateKey(hdRoot).derive(this.hdIndex++); | |
var privkeyBuf = hdprivkey.privateKey.toBuffer(); | |
var privkeyHex = privkeyBuf.toString('hex'); | |
if (privkeyBuf.length < 16) { | |
// Way too small key, something must have gone wrong | |
// Halt and catch fire | |
throw new Error('Private key suspiciously small: < 16 bytes. Aborting!'); | |
} else if (privkeyBuf.length < 32) { | |
// Pad private key if too short | |
// bitcore has a bug where it sometimes returns | |
// truncated keys | |
privkeyHex = leftPadString(privkeyBuf.toString('hex'), '0', 64); | |
} else if (privkeyBuf.length > 32) { | |
throw new Error('Private key larger than 32 bytes. Aborting!'); | |
} | |
var encPrivKey = KeyStore._encryptKey(privkeyHex, pwDerivedKey); | |
keys[i] = { | |
privKey: privkeyHex, | |
encPrivKey: encPrivKey | |
}; | |
} | |
return keys; | |
}; | |
// This function is tested using the test vectors here: | |
// http://www.di-mgt.com.au/sha_testvectors.html | |
KeyStore._concatAndSha256 = function (entropyBuf0, entropyBuf1) { | |
var totalEnt = Buffer.concat([entropyBuf0, entropyBuf1]); | |
if (totalEnt.length !== entropyBuf0.length + entropyBuf1.length) { | |
throw new Error('generateRandomSeed: Logic error! Concatenation of entropy sources failed.'); | |
} | |
var hashedEnt = Hash.sha256(totalEnt); | |
return hashedEnt; | |
}; | |
// External static functions | |
// Generates a random seed. If the optional string | |
// extraEntropy is set, a random set of entropy | |
// is created, then concatenated with extraEntropy | |
// and hashed to produce the entropy that gives the seed. | |
// Thus if extraEntropy comes from a high-entropy source | |
// (like dice) it can give some protection from a bad RNG. | |
// If extraEntropy is not set, the random number generator | |
// is used directly. | |
KeyStore.generateRandomSeed = function (extraEntropy) { | |
var seed = ''; | |
if (extraEntropy === undefined) { | |
seed = new Mnemonic(Mnemonic.Words.ENGLISH); | |
} else if (typeof extraEntropy === 'string') { | |
var entBuf = new Buffer(extraEntropy); | |
var randBuf = Random.getRandomBuffer(256 / 8); | |
var hashedEnt = this._concatAndSha256(randBuf, entBuf).slice(0, 128 / 8); | |
seed = new Mnemonic(hashedEnt, Mnemonic.Words.ENGLISH); | |
} else { | |
throw new Error('generateRandomSeed: extraEntropy is set but not a string.'); | |
} | |
return seed.toString(); | |
}; | |
KeyStore.isSeedValid = function (seed) { | |
return Mnemonic.isValid(seed, Mnemonic.Words.ENGLISH); | |
}; | |
// Takes keystore serialized as string and returns an instance of KeyStore | |
KeyStore.deserialize = function (keystore) { | |
var jsonKS = JSON.parse(keystore); | |
if (jsonKS.version === undefined || jsonKS.version !== 3) { | |
throw new Error('Old version of serialized keystore. Please use KeyStore.upgradeOldSerialized() to convert it to the latest version.'); | |
} | |
// Create keystore | |
var keystoreX = new KeyStore(); | |
keystoreX.salt = jsonKS.salt; | |
keystoreX.hdPathString = jsonKS.hdPathString; | |
keystoreX.encSeed = jsonKS.encSeed; | |
keystoreX.encHdRootPriv = jsonKS.encHdRootPriv; | |
keystoreX.version = jsonKS.version; | |
keystoreX.hdIndex = jsonKS.hdIndex; | |
keystoreX.encPrivKeys = jsonKS.encPrivKeys; | |
keystoreX.addresses = jsonKS.addresses; | |
return keystoreX; | |
}; | |
KeyStore.deriveKeyFromPasswordAndSalt = function (password, salt, callback) { | |
// Do not require salt, and default it to 'lightwalletSalt' | |
// (for backwards compatibility) | |
if (!callback && typeof salt === 'function') { | |
callback = salt; | |
salt = 'lightwalletSalt'; | |
} else if (!salt && typeof callback === 'function') { | |
salt = 'lightwalletSalt'; | |
} | |
var logN = 14; | |
var r = 8; | |
var dkLen = 32; | |
var interruptStep = 200; | |
var cb = function cb(derKey) { | |
var err = null; | |
var ui8arr = null; | |
try { | |
ui8arr = new Uint8Array(derKey); | |
} catch (e) { | |
err = e; | |
} | |
callback(err, ui8arr); | |
}; | |
scrypt(password, salt, logN, r, dkLen, interruptStep, cb, null); | |
}; | |
// External API functions | |
KeyStore.prototype.serialize = function () { | |
var jsonKS = { 'encSeed': this.encSeed, | |
'encHdRootPriv': this.encHdRootPriv, | |
'addresses': this.addresses, | |
'encPrivKeys': this.encPrivKeys, | |
'hdPathString': this.hdPathString, | |
'salt': this.salt, | |
'hdIndex': this.hdIndex, | |
'version': this.version }; | |
return JSON.stringify(jsonKS); | |
}; | |
KeyStore.prototype.getAddresses = function () { | |
var prefixedAddresses = this.addresses.map(function (addr) { | |
return add0x(addr); | |
}); | |
return prefixedAddresses; | |
}; | |
KeyStore.prototype.getSeed = function (pwDerivedKey) { | |
if (!this.isDerivedKeyCorrect(pwDerivedKey)) { | |
throw new Error("Incorrect derived key!"); | |
} | |
var paddedSeed = KeyStore._decryptString(this.encSeed, pwDerivedKey); | |
return paddedSeed.trim(); | |
}; | |
KeyStore.prototype.exportPrivateKey = function (address, pwDerivedKey) { | |
if (!this.isDerivedKeyCorrect(pwDerivedKey)) { | |
throw new Error("Incorrect derived key!"); | |
} | |
var address = strip0x(address); | |
if (this.encPrivKeys[address] === undefined) { | |
throw new Error('KeyStore.exportPrivateKey: Address not found in KeyStore'); | |
} | |
var encPrivKey = this.encPrivKeys[address]; | |
var privKey = KeyStore._decryptKey(encPrivKey, pwDerivedKey); | |
return privKey; | |
}; | |
KeyStore.prototype.generateNewAddress = function (pwDerivedKey, n) { | |
if (!this.isDerivedKeyCorrect(pwDerivedKey)) { | |
throw new Error("Incorrect derived key!"); | |
} | |
if (!this.encSeed) { | |
throw new Error('KeyStore.generateNewAddress: No seed set'); | |
} | |
n = n || 1; | |
var keys = this._generatePrivKeys(pwDerivedKey, n); | |
for (var i = 0; i < n; i++) { | |
var keyObj = keys[i]; | |
var address = KeyStore._computeAddressFromPrivKey(keyObj.privKey); | |
this.encPrivKeys[address] = keyObj.encPrivKey; | |
this.addresses.push(address); | |
} | |
}; | |
KeyStore.prototype.keyFromPassword = function (password, callback) { | |
KeyStore.deriveKeyFromPasswordAndSalt(password, this.salt, callback); | |
}; | |
// Async functions exposed for Hooked Web3-provider | |
// hasAddress(address, callback) | |
// signTransaction(txParams, callback) | |
// | |
// The function signTransaction() needs the | |
// function KeyStore.prototype.passwordProvider(callback) | |
// to be set in order to run properly. | |
// The function passwordProvider is an async function | |
// that calls the callback(err, password) with a password | |
// supplied by the user or by other means. | |
// The user of the hooked web3-provider is encouraged | |
// to write their own passwordProvider. | |
// | |
// Uses defaultHdPathString for the addresses. | |
KeyStore.prototype.passwordProvider = function (callback) { | |
var password = prompt("Enter password to continue", "Enter password"); | |
callback(null, password); | |
}; | |
KeyStore.prototype.hasAddress = function (address, callback) { | |
var addrToCheck = strip0x(address); | |
if (this.encPrivKeys[addrToCheck] === undefined) { | |
callback('Address not found!', false); | |
} else { | |
callback(null, true); | |
} | |
}; | |
KeyStore.prototype.signTransaction = function (txParams, callback) { | |
var _this = this; | |
var ethjsTxParams = {}; | |
ethjsTxParams.from = add0x(txParams.from); | |
ethjsTxParams.to = add0x(txParams.to); | |
ethjsTxParams.gasLimit = add0x(txParams.gas); | |
ethjsTxParams.gasPrice = add0x(txParams.gasPrice); | |
ethjsTxParams.nonce = add0x(txParams.nonce); | |
ethjsTxParams.value = add0x(txParams.value); | |
ethjsTxParams.data = add0x(txParams.data); | |
var txObj = new Transaction(ethjsTxParams); | |
var rawTx = txObj.serialize().toString('hex'); | |
var signingAddress = strip0x(txParams.from); | |
var salt = this.salt; | |
var self = this; | |
this.passwordProvider(function (err, password, salt) { | |
if (err) return callback(err); | |
if (!salt) { | |
salt = _this.salt; | |
} | |
_this.keyFromPassword(password, function (err, pwDerivedKey) { | |
if (err) return callback(err); | |
var signedTx = signing.signTx(self, pwDerivedKey, rawTx, signingAddress, self.defaultHdPathString); | |
callback(null, '0x' + signedTx); | |
}); | |
}); | |
}; | |
module.exports = KeyStore; | |
}).call(this,require("buffer").Buffer) | |
},{"./encryption":2,"./signing":4,"bitcore-lib":26,"bitcore-mnemonic":88,"buffer":148,"crypto-js":182,"elliptic":218,"ethereumjs-tx":234,"scrypt-async":315,"tweetnacl":349}],4:[function(require,module,exports){ | |
(function (Buffer){ | |
"use strict"; | |
var Transaction = require("ethereumjs-tx"); | |
var util = require("ethereumjs-util"); | |
var signTx = function signTx(keystore, pwDerivedKey, rawTx, signingAddress) { | |
if (!keystore.isDerivedKeyCorrect(pwDerivedKey)) { | |
throw new Error("Incorrect derived key!"); | |
} | |
rawTx = util.stripHexPrefix(rawTx); | |
signingAddress = util.stripHexPrefix(signingAddress); | |
var txCopy = new Transaction(new Buffer(rawTx, 'hex')); | |
var privKey = keystore.exportPrivateKey(signingAddress, pwDerivedKey); | |
txCopy.sign(new Buffer(privKey, 'hex')); | |
privKey = ''; | |
return txCopy.serialize().toString('hex'); | |
}; | |
module.exports.signTx = signTx; | |
var signMsg = function signMsg(keystore, pwDerivedKey, rawMsg, signingAddress) { | |
if (!keystore.isDerivedKeyCorrect(pwDerivedKey)) { | |
throw new Error("Incorrect derived key!"); | |
} | |
var msgHash = util.addHexPrefix(util.sha3(rawMsg).toString('hex')); | |
return this.signMsgHash(keystore, pwDerivedKey, msgHash, signingAddress); | |
}; | |
module.exports.signMsg = signMsg; | |
var signMsgHash = function signMsgHash(keystore, pwDerivedKey, msgHash, signingAddress) { | |
if (!keystore.isDerivedKeyCorrect(pwDerivedKey)) { | |
throw new Error("Incorrect derived key!"); | |
} | |
signingAddress = util.stripHexPrefix(signingAddress); | |
var privKey = keystore.exportPrivateKey(signingAddress, pwDerivedKey); | |
return util.ecsign(new Buffer(util.stripHexPrefix(msgHash), 'hex'), new Buffer(privKey, 'hex')); | |
}; | |
module.exports.signMsgHash = signMsgHash; | |
var recoverAddress = function recoverAddress(rawMsg, v, r, s) { | |
var msgHash = util.sha3(rawMsg); | |
return util.pubToAddress(util.ecrecover(msgHash, v, r, s)); | |
}; | |
module.exports.recoverAddress = recoverAddress; | |
var concatSig = function concatSig(signature) { | |
var v = signature.v; | |
var r = signature.r; | |
var s = signature.s; | |
r = util.fromSigned(r); | |
s = util.fromSigned(s); | |
v = util.bufferToInt(v); | |
r = util.setLengthLeft(util.toUnsigned(r), 32).toString('hex'); | |
s = util.setLengthLeft(util.toUnsigned(s), 32).toString('hex'); | |
v = util.stripHexPrefix(util.intToHex(v)); | |
return util.addHexPrefix(r.concat(s, v).toString("hex")); | |
}; | |
module.exports.concatSig = concatSig; | |
}).call(this,require("buffer").Buffer) | |
},{"buffer":148,"ethereumjs-tx":234,"ethereumjs-util":235}],5:[function(require,module,exports){ | |
(function (Buffer){ | |
'use strict'; | |
var Transaction = require('ethereumjs-tx'); | |
var coder = require('web3/lib/solidity/coder'); | |
// When updating to web3 1.0.0, replace by | |
// var coder = require('web3-eth-abi'); | |
var rlp = require('rlp'); | |
var CryptoJS = require('crypto-js'); | |
function add0x(input) { | |
if (typeof input !== 'string') { | |
return input; | |
} | |
if (input.length < 2 || input.slice(0, 2) !== '0x') { | |
return '0x' + input; | |
} | |
return input; | |
} | |
function strip0x(input) { | |
if (typeof input !== 'string') { | |
return input; | |
} else if (input.length >= 2 && input.slice(0, 2) === '0x') { | |
return input.slice(2); | |
} else { | |
return input; | |
} | |
} | |
function _encodeFunctionTxData(functionName, types, args) { | |
var fullName = functionName + '(' + types.join() + ')'; | |
var signature = CryptoJS.SHA3(fullName, { outputLength: 256 }).toString(CryptoJS.enc.Hex).slice(0, 8); | |
var dataHex = '0x' + signature + coder.encodeParams(types, args); | |
// When updating to web3 1.0.0, replace by | |
// var dataHex = coder.encodeFunctionSignature(fullName) + coder.encodeParameters(types, args).replace('0x','') | |
return dataHex; | |
} | |
function _getTypesFromAbi(abi, functionName) { | |
function matchesFunctionName(json) { | |
return json.name === functionName && json.type === 'function'; | |
} | |
function getTypes(json) { | |
return json.type; | |
} | |
var funcJson = abi.filter(matchesFunctionName)[0]; | |
return funcJson.inputs.map(getTypes); | |
} | |
function functionTx(abi, functionName, args, txObject) { | |
// txObject contains gasPrice, gasLimit, nonce, to, value | |
var types = _getTypesFromAbi(abi, functionName); | |
var txData = _encodeFunctionTxData(functionName, types, args); | |
var txObjectCopy = {}; | |
txObjectCopy.to = add0x(txObject.to); | |
txObjectCopy.gasPrice = add0x(txObject.gasPrice); | |
txObjectCopy.gasLimit = add0x(txObject.gasLimit); | |
txObjectCopy.nonce = add0x(txObject.nonce); | |
txObjectCopy.data = add0x(txData); | |
txObjectCopy.value = add0x(txObject.value); | |
return '0x' + new Transaction(txObjectCopy).serialize().toString('hex'); | |
} | |
function createdContractAddress(fromAddress, nonce) { | |
var rlpEncodedHex = rlp.encode([new Buffer(strip0x(fromAddress), 'hex'), nonce]).toString('hex'); | |
var rlpEncodedWordArray = CryptoJS.enc.Hex.parse(rlpEncodedHex); | |
var hash = CryptoJS.SHA3(rlpEncodedWordArray, { outputLength: 256 }).toString(CryptoJS.enc.Hex); | |
return '0x' + hash.slice(24); | |
} | |
function createContractTx(fromAddress, txObject) { | |
// txObject contains gasPrice, gasLimit, value, data, nonce | |
var txObjectCopy = {}; | |
txObjectCopy.to = add0x(txObject.to); | |
txObjectCopy.gasPrice = add0x(txObject.gasPrice); | |
txObjectCopy.gasLimit = add0x(txObject.gasLimit); | |
txObjectCopy.nonce = add0x(txObject.nonce); | |
txObjectCopy.data = add0x(txObject.data); | |
txObjectCopy.value = add0x(txObject.value); | |
var contractAddress = createdContractAddress(fromAddress, txObject.nonce); | |
var tx = new Transaction(txObjectCopy); | |
return { tx: '0x' + tx.serialize().toString('hex'), addr: contractAddress }; | |
} | |
function valueTx(txObject) { | |
// txObject contains gasPrice, gasLimit, value, nonce | |
var txObjectCopy = {}; | |
txObjectCopy.to = add0x(txObject.to); | |
txObjectCopy.gasPrice = add0x(txObject.gasPrice); | |
txObjectCopy.gasLimit = add0x(txObject.gasLimit); | |
txObjectCopy.nonce = add0x(txObject.nonce); | |
txObjectCopy.value = add0x(txObject.value); | |
var tx = new Transaction(txObjectCopy); | |
return '0x' + tx.serialize().toString('hex'); | |
} | |
module.exports = { | |
_encodeFunctionTxData: _encodeFunctionTxData, | |
_getTypesFromAbi: _getTypesFromAbi, | |
functionTx: functionTx, | |
createdContractAddress: createdContractAddress, | |
createContractTx: createContractTx, | |
valueTx: valueTx | |
}; | |
}).call(this,require("buffer").Buffer) | |
},{"buffer":148,"crypto-js":182,"ethereumjs-tx":234,"rlp":313,"web3/lib/solidity/coder":361}],6:[function(require,module,exports){ | |
'use strict'; | |
var CryptoJS = require('crypto-js'); | |
var keystore = require('./keystore'); | |
var Transaction = require('ethereumjs-tx'); | |
var EC = require('elliptic').ec; | |
var ec = new EC('secp256k1'); | |
var bitcore = require('bitcore-lib'); | |
var Random = bitcore.crypto.Random; | |
var Hash = bitcore.crypto.Hash; | |
var Mnemonic = require('bitcore-mnemonic'); | |
var nacl = require('tweetnacl'); | |
var scrypt = require('scrypt-async'); | |
var legacyDecryptString = function legacyDecryptString(encryptedStr, password) { | |
var decryptedStr = CryptoJS.AES.decrypt(encryptedStr.encStr, password, { 'iv': encryptedStr.iv, 'salt': encryptedStr.salt }); | |
return decryptedStr.toString(CryptoJS.enc.Latin1); | |
}; | |
var legacyGenerateEncKey = function legacyGenerateEncKey(password, salt, keyHash) { | |
var encKey = CryptoJS.PBKDF2(password, salt, { keySize: 512 / 32, iterations: 150 }).toString(); | |
var hash = CryptoJS.SHA3(encKey).toString(); | |
if (keyHash !== hash) { | |
throw new Error('Invalid Password'); | |
} | |
return encKey; | |
}; | |
var upgradeOldSerialized = function upgradeOldSerialized(oldSerialized, password, callback) { | |
// Upgrades old serialized version of the keystore | |
// to the latest version | |
var oldKS = JSON.parse(oldSerialized); | |
if (oldKS.version === undefined || oldKS.version === 1) { | |
var derivedKey = legacyGenerateEncKey(password, oldKS.salt, oldKS.keyHash); | |
var seed = legacyDecryptString(oldKS.encSeed, derivedKey); | |
keystore.createVault({ | |
password: password, | |
seedPhrase: seed, | |
salt: 'lightwalletSalt', | |
hdPathString: "m/0'/0'/0'" | |
}, function (err, newKeyStore) { | |
newKeyStore.keyFromPassword(password, function (err, pwDerivedKey) { | |
var hdIndex = oldKS.hdIndex; | |
newKeyStore.generateNewAddress(pwDerivedKey, hdIndex); | |
callback(null, newKeyStore.serialize()); | |
}); | |
}); | |
} else if (oldKS.version === 2) { | |
var salt = 'lightWalletSalt'; | |
if (oldKS.salt !== undefined) { | |
salt = oldKS.salt; | |
} | |
keystore.deriveKeyFromPasswordAndSalt(password, salt, function (err, pwKey) { | |
var seed = keystore._decryptString(oldKS.encSeed, pwKey).trim(); | |
var hdPaths = Object.keys(oldKS.ksData); | |
var hdPathString = ''; | |
if (hdPaths.length === 1) { | |
hdPathString = hdPaths[0]; | |
} | |
keystore.createVault({ | |
password: password, | |
seedPhrase: seed, | |
salt: salt, | |
hdPathString: hdPathString | |
}, function (err, newKeyStore) { | |
newKeyStore.keyFromPassword(password, function (err, pwDerivedKey) { | |
var hdIndex = oldKS.ksData[hdPathString].hdIndex; | |
newKeyStore.generateNewAddress(pwDerivedKey, hdIndex); | |
callback(null, newKeyStore.serialize()); | |
}); | |
}); | |
}); | |
} else { | |
throw new Error('Keystore is not of correct version.'); | |
} | |
}; | |
module.exports.upgradeOldSerialized = upgradeOldSerialized; | |
},{"./keystore":3,"bitcore-lib":26,"bitcore-mnemonic":88,"crypto-js":182,"elliptic":218,"ethereumjs-tx":234,"scrypt-async":315,"tweetnacl":349}],7:[function(require,module,exports){ | |
'use strict'; | |
var asn1 = exports; | |
asn1.bignum = require('bn.js'); | |
asn1.define = require('./asn1/api').define; | |
asn1.base = require('./asn1/base'); | |
asn1.constants = require('./asn1/constants'); | |
asn1.decoders = require('./asn1/decoders'); | |
asn1.encoders = require('./asn1/encoders'); | |
},{"./asn1/api":8,"./asn1/base":10,"./asn1/constants":14,"./asn1/decoders":16,"./asn1/encoders":19,"bn.js":99}],8:[function(require,module,exports){ | |
'use strict'; | |
var asn1 = require('../asn1'); | |
var inherits = require('inherits'); | |
var api = exports; | |
api.define = function define(name, body) { | |
return new Entity(name, body); | |
}; | |
function Entity(name, body) { | |
this.name = name; | |
this.body = body; | |
this.decoders = {}; | |
this.encoders = {}; | |
}; | |
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 named(entity) { | |
this._initNamed(entity); | |
}; | |
} | |
inherits(named, base); | |
named.prototype._initNamed = function initnamed(entity) { | |
base.call(this, entity); | |
}; | |
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(asn1.decoders[enc]); | |
return this.decoders[enc]; | |
}; | |
Entity.prototype.decode = function decode(data, enc, options) { | |
return this._getDecoder(enc).decode(data, options); | |
}; | |
Entity.prototype._getEncoder = function _getEncoder(enc) { | |
enc = enc || 'der'; | |
// Lazily create encoder | |
if (!this.encoders.hasOwnProperty(enc)) this.encoders[enc] = this._createNamed(asn1.encoders[enc]); | |
return this.encoders[enc]; | |
}; | |
Entity.prototype.encode = function encode(data, enc, /* internal */reporter) { | |
return this._getEncoder(enc).encode(data, reporter); | |
}; | |
},{"../asn1":7,"inherits":256,"vm":357}],9:[function(require,module,exports){ | |
'use strict'; | |
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; | |
var inherits = require('inherits'); | |
var Reporter = require('../base').Reporter; | |
var Buffer = require('buffer').Buffer; | |
function DecoderBuffer(base, options) { | |
Reporter.call(this, options); | |
if (!Buffer.isBuffer(base)) { | |
this.error('Input not Buffer'); | |
return; | |
} | |
this.base = base; | |
this.offset = 0; | |
this.length = base.length; | |
} | |
inherits(DecoderBuffer, Reporter); | |
exports.DecoderBuffer = DecoderBuffer; | |
DecoderBuffer.prototype.save = function save() { | |
return { offset: this.offset, reporter: Reporter.prototype.save.call(this) }; | |
}; | |
DecoderBuffer.prototype.restore = function restore(save) { | |
// Return skipped data | |
var res = new DecoderBuffer(this.base); | |
res.offset = save.offset; | |
res.length = this.offset; | |
this.offset = save.offset; | |
Reporter.prototype.restore.call(this, save.reporter); | |
return res; | |
}; | |
DecoderBuffer.prototype.isEmpty = function isEmpty() { | |
return this.offset === this.length; | |
}; | |
DecoderBuffer.prototype.readUInt8 = function readUInt8(fail) { | |
if (this.offset + 1 <= this.length) 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'); | |
var res = new DecoderBuffer(this.base); | |
// Share reporter state | |
res._reporterState = this._reporterState; | |
res.offset = this.offset; | |
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 (!(item instanceof EncoderBuffer)) item = new EncoderBuffer(item, reporter); | |
this.length += item.length; | |
return item; | |
}, this); | |
} else if (typeof value === 'number') { | |
if (!(0 <= value && value <= 0xff)) return reporter.error('non-byte EncoderBuffer value'); | |
this.value = value; | |
this.length = 1; | |
} else if (typeof value === 'string') { | |
this.value = value; | |
this.length = Buffer.byteLength(value); | |
} else if (Buffer.isBuffer(value)) { | |
this.value = value; | |
this.length = value.length; | |
} else { | |
return reporter.error('Unsupported type: ' + (typeof value === 'undefined' ? 'undefined' : _typeof(value))); | |
} | |
} | |
exports.EncoderBuffer = EncoderBuffer; | |
EncoderBuffer.prototype.join = function join(out, offset) { | |
if (!out) out = new Buffer(this.length); | |
if (!offset) offset = 0; | |
if (this.length === 0) return out; | |
if (Array.isArray(this.value)) { | |
this.value.forEach(function (item) { | |
item.join(out, offset); | |
offset += item.length; | |
}); | |
} else { | |
if (typeof this.value === 'number') out[offset] = this.value;else if (typeof this.value === 'string') out.write(this.value, offset);else if (Buffer.isBuffer(this.value)) this.value.copy(out, offset); | |
offset += this.length; | |
} | |
return out; | |
}; | |
},{"../base":10,"buffer":148,"inherits":256}],10:[function(require,module,exports){ | |
'use strict'; | |
var base = exports; | |
base.Reporter = require('./reporter').Reporter; | |
base.DecoderBuffer = require('./buffer').DecoderBuffer; | |
base.EncoderBuffer = require('./buffer').EncoderBuffer; | |
base.Node = require('./node'); | |
},{"./buffer":9,"./node":11,"./reporter":12}],11:[function(require,module,exports){ | |
'use strict'; | |
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; | |
var Reporter = require('../base').Reporter; | |
var EncoderBuffer = require('../base').EncoderBuffer; | |
var DecoderBuffer = require('../base').DecoderBuffer; | |
var assert = require('minimalistic-assert'); | |
// Supported tags | |
var tags = ['seq', 'seqof', 'set', 'setof', 'objid', 'bool', 'gentime', 'utctime', 'null_', 'enum', 'int', 'objDesc', 'bitstr', 'bmpstr', 'charstr', 'genstr', 'graphstr', 'ia5str', 'iso646str', 'numstr', 'octstr', 'printstr', 't61str', 'unistr', 'utf8str', 'videostr']; | |
// Public methods list | |
var methods = ['key', 'obj', 'use', 'optional', 'explicit', 'implicit', 'def', 'choice', 'any', 'contains'].concat(tags); | |
// Overrided methods list | |
var overrided = ['_peekTag', '_decodeTag', '_use', '_decodeStr', '_decodeObjid', '_decodeTime', '_decodeNull', '_decodeInt', '_decodeBool', '_decodeList', '_encodeComposite', '_encodeStr', '_encodeObjid', '_encodeTime', '_encodeNull', '_encodeInt', '_encodeBool']; | |
function Node(enc, parent) { | |
var state = {}; | |
this._baseState = state; | |
state.enc = enc; | |
state.parent = parent || null; | |
state.children = null; | |
// State | |
state.tag = null; | |
state.args = null; | |
state.reverseArgs = null; | |
state.choice = null; | |
state.optional = false; | |
state.any = false; | |
state.obj = false; | |
state.use = null; | |
state.useDecoder = null; | |
state.key = null; | |
state['default'] = null; | |
state.explicit = null; | |
state.implicit = null; | |
state.contains = null; | |
// Should create new instance on each method | |
if (!state.parent) { | |
state.children = []; | |
this._wrap(); | |
} | |
} | |
module.exports = Node; | |
var stateProps = ['enc', 'parent', 'children', 'tag', 'args', 'reverseArgs', 'choice', 'optional', 'any', 'obj', 'use', 'alteredUse', 'key', 'default', 'explicit', 'implicit', 'contains']; | |
Node.prototype.clone = function clone() { | |
var state = this._baseState; | |
var cstate = {}; | |
stateProps.forEach(function (prop) { | |
cstate[prop] = state[prop]; | |
}); | |
var res = new this.constructor(cstate.parent); | |
res._baseState = cstate; | |
return res; | |
}; | |
Node.prototype._wrap = function wrap() { | |
var state = this._baseState; | |
methods.forEach(function (method) { | |
this[method] = function _wrappedMethod() { | |
var clone = new this.constructor(this); | |
state.children.push(clone); | |
return clone[method].apply(clone, arguments); | |
}; | |
}, this); | |
}; | |
Node.prototype._init = function init(body) { | |
var state = this._baseState; | |
assert(state.parent === null); | |
body.call(this); | |
// Filter children | |
state.children = state.children.filter(function (child) { | |
return child._baseState.parent === this; | |
}, this); | |
assert.equal(state.children.length, 1, 'Root node can have only one child'); | |
}; | |
Node.prototype._useArgs = function useArgs(args) { | |
var state = this._baseState; | |
// Filter children and args | |
var children = args.filter(function (arg) { | |
return arg instanceof this.constructor; | |
}, this); | |
args = args.filter(function (arg) { | |
return !(arg instanceof this.constructor); | |
}, this); | |
if (children.length !== 0) { | |
assert(state.children === null); | |
state.children = children; | |
// Replace parent to maintain backward link | |
children.forEach(function (child) { | |
child._baseState.parent = this; | |
}, this); | |
} | |
if (args.length !== 0) { | |
assert(state.args === null); | |
state.args = args; | |
state.reverseArgs = args.map(function (arg) { | |
if ((typeof arg === 'undefined' ? 'undefined' : _typeof(arg)) !== 'object' || arg.constructor !== Object) return arg; | |
var res = {}; | |
Object.keys(arg).forEach(function (key) { | |
if (key == (key | 0)) key |= 0; | |
var value = arg[key]; | |
res[value] = key; | |
}); | |
return res; | |
}); | |
} | |
}; | |
// | |
// Overrided methods | |
// | |
overrided.forEach(function (method) { | |
Node.prototype[method] = function _overrided() { | |
var state = this._baseState; | |
throw new Error(method + ' not implemented for encoding: ' + state.enc); | |
}; | |
}); | |
// | |
// Public methods | |
// | |
tags.forEach(function (tag) { | |
Node.prototype[tag] = function _tagMethod() { | |
var state = this._baseState; | |
var args = Array.prototype.slice.call(arguments); | |
assert(state.tag === null); | |
state.tag = tag; | |
this._useArgs(args); | |
return this; | |
}; | |
}); | |
Node.prototype.use = function use(item) { | |
assert(item); | |
var state = this._baseState; | |
assert(state.use === null); | |
state.use = item; | |
return this; | |
}; | |
Node.prototype.optional = function optional() { | |
var state = this._baseState; | |
state.optional = true; | |
return this; | |
}; | |
Node.prototype.def = function def(val) { | |
var state = this._baseState; | |
assert(state['default'] === null); | |
state['default'] = val; | |
state.optional = true; | |
return this; | |
}; | |
Node.prototype.explicit = function explicit(num) { | |
var state = this._baseState; | |
assert(state.explicit === null && state.implicit === null); | |
state.explicit = num; | |
return this; | |
}; | |
Node.prototype.implicit = function implicit(num) { | |
var state = this._baseState; | |
assert(state.explicit === null && state.implicit === null); | |
state.implicit = num; | |
return this; | |
}; | |
Node.prototype.obj = function obj() { | |
var state = this._baseState; | |
var args = Array.prototype.slice.call(arguments); | |
state.obj = true; | |
if (args.length !== 0) this._useArgs(args); | |
return this; | |
}; | |
Node.prototype.key = function key(newKey) { | |
var state = this._baseState; | |
assert(state.key === null); | |
state.key = newKey; | |
return this; | |
}; | |
Node.prototype.any = function any() { | |
var state = this._baseState; | |
state.any = true; | |
return this; | |
}; | |
Node.prototype.choice = function choice(obj) { | |
var state = this._baseState; | |
assert(state.choice === null); | |
state.choice = obj; | |
this._useArgs(Object.keys(obj).map(function (key) { | |
return obj[key]; | |
})); | |
return this; | |
}; | |
Node.prototype.contains = function contains(item) { | |
var state = this._baseState; | |
assert(state.use === null); | |
state.contains = item; | |
return this; | |
}; | |
// | |
// Decoding | |
// | |
Node.prototype._decode = function decode(input, options) { | |
var state = this._baseState; | |
// Decode root node | |
if (state.parent === null) return input.wrapResult(state.children[0]._decode(input, options)); | |
var result = state['default']; | |
var present = true; | |
var prevKey = null; | |
if (state.key !== null) prevKey = input.enterKey(state.key); | |
// Check if tag is there | |
if (state.optional) { | |
var tag = null; | |
if (state.explicit !== null) tag = state.explicit;else if (state.implicit !== null) tag = state.implicit;else if (state.tag !== null) tag = state.tag; | |
if (tag === null && !state.any) { | |
// Trial and Error | |
var save = input.save(); | |
try { | |
if (state.choice === null) this._decodeGeneric(state.tag, input, options);else this._decodeChoice(input, options); | |
present = true; | |
} catch (e) { | |
present = false; | |
} | |
input.restore(save); | |
} else { | |
present = this._peekTag(input, tag, state.any); | |
if (input.isError(present)) return present; | |
} | |
} | |
// Push object on stack | |
var prevObj; | |
if (state.obj && present) prevObj = input.enterObject(); | |
if (present) { | |
// Unwrap explicit values | |
if (state.explicit !== null) { | |
var explicit = this._decodeTag(input, state.explicit); | |
if (input.isError(explicit)) return explicit; | |
input = explicit; | |
} | |
var start = input.offset; | |
// Unwrap implicit and normal values | |
if (state.use === null && state.choice === null) { | |
if (state.any) var save = input.save(); | |
var body = this._decodeTag(input, state.implicit !== null ? state.implicit : state.tag, state.any); | |
if (input.isError(body)) return body; | |
if (state.any) result = input.raw(save);else input = body; | |
} | |
if (options && options.track && state.tag !== null) options.track(input.path(), start, input.length, 'tagged'); | |
if (options && options.track && state.tag !== null) options.track(input.path(), input.offset, input.length, 'content'); | |
// Select proper method for tag | |
if (state.any) result = result;else if (state.choice === null) result = this._decodeGeneric(state.tag, input, options);else result = this._decodeChoice(input, options); | |
if (input.isError(result)) return result; | |
// Decode children | |
if (!state.any && state.choice === null && state.children !== null) { | |
state.children.forEach(function decodeChildren(child) { | |
// NOTE: We are ignoring errors here, to let parser continue with other | |
// parts of encoded data | |
child._decode(input, options); | |
}); | |
} | |
// Decode contained/encoded by schema, only in bit or octet strings | |
if (state.contains && (state.tag === 'octstr' || state.tag === 'bitstr')) { | |
var data = new DecoderBuffer(result); | |
result = this._getUse(state.contains, input._reporterState.obj)._decode(data, options); | |
} | |
} | |
// Pop object | |
if (state.obj && present) result = input.leaveObject(prevObj); | |
// Set key | |
if (state.key !== null && (result !== null || present === true)) input.leaveKey(prevKey, state.key, result);else if (prevKey !== null) input.exitKey(prevKey); | |
return result; | |
}; | |
Node.prototype._decodeGeneric = function decodeGeneric(tag, input, options) { | |
var state = this._baseState; | |
if (tag === 'seq' || tag === 'set') return null; | |
if (tag === 'seqof' || tag === 'setof') return this._decodeList(input, tag, state.args[0], options);else if (/str$/.test(tag)) return this._decodeStr(input, tag, options);else if (tag === 'objid' && state.args) return this._decodeObjid(input, state.args[0], state.args[1], options);else if (tag === 'objid') return this._decodeObjid(input, null, null, options);else if (tag === 'gentime' || tag === 'utctime') return this._decodeTime(input, tag, options);else if (tag === 'null_') return this._decodeNull(input, options);else if (tag === 'bool') return this._decodeBool(input, options);else if (tag === 'objDesc') return this._decodeStr(input, tag, options);else if (tag === 'int' || tag === 'enum') return this._decodeInt(input, state.args && state.args[0], options); | |
if (state.use !== null) { | |
return this._getUse(state.use, input._reporterState.obj)._decode(input, options); | |
} else { | |
return input.error('unknown tag: ' + tag); | |
} | |
}; | |
Node.prototype._getUse = function _getUse(entity, obj) { | |
var state = this._baseState; | |
// Create altered use decoder if implicit is set | |
state.useDecoder = this._use(entity, obj); | |
assert(state.useDecoder._baseState.parent === null); | |
state.useDecoder = state.useDecoder._baseState.children[0]; | |
if (state.implicit !== state.useDecoder._baseState.implicit) { | |
state.useDecoder = state.useDecoder.clone(); | |
state.useDecoder._baseState.implicit = state.implicit; | |
} | |
return state.useDecoder; | |
}; | |
Node.prototype._decodeChoice = function decodeChoice(input, options) { | |
var state = this._baseState; | |
var result = null; | |
var match = false; | |
Object.keys(state.choice).some(function (key) { | |
var save = input.save(); | |
var node = state.choice[key]; | |
try { | |
var value = node._decode(input, options); | |
if (input.isError(value)) return false; | |
result = { type: key, value: value }; | |
match = true; | |
} catch (e) { | |
input.restore(save); | |
return false; | |
} | |
return true; | |
}, this); | |
if (!match) return input.error('Choice not matched'); | |
return result; | |
}; | |
// | |
// Encoding | |
// | |
Node.prototype._createEncoderBuffer = function createEncoderBuffer(data) { | |
return new EncoderBuffer(data, this.reporter); | |
}; | |
Node.prototype._encode = function encode(data, reporter, parent) { | |
var state = this._baseState; | |
if (state['default'] !== null && state['default'] === data) return; | |
var result = this._encodeValue(data, reporter, parent); | |
if (result === undefined) return; | |
if (this._skipDefault(result, reporter, parent)) return; | |
return result; | |
}; | |
Node.prototype._encodeValue = function encode(data, reporter, parent) { | |
var state = this._baseState; | |
// Decode root node | |
if (state.parent === null) return state.children[0]._encode(data, reporter || new Reporter()); | |
var result = null; | |
// Set reporter to share it with a child class | |
this.reporter = reporter; | |
// Check if data is there | |
if (state.optional && data === undefined) { | |
if (state['default'] !== null) data = state['default'];else return; | |
} | |
// Encode children first | |
var content = null; | |
var primitive = false; | |
if (state.any) { | |
// Anything that was given is translated to buffer | |
result = this._createEncoderBuffer(data); | |
} else if (state.choice) { | |
result = this._encodeChoice(data, reporter); | |
} else if (state.contains) { | |
content = this._getUse(state.contains, parent)._encode(data, reporter); | |
primitive = true; | |
} else if (state.children) { | |
content = state.children.map(function (child) { | |
if (child._baseState.tag === 'null_') return child._encode(null, reporter, data); | |
if (child._baseState.key === null) return reporter.error('Child should have a key'); | |
var prevKey = reporter.enterKey(child._baseState.key); | |
if ((typeof data === 'undefined' ? 'undefined' : _typeof(data)) !== 'object') return reporter.error('Child expected, but input is not object'); | |
var res = child._encode(data[child._baseState.key], reporter, data); | |
reporter.leaveKey(prevKey); | |
return res; | |
}, this).filter(function (child) { | |
return child; | |
}); | |
content = this._createEncoderBuffer(content); | |
} else { | |
if (state.tag === 'seqof' || state.tag === 'setof') { | |
// TODO(indutny): this should be thrown on DSL level | |
if (!(state.args && state.args.length === 1)) return reporter.error('Too many args for : ' + state.tag); | |
if (!Array.isArray(data)) return reporter.error('seqof/setof, but data is not Array'); | |
var child = this.clone(); | |
child._baseState.implicit = null; | |
content = this._createEncoderBuffer(data.map(function (item) { | |
var state = this._baseState; | |
return this._getUse(state.args[0], data)._encode(item, reporter); | |
}, child)); | |
} else if (state.use !== null) { | |
result = this._getUse(state.use, parent)._encode(data, reporter); | |
} else { | |
content = this._encodePrimitive(state.tag, data); | |
primitive = true; | |
} | |
} | |
// Encode data itself | |
var result; | |
if (!state.any && state.choice === null) { | |
var tag = state.implicit !== null ? state.implicit : state.tag; | |
var cls = state.implicit === null ? 'universal' : 'context'; | |
if (tag === null) { | |
if (state.use === null) reporter.error('Tag could be omitted only for .use()'); | |
} else { | |
if (state.use === null) result = this._encodeComposite(tag, primitive, cls, content); | |
} | |
} | |
// Wrap in explicit | |
if (state.explicit !== null) result = this._encodeComposite(state.explicit, false, 'context', result); | |
return result; | |
}; | |
Node.prototype._encodeChoice = function encodeChoice(data, reporter) { | |
var state = this._baseState; | |
var node = state.choice[data.type]; | |
if (!node) { | |
assert(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) { | |
var state = this._baseState; | |
if (/str$/.test(tag)) return this._encodeStr(data, tag);else if (tag === 'objid' && state.args) return this._encodeObjid(data, state.reverseArgs[0], state.args[1]);else if (tag === 'objid') return this._encodeObjid(data, null, null);else if (tag === 'gentime' || tag === 'utctime') return this._encodeTime(data, tag);else if (tag === 'null_') return this._encodeNull();else if (tag === 'int' || tag === 'enum') return this._encodeInt(data, state.args && state.reverseArgs[0]);else if (tag === 'bool') return this._encodeBool(data);else if (tag === 'objDesc') return this._encodeStr(data, tag);else throw new Error('Unsupported tag: ' + tag); | |
}; | |
Node.prototype._isNumstr = function isNumstr(str) { | |
return (/^[0-9 ]*$/.test(str) | |
); | |
}; | |
Node.prototype._isPrintstr = function isPrintstr(str) { | |
return (/^[A-Za-z0-9 '\(\)\+,\-\.\/:=\?]*$/.test(str) | |
); | |
}; | |
},{"../base":10,"minimalistic-assert":271}],12:[function(require,module,exports){ | |
'use strict'; | |
var inherits = require('inherits'); | |
function Reporter(options) { | |
this._reporterState = { | |
obj: null, | |
path: [], | |
options: options || {}, | |
errors: [] | |
}; | |
} | |
exports.Reporter = Reporter; | |
Reporter.prototype.isError = function isError(obj) { | |
return obj instanceof ReporterError; | |
}; | |
Reporter.prototype.save = function save() { | |
var state = this._reporterState; | |
return { obj: state.obj, pathLen: state.path.length }; | |
}; | |
Reporter.prototype.restore = function restore(data) { | |
var state = this._reporterState; | |
state.obj = data.obj; | |
state.path = state.path.slice(0, data.pathLen); | |
}; | |
Reporter.prototype.enterKey = function enterKey(key) { | |
return this._reporterState.path.push(key); | |
}; | |
Reporter.prototype.exitKey = function exitKey(index) { | |
var state = this._reporterState; | |
state.path = state.path.slice(0, index - 1); | |
}; | |
Reporter.prototype.leaveKey = function leaveKey(index, key, value) { | |
var state = this._reporterState; | |
this.exitKey(index); | |
if (state.obj !== null) state.obj[key] = value; | |
}; | |
Reporter.prototype.path = function path() { | |
return this._reporterState.path.join('/'); | |
}; | |
Reporter.prototype.enterObject = function enterObject() { | |
var state = this._reporterState; | |
var prev = state.obj; | |
state.obj = {}; | |
return prev; | |
}; | |
Reporter.prototype.leaveObject = function leaveObject(prev) { | |
var state = this._reporterState; | |
var now = state.obj; | |
state.obj = prev; | |
return now; | |
}; | |
Reporter.prototype.error = function error(msg) { | |
var err; | |
var state = this._reporterState; | |
var inherited = msg instanceof ReporterError; | |
if (inherited) { | |
err = msg; | |
} else { | |
err = new ReporterError(state.path.map(function (elem) { | |
return '[' + JSON.stringify(elem) + ']'; | |
}).join(''), msg.message || msg, msg.stack); | |
} | |
if (!state.options.partial) throw err; | |
if (!inherited) state.errors.push(err); | |
return err; | |
}; | |
Reporter.prototype.wrapResult = function wrapResult(result) { | |
var state = this._reporterState; | |
if (!state.options.partial) return result; | |
return { | |
result: this.isError(result) ? null : result, | |
errors: state.errors | |
}; | |
}; | |
function ReporterError(path, msg) { | |
this.path = path; | |
this.rethrow(msg); | |
}; | |
inherits(ReporterError, Error); | |
ReporterError.prototype.rethrow = function rethrow(msg) { | |
this.message = msg + ' at: ' + (this.path || '(shallow)'); | |
if (Error.captureStackTrace) Error.captureStackTrace(this, ReporterError); | |
if (!this.stack) { | |
try { | |
// IE only adds stack when thrown | |
throw new Error(this.message); | |
} catch (e) { | |
this.stack = e.stack; | |
} | |
} | |
return this; | |
}; | |
},{"inherits":256}],13:[function(require,module,exports){ | |
'use strict'; | |
var constants = require('../constants'); | |
exports.tagClass = { | |
0: 'universal', | |
1: 'application', | |
2: 'context', | |
3: 'private' | |
}; | |
exports.tagClassByName = constants._reverse(exports.tagClass); | |
exports.tag = { | |
0x00: 'end', | |
0x01: 'bool', | |
0x02: 'int', | |
0x03: 'bitstr', | |
0x04: 'octstr', | |
0x05: 'null_', | |
0x06: 'objid', | |
0x07: 'objDesc', | |
0x08: 'external', | |
0x09: 'real', | |
0x0a: 'enum', | |
0x0b: 'embed', | |
0x0c: 'utf8str', | |
0x0d: 'relativeOid', | |
0x10: 'seq', | |
0x11: 'set', | |
0x12: 'numstr', | |
0x13: 'printstr', | |
0x14: 't61str', | |
0x15: 'videostr', | |
0x16: 'ia5str', | |
0x17: 'utctime', | |
0x18: 'gentime', | |
0x19: 'graphstr', | |
0x1a: 'iso646str', | |
0x1b: 'genstr', | |
0x1c: 'unistr', | |
0x1d: 'charstr', | |
0x1e: 'bmpstr' | |
}; | |
exports.tagByName = constants._reverse(exports.tag); | |
},{"../constants":14}],14:[function(require,module,exports){ | |
'use strict'; | |
var constants = exports; | |
// Helper | |
constants._reverse = function reverse(map) { | |
var res = {}; | |
Object.keys(map).forEach(function (key) { | |
// Convert key to integer if it is stringified | |
if ((key | 0) == key) key = key | 0; | |
var value = map[key]; | |
res[value] = key; | |
}); | |
return res; | |
}; | |
constants.der = require('./der'); | |
},{"./der":13}],15:[function(require,module,exports){ | |
'use strict'; | |
var inherits = require('inherits'); | |
var asn1 = require('../../asn1'); | |
var base = asn1.base; | |
var bignum = asn1.bignum; | |
// Import DER constants | |
var der = asn1.constants.der; | |
function DERDecoder(entity) { | |
this.enc = 'der'; | |
this.name = entity.name; | |
this.entity = entity; | |
// Construct base tree | |
this.tree = new DERNode(); | |
this.tree._init(entity.body); | |
}; | |
module.exports = DERDecoder; | |
DERDecoder.prototype.decode = function decode(data, options) { | |
if (!(data instanceof base.DecoderBuffer)) data = new base.DecoderBuffer(data, options); | |
return this.tree._decode(data, options); | |
}; | |
// Tree methods | |
function DERNode(parent) { | |
base.Node.call(this, 'der', parent); | |
} | |
inherits(DERNode, base.Node); | |
DERNode.prototype._peekTag = function peekTag(buffer, tag, any) { | |
if (buffer.isEmpty()) return false; | |
var state = buffer.save(); | |
var decodedTag = derDecodeTag(buffer, 'Failed to peek tag: "' + tag + '"'); | |
if (buffer.isError(decodedTag)) return decodedTag; | |
buffer.restore(state); | |
return decodedTag.tag === tag || decodedTag.tagStr === tag || decodedTag.tagStr + 'of' === tag || any; | |
}; | |
DERNode.prototype._decodeTag = function decodeTag(buffer, tag, any) { | |
var decodedTag = derDecodeTag(buffer, 'Failed to decode tag of "' + tag + '"'); | |
if (buffer.isError(decodedTag)) return decodedTag; | |
var len = derDecodeLen(buffer, decodedTag.primitive, 'Failed to get length of "' + tag + '"'); | |
// Failure | |
if (buffer.isError(len)) return len; | |
if (!any && decodedTag.tag !== tag && decodedTag.tagStr !== tag && decodedTag.tagStr + 'of' !== tag) { | |
return buffer.error('Failed to match tag: "' + tag + '"'); | |
} | |
if (decodedTag.primitive || len !== null) return buffer.skip(len, 'Failed to match body of: "' + tag + '"'); | |
// Indefinite length... find END tag | |
var state = buffer.save(); | |
var res = this._skipUntilEnd(buffer, 'Failed to skip indefinite length body: "' + this.tag + '"'); | |
if (buffer.isError(res)) return res; | |
len = buffer.offset - state.offset; | |
buffer.restore(state); | |
return buffer.skip(len, 'Failed to match body of: "' + tag + '"'); | |
}; | |
DERNode.prototype._skipUntilEnd = function skipUntilEnd(buffer, fail) { | |
while (true) { | |
var tag = derDecodeTag(buffer, fail); | |
if (buffer.isError(tag)) return tag; | |
var len = derDecodeLen(buffer, tag.primitive, fail); | |
if (buffer.isError(len)) return len; | |
var res; | |
if (tag.primitive || len !== null) res = buffer.skip(len);else res = this._skipUntilEnd(buffer, fail); | |
// Failure | |
if (buffer.isError(res)) return res; | |
if (tag.tagStr === 'end') break; | |
} | |
}; | |
DERNode.prototype._decodeList = function decodeList(buffer, tag, decoder, options) { | |
var result = []; | |
while (!buffer.isEmpty()) { | |
var possibleEnd = this._peekTag(buffer, 'end'); | |
if (buffer.isError(possibleEnd)) return possibleEnd; | |
var res = decoder.decode(buffer, 'der', options); | |
if (buffer.isError(res) && possibleEnd) break; | |
result.push(res); | |
} | |
return result; | |
}; | |
DERNode.prototype._decodeStr = function decodeStr(buffer, tag) { | |
if (tag === 'bitstr') { | |
var unused = buffer.readUInt8(); | |
if (buffer.isError(unused)) return unused; | |
return { unused: unused, data: buffer.raw() }; | |
} else if (tag === 'bmpstr') { | |
var raw = buffer.raw(); | |
if (raw.length % 2 === 1) return buffer.error('Decoding of string type: bmpstr length mismatch'); | |
var str = ''; | |
for (var i = 0; i < raw.length / 2; i++) { | |
str += String.fromCharCode(raw.readUInt16BE(i * 2)); | |
} | |
return str; | |
} else if (tag === 'numstr') { | |
var numstr = buffer.raw().toString('ascii'); | |
if (!this._isNumstr(numstr)) { | |
return buffer.error('Decoding of string type: ' + 'numstr unsupported characters'); | |
} | |
return numstr; | |
} else if (tag === 'octstr') { | |
return buffer.raw(); | |
} else if (tag === 'objDesc') { | |
return buffer.raw(); | |
} else if (tag === 'printstr') { | |
var printstr = buffer.raw().toString('ascii'); | |
if (!this._isPrintstr(printstr)) { | |
return buffer.error('Decoding of string type: ' + 'printstr unsupported characters'); | |
} | |
return printstr; | |
} else if (/str$/.test(tag)) { | |
return buffer.raw().toString(); | |
} else { | |
return buffer.error('Decoding of string type: ' + tag + ' unsupported'); | |
} | |
}; | |
DERNode.prototype._decodeObjid = function decodeObjid(buffer, values, relative) { | |
var result; | |
var identifiers = []; | |
var ident = 0; | |
while (!buffer.isEmpty()) { | |
var subident = buffer.readUInt8(); | |
ident <<= 7; | |
ident |= subident & 0x7f; | |
if ((subident & 0x80) === 0) { | |
identifiers.push(ident); | |
ident = 0; | |
} | |
} | |
if (subident & 0x80) identifiers.push(ident); | |
var first = identifiers[0] / 40 | 0; | |
var second = identifiers[0] % 40; | |
if (relative) result = identifiers;else result = [first, second].concat(identifiers.slice(1)); | |
if (values) { | |
var tmp = values[result.join(' ')]; | |
if (tmp === undefined) tmp = values[result.join('.')]; | |
if (tmp !== undefined) result = tmp; | |
} | |
return result; | |
}; | |
DERNode.prototype._decodeTime = function decodeTime(buffer, tag) { | |
var str = buffer.raw().toString(); | |
if (tag === 'gentime') { | |
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') { | |
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 year = 1900 + year; | |
} else { | |
return buffer.error('Decoding ' + tag + ' time is not supported yet'); | |
} | |
return Date.UTC(year, mon - 1, day, hour, min, sec, 0); | |
}; | |
DERNode.prototype._decodeNull = function decodeNull(buffer) { | |
return null; | |
}; | |
DERNode.prototype._decodeBool = function decodeBool(buffer) { | |
var res = buffer.readUInt8(); | |
if (buffer.isError(res)) return res;else return res !== 0; | |
}; | |
DERNode.prototype._decodeInt = function decodeInt(buffer, values) { | |
// Bigint, return as it is (assume big endian) | |
var raw = buffer.raw(); | |
var res = new bignum(raw); | |
if (values) res = values[res.toString(10)] || res; | |
return res; | |
}; | |
DERNode.prototype._use = function use(entity, obj) { | |
if (typeof entity === 'function') entity = entity(obj); | |
return entity._getDecoder('der').tree; | |
}; | |
// Utility methods | |
function derDecodeTag(buf, fail) { | |
var tag = buf.readUInt8(fail); | |
if (buf.isError(tag)) return tag; | |
var cls = der.tagClass[tag >> 6]; | |
var primitive = (tag & 0x20) === 0; | |
// Multi-octet tag - load | |
if ((tag & 0x1f) === 0x1f) { | |
var oct = tag; | |
tag = 0; | |
while ((oct & 0x80) === 0x80) { | |
oct = buf.readUInt8(fail); | |
if (buf.isError(oct)) return oct; | |
tag <<= 7; | |
tag |= oct & 0x7f; | |
} | |
} else { | |
tag &= 0x1f; | |
} | |
var tagStr = der.tag[tag]; | |
return { | |
cls: cls, | |
primitive: primitive, | |
tag: tag, | |
tagStr: tagStr | |
}; | |
} | |
function derDecodeLen(buf, primitive, fail) { | |
var len = buf.readUInt8(fail); | |
if (buf.isError(len)) return len; | |
// Indefinite form | |
if (!primitive && len === 0x80) return null; | |
// Definite form | |
if ((len & 0x80) === 0) { | |
// Short form | |
return len; | |
} | |
// Long form | |
var num = len & 0x7f; | |
if (num > 4) return buf.error('length octect is too long'); | |
len = 0; | |
for (var i = 0; i < num; i++) { | |
len <<= 8; | |
var j = buf.readUInt8(fail); | |
if (buf.isError(j)) return j; | |
len |= j; | |
} | |
return len; | |
} | |
},{"../../asn1":7,"inherits":256}],16:[function(require,module,exports){ | |
'use strict'; | |
var decoders = exports; | |
decoders.der = require('./der'); | |
decoders.pem = require('./pem'); | |
},{"./der":15,"./pem":17}],17:[function(require,module,exports){ | |
'use strict'; | |
var inherits = require('inherits'); | |
var Buffer = require('buffer').Buffer; | |
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) { | |
var lines = data.toString().split(/[\r\n]+/g); | |
var label = options.label.toUpperCase(); | |
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; | |
if (match[2] !== label) continue; | |
if (start === -1) { | |
if (match[1] !== 'BEGIN') break; | |
start = i; | |
} else { | |
if (match[1] !== 'END') break; | |
end = i; | |
break; | |
} | |
} | |
if (start === -1 || end === -1) throw new Error('PEM section not found for: ' + label); | |
var base64 = lines.slice(start + 1, end).join(''); | |
// Remove excessive symbols | |
base64.replace(/[^a-z0-9\+\/=]+/gi, ''); | |
var input = new Buffer(base64, 'base64'); | |
return DERDecoder.prototype.decode.call(this, input, options); | |
}; | |
},{"./der":15,"buffer":148,"inherits":256}],18:[function(require,module,exports){ | |
'use strict'; | |
var inherits = require('inherits'); | |
var Buffer = require('buffer').Buffer; | |
var asn1 = require('../../asn1'); | |
var base = asn1.base; | |
// Import DER constants | |
var der = asn1.constants.der; | |
function DEREncoder(entity) { | |
this.enc = 'der'; | |
this.name = entity.name; | |
this.entity = entity; | |
// Construct base tree | |
this.tree = new DERNode(); | |
this.tree._init(entity.body); | |
}; | |
module.exports = DEREncoder; | |
DEREncoder.prototype.encode = function encode(data, reporter) { | |
return this.tree._encode(data, reporter).join(); | |
}; | |
// Tree methods | |
function DERNode(parent) { | |
base.Node.call(this, 'der', parent); | |
} | |
inherits(DERNode, base.Node); | |
DERNode.prototype._encodeComposite = function encodeComposite(tag, primitive, cls, content) { | |
var encodedTag = encodeTag(tag, primitive, cls, this.reporter); | |
// Short form | |
if (content.length < 0x80) { | |
var header = new Buffer(2); | |
header[0] = encodedTag; | |
header[1] = content.length; | |
return this._createEncoderBuffer([header, content]); | |
} | |
// Long form | |
// Count octets required to store length | |
var lenOctets = 1; | |
for (var i = content.length; i >= 0x100; i >>= 8) { | |
lenOctets++; | |
}var header = new Buffer(1 + 1 + lenOctets); | |
header[0] = encodedTag; | |
header[1] = 0x80 | lenOctets; | |
for (var i = 1 + lenOctets, j = content.length; j > 0; i--, j >>= 8) { | |
header[i] = j & 0xff; | |
}return this._createEncoderBuffer([header, content]); | |
}; | |
DERNode.prototype._encodeStr = function encodeStr(str, tag) { | |
if (tag === 'bitstr') { | |
return this._createEncoderBuffer([str.unused | 0, str.data]); | |
} else if (tag === 'bmpstr') { | |
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); | |
} else if (tag === 'numstr') { | |
if (!this._isNumstr(str)) { | |
return this.reporter.error('Encoding of string type: numstr supports ' + 'only digits and space'); | |
} | |
return this._createEncoderBuffer(str); | |
} else if (tag === 'printstr') { | |
if (!this._isPrintstr(str)) { | |
return this.reporter.error('Encoding of string type: printstr supports ' + 'only latin upper and lower case letters, ' + 'digits, space, apostrophe, left and rigth ' + 'parenthesis, plus sign, comma, hyphen, ' + 'dot, slash, colon, equal sign, ' + 'question mark'); | |
} | |
return this._createEncoderBuffer(str); | |
} else if (/str$/.test(tag)) { | |
return this._createEncoderBuffer(str); | |
} else if (tag === 'objDesc') { | |
return this._createEncoderBuffer(str); | |
} else { | |
return this.reporter.error('Encoding of string type: ' + tag + ' unsupported'); | |
} | |
}; | |
DERNode.prototype._encodeObjid = function encodeObjid(id, values, relative) { | |
if (typeof id === 'string') { | |
if (!values) 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 (var i = 0; i < id.length; i++) { | |
id[i] |= 0; | |
} | |
} else if (Array.isArray(id)) { | |
id = id.slice(); | |
for (var i = 0; i < id.length; i++) { | |
id[i] |= 0; | |
} | |
} | |
if (!Array.isArray(id)) { | |
return this.reporter.error('objid() should be either array or string, ' + 'got: ' + JSON.stringify(id)); | |
} | |
if (!relative) { | |
if (id[1] >= 40) return this.reporter.error('Second objid identifier OOB'); | |
id.splice(0, 2, id[0] * 40 + id[1]); | |
} | |
// Count number of octets | |
var size = 0; | |
for (var i = 0; i < id.length; i++) { | |
var ident = id[i]; | |
for (size++; ident >= 0x80; ident >>= 7) { | |
size++; | |
} | |
} | |
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; | |
} | |
} | |
return this._createEncoderBuffer(objid); | |
}; | |
function two(num) { | |
if (num < 10) return '0' + num;else return num; | |
} | |
DERNode.prototype._encodeTime = function encodeTime(time, tag) { | |
var str; | |
var date = new Date(time); | |
if (tag === 'gentime') { | |
str = [two(date.getFullYear()), two(date.getUTCMonth() + 1), two(date.getUTCDate()), two(date.getUTCHours()), two(date.getUTCMinutes()), two(date.getUTCSeconds()), 'Z'].join(''); | |
} else if (tag === 'utctime') { | |
str = [two(date.getFullYear() % 100), two(date.getUTCMonth() + 1), two(date.getUTCDate()), two(date.getUTCHours()), two(date.getUTCMinutes()), two(date.getUTCSeconds()), 'Z'].join(''); | |
} else { | |
this.reporter.error('Encoding ' + tag + ' time is not supported yet'); | |
} | |
return this._encodeStr(str, 'octstr'); | |
}; | |
DERNode.prototype._encodeNull = function encodeNull() { | |
return this._createEncoderBuffer(''); | |
}; | |
DERNode.prototype._encodeInt = function encodeInt(num, values) { | |
if (typeof num === 'string') { | |
if (!values) return this.reporter.error('String int or enum given, but no values map'); | |
if (!values.hasOwnProperty(num)) { | |
return this.reporter.error('Values map doesn\'t contain: ' + JSON.stringify(num)); | |
} | |
num = values[num]; | |
} | |
// Bignum, assume big endian | |
if (typeof num !== 'number' && !Buffer.isBuffer(num)) { | |
var numArray = num.toArray(); | |
if (!num.sign && numArray[0] & 0x80) { | |
numArray.unshift(0); | |
} | |
num = new Buffer(numArray); | |
} | |
if (Buffer.isBuffer(num)) { | |
var size = num.length; | |
if (num.length === 0) size++; | |
var out = new Buffer(size); | |
num.copy(out); | |
if (num.length === 0) out[0] = 0; | |
return this._createEncoderBuffer(out); | |
} | |
if (num < 0x80) return this._createEncoderBuffer(num); | |
if (num < 0x100) return this._createEncoderBuffer([0, num]); | |
var size = 1; | |
for (var i = num; i >= 0x100; i >>= 8) { | |
size++; | |
}var out = new Array(size); | |
for (var i = out.length - 1; i >= 0; i--) { | |
out[i] = num & 0xff; | |
num >>= 8; | |
} | |
if (out[0] & 0x80) { | |
out.unshift(0); | |
} | |
return this._createEncoderBuffer(new Buffer(out)); | |
}; | |
DERNode.prototype._encodeBool = function encodeBool(value) { | |
return this._createEncoderBuffer(value ? 0xff : 0); | |
}; | |
DERNode.prototype._use = function use(entity, obj) { | |
if (typeof entity === 'function') entity = entity(obj); | |
return entity._getEncoder('der').tree; | |
}; | |
DERNode.prototype._skipDefault = function skipDefault(dataBuffer, reporter, parent) { | |
var state = this._baseState; | |
var i; | |
if (state['default'] === null) return false; | |
var data = dataBuffer.join(); | |
if (state.defaultBuffer === undefined) state.defaultBuffer = this._encodeValue(state['default'], reporter, parent).join(); | |
if (data.length !== state.defaultBuffer.length) return false; | |
for (i = 0; i < data.length; i++) { | |
if (data[i] !== state.defaultBuffer[i]) return false; | |
}return true; | |
}; | |
// Utility methods | |
function encodeTag(tag, primitive, cls, reporter) { | |
var res; | |
if (tag === 'seqof') tag = 'seq';else if (tag === 'setof') tag = 'set'; | |
if (der.tagByName.hasOwnProperty(tag)) res = der.tagByName[tag];else if (typeof tag === 'number' && (tag | 0) === tag) res = tag;else return reporter.error('Unknown tag: ' + tag); | |
if (res >= 0x1f) return reporter.error('Multi-octet tag encoding unsupported'); | |
if (!primitive) res |= 0x20; | |
res |= der.tagClassByName[cls || 'universal'] << 6; | |
return res; | |
} | |
},{"../../asn1":7,"buffer":148,"inherits":256}],19:[function(require,module,exports){ | |
'use strict'; | |
var encoders = exports; | |
encoders.der = require('./der'); | |
encoders.pem = require('./pem'); | |
},{"./der":18,"./pem":20}],20:[function(require,module,exports){ | |
'use strict'; | |
var inherits = require('inherits'); | |
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) { | |
var buf = DEREncoder.prototype.encode.call(this, data); | |
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":18,"inherits":256}],21:[function(require,module,exports){ | |
(function (global){ | |
'use strict'; | |
// compare and isBuffer taken from https://github.com/feross/buffer/blob/680e9e5e488f22aac27599a57dc844a6315928dd/index.js | |
// original notice: | |
/*! | |
* The buffer module from node.js, for the browser. | |
* | |
* @author Feross Aboukhadijeh <feross@feross.org> <http://feross.org> | |
* @license MIT | |
*/ | |
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; | |
function compare(a, b) { | |
if (a === b) { | |
return 0; | |
} | |
var x = a.length; | |
var y = b.length; | |
for (var i = 0, len = Math.min(x, y); i < len; ++i) { | |
if (a[i] !== b[i]) { | |
x = a[i]; | |
y = b[i]; | |
break; | |
} | |
} | |
if (x < y) { | |
return -1; | |
} | |
if (y < x) { | |
return 1; | |
} | |
return 0; | |
} | |
function isBuffer(b) { | |
if (global.Buffer && typeof global.Buffer.isBuffer === 'function') { | |
return global.Buffer.isBuffer(b); | |
} | |
return !!(b != null && b._isBuffer); | |
} | |
// based on node assert, original notice: | |
// http://wiki.commonjs.org/wiki/Unit_Testing/1.0 | |
// | |
// THIS IS NOT TESTED NOR LIKELY TO WORK OUTSIDE V8! | |
// | |
// Originally from narwhal.js (http://narwhaljs.org) | |
// Copyright (c) 2009 Thomas Robinson <280north.com> | |
// | |
// 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 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 util = require('util/'); | |
var hasOwn = Object.prototype.hasOwnProperty; | |
var pSlice = Array.prototype.slice; | |
var functionsHaveNames = function () { | |
return function foo() {}.name === 'foo'; | |
}(); | |
function pToString(obj) { | |
return Object.prototype.toString.call(obj); | |
} | |
function isView(arrbuf) { | |
if (isBuffer(arrbuf)) { | |
return false; | |
} | |
if (typeof global.ArrayBuffer !== 'function') { | |
return false; | |
} | |
if (typeof ArrayBuffer.isView === 'function') { | |
return ArrayBuffer.isView(arrbuf); | |
} | |
if (!arrbuf) { | |
return false; | |
} | |
if (arrbuf instanceof DataView) { | |
return true; | |
} | |
if (arrbuf.buffer && arrbuf.buffer instanceof ArrayBuffer) { | |
return true; | |
} | |
return false; | |
} | |
// 1. The assert module provides functions that throw | |
// AssertionError's when particular conditions are not met. The | |
// assert module must conform to the following interface. | |
var assert = module.exports = ok; | |
// 2. The AssertionError is defined in assert. | |
// new assert.AssertionError({ message: message, | |
// actual: actual, | |
// expected: expected }) | |
var regex = /\s*function\s+([^\(\s]*)\s*/; | |
// based on https://github.com/ljharb/function.prototype.name/blob/adeeeec8bfcc6068b187d7d9fb3d5bb1d3a30899/implementation.js | |
function getName(func) { | |
if (!util.isFunction(func)) { | |
return; | |
} | |
if (functionsHaveNames) { | |
return func.name; | |
} | |
var str = func.toString(); | |
var match = str.match(regex); | |
return match && match[1]; | |
} | |
assert.AssertionError = function AssertionError(options) { | |
this.name = 'AssertionError'; | |
this.actual = options.actual; | |
this.expected = options.expected; | |
this.operator = options.operator; | |
if (options.message) { | |
this.message = options.message; | |
this.generatedMessage = false; | |
} else { | |
this.message = getMessage(this); | |
this.generatedMessage = true; | |
} | |
var stackStartFunction = options.stackStartFunction || fail; | |
if (Error.captureStackTrace) { | |
Error.captureStackTrace(this, stackStartFunction); | |
} else { | |
// non v8 browsers so we can have a stacktrace | |
var err = new Error(); | |
if (err.stack) { | |
var out = err.stack; | |
// try to strip useless frames | |
var fn_name = getName(stackStartFunction); | |
var idx = out.indexOf('\n' + fn_name); | |
if (idx >= 0) { | |
// once we have located the function frame | |
// we need to strip out everything before it (and its line) | |
var next_line = out.indexOf('\n', idx + 1); | |
out = out.substring(next_line + 1); | |
} | |
this.stack = out; | |
} | |
} | |
}; | |
// assert.AssertionError instanceof Error | |
util.inherits(assert.AssertionError, Error); | |
function truncate(s, n) { | |
if (typeof s === 'string') { | |
return s.length < n ? s : s.slice(0, n); | |
} else { | |
return s; | |
} | |
} | |
function inspect(something) { | |
if (functionsHaveNames || !util.isFunction(something)) { | |
return util.inspect(something); | |
} | |
var rawname = getName(something); | |
var name = rawname ? ': ' + rawname : ''; | |
return '[Function' + name + ']'; | |
} | |
function getMessage(self) { | |
return truncate(inspect(self.actual), 128) + ' ' + self.operator + ' ' + truncate(inspect(self.expected), 128); | |
} | |
// At present only the three keys mentioned above are used and | |
// understood by the spec. Implementations or sub modules can pass | |
// other keys to the AssertionError's constructor - they will be | |
// ignored. | |
// 3. All of the following functions must throw an AssertionError | |
// when a corresponding condition is not met, with a message that | |
// may be undefined if not provided. All assertion methods provide | |
// both the actual and expected values to the assertion error for | |
// display purposes. | |
function fail(actual, expected, message, operator, stackStartFunction) { | |
throw new assert.AssertionError({ | |
message: message, | |
actual: actual, | |
expected: expected, | |
operator: operator, | |
stackStartFunction: stackStartFunction | |
}); | |
} | |
// EXTENSION! allows for well behaved errors defined elsewhere. | |
assert.fail = fail; | |
// 4. Pure assertion tests whether a value is truthy, as determined | |
// by !!guard. | |
// assert.ok(guard, message_opt); | |
// This statement is equivalent to assert.equal(true, !!guard, | |
// message_opt);. To test strictly for the value true, use | |
// assert.strictEqual(true, guard, message_opt);. | |
function ok(value, message) { | |
if (!value) fail(value, true, message, '==', assert.ok); | |
} | |
assert.ok = ok; | |
// 5. The equality assertion tests shallow, coercive equality with | |
// ==. | |
// assert.equal(actual, expected, message_opt); | |
assert.equal = function equal(actual, expected, message) { | |
if (actual != expected) fail(actual, expected, message, '==', assert.equal); | |
}; | |
// 6. The non-equality assertion tests for whether two objects are not equal | |
// with != assert.notEqual(actual, expected, message_opt); | |
assert.notEqual = function notEqual(actual, expected, message) { | |
if (actual == expected) { | |
fail(actual, expected, message, '!=', assert.notEqual); | |
} | |
}; | |
// 7. The equivalence assertion tests a deep equality relation. | |
// assert.deepEqual(actual, expected, message_opt); | |
assert.deepEqual = function deepEqual(actual, expected, message) { | |
if (!_deepEqual(actual, expected, false)) { | |
fail(actual, expected, message, 'deepEqual', assert.deepEqual); | |
} | |
}; | |
assert.deepStrictEqual = function deepStrictEqual(actual, expected, message) { | |
if (!_deepEqual(actual, expected, true)) { | |
fail(actual, expected, message, 'deepStrictEqual', assert.deepStrictEqual); | |
} | |
}; | |
function _deepEqual(actual, expected, strict, memos) { | |
// 7.1. All identical values are equivalent, as determined by ===. | |
if (actual === expected) { | |
return true; | |
} else if (isBuffer(actual) && isBuffer(expected)) { | |
return compare(actual, expected) === 0; | |
// 7.2. If the expected value is a Date object, the actual value is | |
// equivalent if it is also a Date object that refers to the same time. | |
} else if (util.isDate(actual) && util.isDate(expected)) { | |
return actual.getTime() === expected.getTime(); | |
// 7.3 If the expected value is a RegExp object, the actual value is | |
// equivalent if it is also a RegExp object with the same source and | |
// properties (`global`, `multiline`, `lastIndex`, `ignoreCase`). | |
} else if (util.isRegExp(actual) && util.isRegExp(expected)) { | |
return actual.source === expected.source && actual.global === expected.global && actual.multiline === expected.multiline && actual.lastIndex === expected.lastIndex && actual.ignoreCase === expected.ignoreCase; | |
// 7.4. Other pairs that do not both pass typeof value == 'object', | |
// equivalence is determined by ==. | |
} else if ((actual === null || (typeof actual === 'undefined' ? 'undefined' : _typeof(actual)) !== 'object') && (expected === null || (typeof expected === 'undefined' ? 'undefined' : _typeof(expected)) !== 'object')) { | |
return strict ? actual === expected : actual == expected; | |
// If both values are instances of typed arrays, wrap their underlying | |
// ArrayBuffers in a Buffer each to increase performance | |
// This optimization requires the arrays to have the same type as checked by | |
// Object.prototype.toString (aka pToString). Never perform binary | |
// comparisons for Float*Arrays, though, since e.g. +0 === -0 but their | |
// bit patterns are not identical. | |
} else if (isView(actual) && isView(expected) && pToString(actual) === pToString(expected) && !(actual instanceof Float32Array || actual instanceof Float64Array)) { | |
return compare(new Uint8Array(actual.buffer), new Uint8Array(expected.buffer)) === 0; | |
// 7.5 For all other Object pairs, including Array objects, equivalence is | |
// determined by having the same number of owned properties (as verified | |
// with Object.prototype.hasOwnProperty.call), the same set of keys | |
// (although not necessarily the same order), equivalent values for every | |
// corresponding key, and an identical 'prototype' property. Note: this | |
// accounts for both named and indexed properties on Arrays. | |
} else if (isBuffer(actual) !== isBuffer(expected)) { | |
return false; | |
} else { | |
memos = memos || { actual: [], expected: [] }; | |
var actualIndex = memos.actual.indexOf(actual); | |
if (actualIndex !== -1) { | |
if (actualIndex === memos.expected.indexOf(expected)) { | |
return true; | |
} | |
} | |
memos.actual.push(actual); | |
memos.expected.push(expected); | |
return objEquiv(actual, expected, strict, memos); | |
} | |
} | |
function isArguments(object) { | |
return Object.prototype.toString.call(object) == '[object Arguments]'; | |
} | |
function objEquiv(a, b, strict, actualVisitedObjects) { | |
if (a === null || a === undefined || b === null || b === undefined) return false; | |
// if one is a primitive, the other must be same | |
if (util.isPrimitive(a) || util.isPrimitive(b)) return a === b; | |
if (strict && Object.getPrototypeOf(a) !== Object.getPrototypeOf(b)) return false; | |
var aIsArgs = isArguments(a); | |
var bIsArgs = isArguments(b); | |
if (aIsArgs && !bIsArgs || !aIsArgs && bIsArgs) return false; | |
if (aIsArgs) { | |
a = pSlice.call(a); | |
b = pSlice.call(b); | |
return _deepEqual(a, b, strict); | |
} | |
var ka = objectKeys(a); | |
var kb = objectKeys(b); | |
var key, i; | |
// having the same number of owned properties (keys incorporates | |
// hasOwnProperty) | |
if (ka.length !== kb.length) return false; | |
//the same set of keys (although not necessarily the same order), | |
ka.sort(); | |
kb.sort(); | |
//~~~cheap key test | |
for (i = ka.length - 1; i >= 0; i--) { | |
if (ka[i] !== kb[i]) return false; | |
} | |
//equivalent values for every corresponding key, and | |
//~~~possibly expensive deep test | |
for (i = ka.length - 1; i >= 0; i--) { | |
key = ka[i]; | |
if (!_deepEqual(a[key], b[key], strict, actualVisitedObjects)) return false; | |
} | |
return true; | |
} | |
// 8. The non-equivalence assertion tests for any deep inequality. | |
// assert.notDeepEqual(actual, expected, message_opt); | |
assert.notDeepEqual = function notDeepEqual(actual, expected, message) { | |
if (_deepEqual(actual, expected, false)) { | |
fail(actual, expected, message, 'notDeepEqual', assert.notDeepEqual); | |
} | |
}; | |
assert.notDeepStrictEqual = notDeepStrictEqual; | |
function notDeepStrictEqual(actual, expected, message) { | |
if (_deepEqual(actual, expected, true)) { | |
fail(actual, expected, message, 'notDeepStrictEqual', notDeepStrictEqual); | |
} | |
} | |
// 9. The strict equality assertion tests strict equality, as determined by ===. | |
// assert.strictEqual(actual, expected, message_opt); | |
assert.strictEqual = function strictEqual(actual, expected, message) { | |
if (actual !== expected) { | |
fail(actual, expected, message, '===', assert.strictEqual); | |
} | |
}; | |
// 10. The strict non-equality assertion tests for strict inequality, as | |
// determined by !==. assert.notStrictEqual(actual, expected, message_opt); | |
assert.notStrictEqual = function notStrictEqual(actual, expected, message) { | |
if (actual === expected) { | |
fail(actual, expected, message, '!==', assert.notStrictEqual); | |
} | |
}; | |
function expectedException(actual, expected) { | |
if (!actual || !expected) { | |
return false; | |
} | |
if (Object.prototype.toString.call(expected) == '[object RegExp]') { | |
return expected.test(actual); | |
} | |
try { | |
if (actual instanceof expected) { | |
return true; | |
} | |
} catch (e) { | |
// Ignore. The instanceof check doesn't work for arrow functions. | |
} | |
if (Error.isPrototypeOf(expected)) { | |
return false; | |
} | |
return expected.call({}, actual) === true; | |
} | |
function _tryBlock(block) { | |
var error; | |
try { | |
block(); | |
} catch (e) { | |
error = e; | |
} | |
return error; | |
} | |
function _throws(shouldThrow, block, expected, message) { | |
var actual; | |
if (typeof block !== 'function') { | |
throw new TypeError('"block" argument must be a function'); | |
} | |
if (typeof expected === 'string') { | |
message = expected; | |
expected = null; | |
} | |
actual = _tryBlock(block); | |
message = (expected && expected.name ? ' (' + expected.name + ').' : '.') + (message ? ' ' + message : '.'); | |
if (shouldThrow && !actual) { | |
fail(actual, expected, 'Missing expected exception' + message); | |
} | |
var userProvidedMessage = typeof message === 'string'; | |
var isUnwantedException = !shouldThrow && util.isError(actual); | |
var isUnexpectedException = !shouldThrow && actual && !expected; | |
if (isUnwantedException && userProvidedMessage && expectedException(actual, expected) || isUnexpectedException) { | |
fail(actual, expected, 'Got unwanted exception' + message); | |
} | |
if (shouldThrow && actual && expected && !expectedException(actual, expected) || !shouldThrow && actual) { | |
throw actual; | |
} | |
} | |
// 11. Expected to throw an error: | |
// assert.throws(block, Error_opt, message_opt); | |
assert.throws = function (block, /*optional*/error, /*optional*/message) { | |
_throws(true, block, error, message); | |
}; | |
// EXTENSION! This is annoying to write outside this module. | |
assert.doesNotThrow = function (block, /*optional*/error, /*optional*/message) { | |
_throws(false, block, error, message); | |
}; | |
assert.ifError = function (err) { | |
if (err) throw err; | |
}; | |
var objectKeys = Object.keys || function (obj) { | |
var keys = []; | |
for (var key in obj) { | |
if (hasOwn.call(obj, key)) keys.push(key); | |
} | |
return keys; | |
}; | |
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) | |
},{"util/":356}],22:[function(require,module,exports){ | |
'use strict'; | |
// base-x encoding | |
// Forked from https://github.com/cryptocoinjs/bs58 | |
// Originally written by Mike Hearn for BitcoinJ | |
// Copyright (c) 2011 Google Inc | |
// Ported to JavaScript by Stefan Thomas | |
// Merged Buffer refactorings from base58-native by Stephen Pair | |
// Copyright (c) 2013 BitPay Inc | |
var Buffer = require('safe-buffer').Buffer; | |
module.exports = function base(ALPHABET) { | |
var ALPHABET_MAP = {}; | |
var BASE = ALPHABET.length; | |
var LEADER = ALPHABET.charAt(0); | |
// pre-compute lookup table | |
for (var z = 0; z < ALPHABET.length; z++) { | |
var x = ALPHABET.charAt(z); | |
if (ALPHABET_MAP[x] !== undefined) throw new TypeError(x + ' is ambiguous'); | |
ALPHABET_MAP[x] = z; | |
} | |
function encode(source) { | |
if (source.length === 0) return ''; | |
var digits = [0]; | |
for (var i = 0; i < source.length; ++i) { | |
for (var j = 0, carry = source[i]; j < digits.length; ++j) { | |
carry += digits[j] << 8; | |
digits[j] = carry % BASE; | |
carry = carry / BASE | 0; | |
} | |
while (carry > 0) { | |
digits.push(carry % BASE); | |
carry = carry / BASE | 0; | |
} | |
} | |
var string = ''; | |
// deal with leading zeros | |
for (var k = 0; source[k] === 0 && k < source.length - 1; ++k) { | |
string += LEADER; | |
} // convert digits to a string | |
for (var q = digits.length - 1; q >= 0; --q) { | |
string += ALPHABET[digits[q]]; | |
}return string; | |
} | |
function decodeUnsafe(string) { | |
if (typeof string !== 'string') throw new TypeError('Expected String'); | |
if (string.length === 0) return Buffer.allocUnsafe(0); | |
var bytes = [0]; | |
for (var i = 0; i < string.length; i++) { | |
var value = ALPHABET_MAP[string[i]]; | |
if (value === undefined) return; | |
for (var j = 0, carry = value; j < bytes.length; ++j) { | |
carry += bytes[j] * BASE; | |
bytes[j] = carry & 0xff; | |
carry >>= 8; | |
} | |
while (carry > 0) { | |
bytes.push(carry & 0xff); | |
carry >>= 8; | |
} | |
} | |
// deal with leading zeros | |
for (var k = 0; string[k] === LEADER && k < string.length - 1; ++k) { | |
bytes.push(0); | |
} | |
return Buffer.from(bytes.reverse()); | |
} | |
function decode(string) { | |
var buffer = decodeUnsafe(string); | |
if (buffer) return buffer; | |
throw new Error('Non-base' + BASE + ' character'); | |
} | |
return { | |
encode: encode, | |
decodeUnsafe: decodeUnsafe, | |
decode: decode | |
}; | |
}; | |
},{"safe-buffer":314}],23:[function(require,module,exports){ | |
'use strict'; | |
exports.byteLength = byteLength; | |
exports.toByteArray = toByteArray; | |
exports.fromByteArray = fromByteArray; | |
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; | |
} | |
revLookup['-'.charCodeAt(0)] = 62; | |
revLookup['_'.charCodeAt(0)] = 63; | |
function placeHoldersCount(b64) { | |
var len = b64.length; | |
if (len % 4 > 0) { | |
throw new Error('Invalid string. Length must be a multiple of 4'); | |
} | |
// the number of equal signs (place holders) | |
// if there are two placeholders, than the two characters before it | |
// represent one byte | |
// if there is only one, then the three characters before it represent 2 bytes | |
// this is just a cheap hack to not do indexOf twice | |
return b64[len - 2] === '=' ? 2 : b64[len - 1] === '=' ? 1 : 0; | |
} | |
function byteLength(b64) { | |
// base64 is 4/3 + up to two characters of the original data | |
return b64.length * 3 / 4 - placeHoldersCount(b64); | |
} | |
function toByteArray(b64) { | |
var i, l, tmp, placeHolders, arr; | |
var len = b64.length; | |
placeHolders = placeHoldersCount(b64); | |
arr = new Arr(len * 3 / 4 - placeHolders); | |
// if there are placeholders, only get up to the last complete 4 chars | |
l = placeHolders > 0 ? len - 4 : len; | |
var L = 0; | |
for (i = 0; i < l; 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[L++] = tmp >> 16 & 0xFF; | |
arr[L++] = tmp >> 8 & 0xFF; | |
arr[L++] = tmp & 0xFF; | |
} | |
if (placeHolders === 2) { | |
tmp = revLookup[b64.charCodeAt(i)] << 2 | revLookup[b64.charCodeAt(i + 1)] >> 4; | |
arr[L++] = tmp & 0xFF; | |
} else if (placeHolders === 1) { | |
tmp = revLookup[b64.charCodeAt(i)] << 10 | revLookup[b64.charCodeAt(i + 1)] << 4 | revLookup[b64.charCodeAt(i + 2)] >> 2; | |
arr[L++] = tmp >> 8 & 0xFF; | |
arr[L++] = tmp & 0xFF; | |
} | |
return arr; | |
} | |
function tripletToBase64(num) { | |
return lookup[num >> 18 & 0x3F] + lookup[num >> 12 & 0x3F] + lookup[num >> 6 & 0x3F] + lookup[num & 0x3F]; | |
} | |
function encodeChunk(uint8, start, end) { | |
var tmp; | |
var output = []; | |
for (var i = start; i < end; i += 3) { | |
tmp = (uint8[i] << 16) + (uint8[i + 1] << 8) + uint8[i + 2]; | |
output.push(tripletToBase64(tmp)); | |
} | |
return output.join(''); | |
} | |
function fromByteArray(uint8) { | |
var tmp; | |
var len = uint8.length; | |
var extraBytes = len % 3; // if we have 1 byte left, pad 2 bytes | |
var output = ''; | |
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]; | |
output += lookup[tmp >> 2]; | |
output += lookup[tmp << 4 & 0x3F]; | |
output += '=='; | |
} else if (extraBytes === 2) { | |
tmp = (uint8[len - 2] << 8) + uint8[len - 1]; | |
output += lookup[tmp >> 10]; | |
output += lookup[tmp >> 4 & 0x3F]; | |
output += lookup[tmp << 2 & 0x3F]; | |
output += '='; | |
} | |
parts.push(output); | |
return parts.join(''); | |
} | |
},{}],24:[function(require,module,exports){ | |
'use strict'; | |
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; | |
/*! bignumber.js v2.0.7 https://github.com/MikeMcl/bignumber.js/LICENCE */ | |
;(function (global) { | |
'use strict'; | |
/* | |
bignumber.js v2.0.7 | |
A JavaScript library for arbitrary-precision arithmetic. | |
https://github.com/MikeMcl/bignumber.js | |
Copyright (c) 2015 Michael Mclaughlin <M8ch88l@gmail.com> | |
MIT Expat Licence | |
*/ | |
var BigNumber, | |
crypto, | |
parseNumeric, | |
isNumeric = /^-?(\d+(\.\d*)?|\.\d+)(e[+-]?\d+)?$/i, | |
mathceil = Math.ceil, | |
mathfloor = Math.floor, | |
notBool = ' not a boolean or binary digit', | |
roundingMode = 'rounding mode', | |
tooManyDigits = 'number type has more than 15 significant digits', | |
ALPHABET = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_', | |
BASE = 1e14, | |
LOG_BASE = 14, | |
MAX_SAFE_INTEGER = 0x1fffffffffffff, | |
// 2^53 - 1 | |
// MAX_INT32 = 0x7fffffff, // 2^31 - 1 | |
POWS_TEN = [1, 10, 100, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11, 1e12, 1e13], | |
SQRT_BASE = 1e7, | |
/* | |
* The limit on the value of DECIMAL_PLACES, TO_EXP_NEG, TO_EXP_POS, MIN_EXP, MAX_EXP, and | |
* the arguments to toExponential, toFixed, toFormat, and toPrecision, beyond which an | |
* exception is thrown (if ERRORS is true). | |
*/ | |
MAX = 1E9; // 0 to MAX_INT32 | |
/* | |
* Create and return a BigNumber constructor. | |
*/ | |
function another(configObj) { | |
var div, | |
// id tracks the caller function, so its name can be included in error messages. | |
id = 0, | |
P = BigNumber.prototype, | |
ONE = new BigNumber(1), | |
/********************************* EDITABLE DEFAULTS **********************************/ | |
/* | |
* The default values below must be integers within the inclusive ranges stated. | |
* The values can also be changed at run-time using BigNumber.config. | |
*/ | |
// The maximum number of decimal places for operations involving division. | |
DECIMAL_PLACES = 20, | |
// 0 to MAX | |
/* | |
* The rounding mode used when rounding to the above decimal places, and when using | |
* toExponential, toFixed, toFormat and toPrecision, and round (default value). | |
* UP 0 Away from zero. | |
* DOWN 1 Towards zero. | |
* CEIL 2 Towards +Infinity. | |
* FLOOR 3 Towards -Infinity. | |
* HALF_UP 4 Towards nearest neighbour. If equidistant, up. | |
* HALF_DOWN 5 Towards nearest neighbour. If equidistant, down. | |
* HALF_EVEN 6 Towards nearest neighbour. If equidistant, towards even neighbour. | |
* HALF_CEIL 7 Towards nearest neighbour. If equidistant, towards +Infinity. | |
* HALF_FLOOR 8 Towards nearest neighbour. If equidistant, towards -Infinity. | |
*/ | |
ROUNDING_MODE = 4, | |
// 0 to 8 | |
// EXPONENTIAL_AT : [TO_EXP_NEG , TO_EXP_POS] | |
// The exponent value at and beneath which toString returns exponential notation. | |
// Number type: -7 | |
TO_EXP_NEG = -7, | |
// 0 to -MAX | |
// The exponent value at and above which toString returns exponential notation. | |
// Number type: 21 | |
TO_EXP_POS = 21, | |
// 0 to MAX | |
// RANGE : [MIN_EXP, MAX_EXP] | |
// The minimum exponent value, beneath which underflow to zero occurs. | |
// Number type: -324 (5e-324) | |
MIN_EXP = -1e7, | |
// -1 to -MAX | |
// The maximum exponent value, above which overflow to Infinity occurs. | |
// Number type: 308 (1.7976931348623157e+308) | |
// For MAX_EXP > 1e7, e.g. new BigNumber('1e100000000').plus(1) may be slow. | |
MAX_EXP = 1e7, | |
// 1 to MAX | |
// Whether BigNumber Errors are ever thrown. | |
ERRORS = true, | |
// true or false | |
// Change to intValidatorNoErrors if ERRORS is false. | |
isValidInt = intValidatorWithErrors, | |
// intValidatorWithErrors/intValidatorNoErrors | |
// Whether to use cryptographically-secure random number generation, if available. | |
CRYPTO = false, | |
// true or false | |
/* | |
* The modulo mode used when calculating the modulus: a mod n. | |
* The quotient (q = a / n) is calculated according to the corresponding rounding mode. | |
* The remainder (r) is calculated as: r = a - n * q. | |
* | |
* UP 0 The remainder is positive if the dividend is negative, else is negative. | |
* DOWN 1 The remainder has the same sign as the dividend. | |
* This modulo mode is commonly known as 'truncated division' and is | |
* equivalent to (a % n) in JavaScript. | |
* FLOOR 3 The remainder has the same sign as the divisor (Python %). | |
* HALF_EVEN 6 This modulo mode implements the IEEE 754 remainder function. | |
* EUCLID 9 Euclidian division. q = sign(n) * floor(a / abs(n)). | |
* The remainder is always positive. | |
* | |
* The truncated division, floored division, Euclidian division and IEEE 754 remainder | |
* modes are commonly used for the modulus operation. | |
* Although the other rounding modes can also be used, they may not give useful results. | |
*/ | |
MODULO_MODE = 1, | |
// 0 to 9 | |
// The maximum number of significant digits of the result of the toPower operation. | |
// If POW_PRECISION is 0, there will be unlimited significant digits. | |
POW_PRECISION = 100, | |
// 0 to MAX | |
// The format specification used by the BigNumber.prototype.toFormat method. | |
FORMAT = { | |
decimalSeparator: '.', | |
groupSeparator: ',', | |
groupSize: 3, | |
secondaryGroupSize: 0, | |
fractionGroupSeparator: '\xA0', // non-breaking space | |
fractionGroupSize: 0 | |
}; | |
/******************************************************************************************/ | |
// CONSTRUCTOR | |
/* | |
* The BigNumber constructor and exported function. | |
* Create and return a new instance of a BigNumber object. | |
* | |
* n {number|string|BigNumber} A numeric value. | |
* [b] {number} The base of n. Integer, 2 to 64 inclusive. | |
*/ | |
function BigNumber(n, b) { | |
var c, | |
e, | |
i, | |
num, | |
len, | |
str, | |
x = this; | |
// Enable constructor usage without new. | |
if (!(x instanceof BigNumber)) { | |
// 'BigNumber() constructor call without new: {n}' | |
if (ERRORS) raise(26, 'constructor call without new', n); | |
return new BigNumber(n, b); | |
} | |
// 'new BigNumber() base not an integer: {b}' | |
// 'new BigNumber() base out of range: {b}' | |
if (b == null || !isValidInt(b, 2, 64, id, 'base')) { | |
// Duplicate. | |
if (n instanceof BigNumber) { | |
x.s = n.s; | |
x.e = n.e; | |
x.c = (n = n.c) ? n.slice() : n; | |
id = 0; | |
return; | |
} | |
if ((num = typeof n == 'number') && n * 0 == 0) { | |
x.s = 1 / n < 0 ? (n = -n, -1) : 1; | |
// Fast path for integers. | |
if (n === ~~n) { | |
for (e = 0, i = n; i >= 10; i /= 10, e++) {} | |
x.e = e; | |
x.c = [n]; | |
id = 0; | |
return; | |
} | |
str = n + ''; | |
} else { | |
if (!isNumeric.test(str = n + '')) return parseNumeric(x, str, num); | |
x.s = str.charCodeAt(0) === 45 ? (str = str.slice(1), -1) : 1; | |
} | |
} else { | |
b = b | 0; | |
str = n + ''; | |
// Ensure return value is rounded to DECIMAL_PLACES as with other bases. | |
// Allow exponential notation to be used with base 10 argument. | |
if (b == 10) { | |
x = new BigNumber(n instanceof BigNumber ? n : str); | |
return round(x, DECIMAL_PLACES + x.e + 1, ROUNDING_MODE); | |
} | |
// Avoid potential interpretation of Infinity and NaN as base 44+ values. | |
// Any number in exponential form will fail due to the [Ee][+-]. | |
if ((num = typeof n == 'number') && n * 0 != 0 || !new RegExp('^-?' + (c = '[' + ALPHABET.slice(0, b) + ']+') + '(?:\\.' + c + ')?$', b < 37 ? 'i' : '').test(str)) { | |
return parseNumeric(x, str, num, b); | |
} | |
if (num) { | |
x.s = 1 / n < 0 ? (str = str.slice(1), -1) : 1; | |
if (ERRORS && str.replace(/^0\.0*|\./, '').length > 15) { | |
// 'new BigNumber() number type has more than 15 significant digits: {n}' | |
raise(id, tooManyDigits, n); | |
} | |
// Prevent later check for length on converted number. | |
num = false; | |
} else { | |
x.s = str.charCodeAt(0) === 45 ? (str = str.slice(1), -1) : 1; | |
} | |
str = convertBase(str, 10, b, x.s); | |
} | |
// Decimal point? | |
if ((e = str.indexOf('.')) > -1) str = str.replace('.', ''); | |
// Exponential form? | |
if ((i = str.search(/e/i)) > 0) { | |
// Determine exponent. | |
if (e < 0) e = i; | |
e += +str.slice(i + 1); | |
str = str.substring(0, i); | |
} else if (e < 0) { | |
// Integer. | |
e = str.length; | |
} | |
// Determine leading zeros. | |
for (i = 0; str.charCodeAt(i) === 48; i++) {} | |
// Determine trailing zeros. | |
for (len = str.length; str.charCodeAt(--len) === 48;) {} | |
str = str.slice(i, len + 1); | |
if (str) { | |
len = str.length; | |
// Disallow numbers with over 15 significant digits if number type. | |
// 'new BigNumber() number type has more than 15 significant digits: {n}' | |
if (num && ERRORS && len > 15) raise(id, tooManyDigits, x.s * n); | |
e = e - i - 1; | |
// Overflow? | |
if (e > MAX_EXP) { | |
// Infinity. | |
x.c = x.e = null; | |
// Underflow? | |
} else if (e < MIN_EXP) { | |
// Zero. | |
x.c = [x.e = 0]; | |
} else { | |
x.e = e; | |
x.c = []; | |
// Transform base | |
// e is the base 10 exponent. | |
// i is where to slice str to get the first element of the coefficient array. | |
i = (e + 1) % LOG_BASE; | |
if (e < 0) i += LOG_BASE; | |
if (i < len) { | |
if (i) x.c.push(+str.slice(0, i)); | |
for (len -= LOG_BASE; i < len;) { | |
x.c.push(+str.slice(i, i += LOG_BASE)); | |
} | |
str = str.slice(i); | |
i = LOG_BASE - str.length; | |
} else { | |
i -= len; | |
} | |
for (; i--; str += '0') {} | |
x.c.push(+str); | |
} | |
} else { | |
// Zero. | |
x.c = [x.e = 0]; | |
} | |
id = 0; | |
} | |
// CONSTRUCTOR PROPERTIES | |
BigNumber.another = another; | |
BigNumber.ROUND_UP = 0; | |
BigNumber.ROUND_DOWN = 1; | |
BigNumber.ROUND_CEIL = 2; | |
BigNumber.ROUND_FLOOR = 3; | |
BigNumber.ROUND_HALF_UP = 4; | |
BigNumber.ROUND_HALF_DOWN = 5; | |
BigNumber.ROUND_HALF_EVEN = 6; | |
BigNumber.ROUND_HALF_CEIL = 7; | |
BigNumber.ROUND_HALF_FLOOR = 8; | |
BigNumber.EUCLID = 9; | |
/* | |
* Configure infrequently-changing library-wide settings. | |
* | |
* Accept an object or an argument list, with one or many of the following properties or | |
* parameters respectively: | |
* | |
* DECIMAL_PLACES {number} Integer, 0 to MAX inclusive | |
* ROUNDING_MODE {number} Integer, 0 to 8 inclusive | |
* EXPONENTIAL_AT {number|number[]} Integer, -MAX to MAX inclusive or | |
* [integer -MAX to 0 incl., 0 to MAX incl.] | |
* RANGE {number|number[]} Non-zero integer, -MAX to MAX inclusive or | |
* [integer -MAX to -1 incl., integer 1 to MAX incl.] | |
* ERRORS {boolean|number} true, false, 1 or 0 | |
* CRYPTO {boolean|number} true, false, 1 or 0 | |
* MODULO_MODE {number} 0 to 9 inclusive | |
* POW_PRECISION {number} 0 to MAX inclusive | |
* FORMAT {object} See BigNumber.prototype.toFormat | |
* decimalSeparator {string} | |
* groupSeparator {string} | |
* groupSize {number} | |
* secondaryGroupSize {number} | |
* fractionGroupSeparator {string} | |
* fractionGroupSize {number} | |
* | |
* (The values assigned to the above FORMAT object properties are not checked for validity.) | |
* | |
* E.g. | |
* BigNumber.config(20, 4) is equivalent to | |
* BigNumber.config({ DECIMAL_PLACES : 20, ROUNDING_MODE : 4 }) | |
* | |
* Ignore properties/parameters set to null or undefined. | |
* Return an object with the properties current values. | |
*/ | |
BigNumber.config = function () { | |
var v, | |
p, | |
i = 0, | |
r = {}, | |
a = arguments, | |
o = a[0], | |
has = o && (typeof o === 'undefined' ? 'undefined' : _typeof(o)) == 'object' ? function () { | |
if (o.hasOwnProperty(p)) return (v = o[p]) != null; | |
} : function () { | |
if (a.length > i) return (v = a[i++]) != null; | |
}; | |
// DECIMAL_PLACES {number} Integer, 0 to MAX inclusive. | |
// 'config() DECIMAL_PLACES not an integer: {v}' | |
// 'config() DECIMAL_PLACES out of range: {v}' | |
if (has(p = 'DECIMAL_PLACES') && isValidInt(v, 0, MAX, 2, p)) { | |
DECIMAL_PLACES = v | 0; | |
} | |
r[p] = DECIMAL_PLACES; | |
// ROUNDING_MODE {number} Integer, 0 to 8 inclusive. | |
// 'config() ROUNDING_MODE not an integer: {v}' | |
// 'config() ROUNDING_MODE out of range: {v}' | |
if (has(p = 'ROUNDING_MODE') && isValidInt(v, 0, 8, 2, p)) { | |
ROUNDING_MODE = v | 0; | |
} | |
r[p] = ROUNDING_MODE; | |
// EXPONENTIAL_AT {number|number[]} | |
// Integer, -MAX to MAX inclusive or [integer -MAX to 0 inclusive, 0 to MAX inclusive]. | |
// 'config() EXPONENTIAL_AT not an integer: {v}' | |
// 'config() EXPONENTIAL_AT out of range: {v}' | |
if (has(p = 'EXPONENTIAL_AT')) { | |
if (isArray(v)) { | |
if (isValidInt(v[0], -MAX, 0, 2, p) && isValidInt(v[1], 0, MAX, 2, p)) { | |
TO_EXP_NEG = v[0] | 0; | |
TO_EXP_POS = v[1] | 0; | |
} | |
} else if (isValidInt(v, -MAX, MAX, 2, p)) { | |
TO_EXP_NEG = -(TO_EXP_POS = (v < 0 ? -v : v) | 0); | |
} | |
} | |
r[p] = [TO_EXP_NEG, TO_EXP_POS]; | |
// RANGE {number|number[]} Non-zero integer, -MAX to MAX inclusive or | |
// [integer -MAX to -1 inclusive, integer 1 to MAX inclusive]. | |
// 'config() RANGE not an integer: {v}' | |
// 'config() RANGE cannot be zero: {v}' | |
// 'config() RANGE out of range: {v}' | |
if (has(p = 'RANGE')) { | |
if (isArray(v)) { | |
if (isValidInt(v[0], -MAX, -1, 2, p) && isValidInt(v[1], 1, MAX, 2, p)) { | |
MIN_EXP = v[0] | 0; | |
MAX_EXP = v[1] | 0; | |
} | |
} else if (isValidInt(v, -MAX, MAX, 2, p)) { | |
if (v | 0) MIN_EXP = -(MAX_EXP = (v < 0 ? -v : v) | 0);else if (ERRORS) raise(2, p + ' cannot be zero', v); | |
} | |
} | |
r[p] = [MIN_EXP, MAX_EXP]; | |
// ERRORS {boolean|number} true, false, 1 or 0. | |
// 'config() ERRORS not a boolean or binary digit: {v}' | |
if (has(p = 'ERRORS')) { | |
if (v === !!v || v === 1 || v === 0) { | |
id = 0; | |
isValidInt = (ERRORS = !!v) ? intValidatorWithErrors : intValidatorNoErrors; | |
} else if (ERRORS) { | |
raise(2, p + notBool, v); | |
} | |
} | |
r[p] = ERRORS; | |
// CRYPTO {boolean|number} true, false, 1 or 0. | |
// 'config() CRYPTO not a boolean or binary digit: {v}' | |
// 'config() crypto unavailable: {crypto}' | |
if (has(p = 'CRYPTO')) { | |
if (v === !!v || v === 1 || v === 0) { | |
CRYPTO = !!(v && crypto && (typeof crypto === 'undefined' ? 'undefined' : _typeof(crypto)) == 'object'); | |
if (v && !CRYPTO && ERRORS) raise(2, 'crypto unavailable', crypto); | |
} else if (ERRORS) { | |
raise(2, p + notBool, v); | |
} | |
} | |
r[p] = CRYPTO; | |
// MODULO_MODE {number} Integer, 0 to 9 inclusive. | |
// 'config() MODULO_MODE not an integer: {v}' | |
// 'config() MODULO_MODE out of range: {v}' | |
if (has(p = 'MODULO_MODE') && isValidInt(v, 0, 9, 2, p)) { | |
MODULO_MODE = v | 0; | |
} | |
r[p] = MODULO_MODE; | |
// POW_PRECISION {number} Integer, 0 to MAX inclusive. | |
// 'config() POW_PRECISION not an integer: {v}' | |
// 'config() POW_PRECISION out of range: {v}' | |
if (has(p = 'POW_PRECISION') && isValidInt(v, 0, MAX, 2, p)) { | |
POW_PRECISION = v | 0; | |
} | |
r[p] = POW_PRECISION; | |
// FORMAT {object} | |
// 'config() FORMAT not an object: {v}' | |
if (has(p = 'FORMAT')) { | |
if ((typeof v === 'undefined' ? 'undefined' : _typeof(v)) == 'object') { | |
FORMAT = v; | |
} else if (ERRORS) { | |
raise(2, p + ' not an object', v); | |
} | |
} | |
r[p] = FORMAT; | |
return r; | |
}; | |
/* | |
* Return a new BigNumber whose value is the maximum of the arguments. | |
* | |
* arguments {number|string|BigNumber} | |
*/ | |
BigNumber.max = function () { | |
return maxOrMin(arguments, P.lt); | |
}; | |
/* | |
* Return a new BigNumber whose value is the minimum of the arguments. | |
* | |
* arguments {number|string|BigNumber} | |
*/ | |
BigNumber.min = function () { | |
return maxOrMin(arguments, P.gt); | |
}; | |
/* | |
* Return a new BigNumber with a random value equal to or greater than 0 and less than 1, | |
* and with dp, or DECIMAL_PLACES if dp is omitted, decimal places (or less if trailing | |
* zeros are produced). | |
* | |
* [dp] {number} Decimal places. Integer, 0 to MAX inclusive. | |
* | |
* 'random() decimal places not an integer: {dp}' | |
* 'random() decimal places out of range: {dp}' | |
* 'random() crypto unavailable: {crypto}' | |
*/ | |
BigNumber.random = function () { | |
var pow2_53 = 0x20000000000000; | |
// Return a 53 bit integer n, where 0 <= n < 9007199254740992. | |
// Check if Math.random() produces more than 32 bits of randomness. | |
// If it does, assume at least 53 bits are produced, otherwise assume at least 30 bits. | |
// 0x40000000 is 2^30, 0x800000 is 2^23, 0x1fffff is 2^21 - 1. | |
var random53bitInt = Math.random() * pow2_53 & 0x1fffff ? function () { | |
return mathfloor(Math.random() * pow2_53); | |
} : function () { | |
return (Math.random() * 0x40000000 | 0) * 0x800000 + (Math.random() * 0x800000 | 0); | |
}; | |
return function (dp) { | |
var a, | |
b, | |
e, | |
k, | |
v, | |
i = 0, | |
c = [], | |
rand = new BigNumber(ONE); | |
dp = dp == null || !isValidInt(dp, 0, MAX, 14) ? DECIMAL_PLACES : dp | 0; | |
k = mathceil(dp / LOG_BASE); | |
if (CRYPTO) { | |
// Browsers supporting crypto.getRandomValues. | |
if (crypto && crypto.getRandomValues) { | |
a = crypto.getRandomValues(new Uint32Array(k *= 2)); | |
for (; i < k;) { | |
// 53 bits: | |
// ((Math.pow(2, 32) - 1) * Math.pow(2, 21)).toString(2) | |
// 11111 11111111 11111111 11111111 11100000 00000000 00000000 | |
// ((Math.pow(2, 32) - 1) >>> 11).toString(2) | |
// 11111 11111111 11111111 | |
// 0x20000 is 2^21. | |
v = a[i] * 0x20000 + (a[i + 1] >>> 11); | |
// Rejection sampling: | |
// 0 <= v < 9007199254740992 | |
// Probability that v >= 9e15, is | |
// 7199254740992 / 9007199254740992 ~= 0.0008, i.e. 1 in 1251 | |
if (v >= 9e15) { | |
b = crypto.getRandomValues(new Uint32Array(2)); | |
a[i] = b[0]; | |
a[i + 1] = b[1]; | |
} else { | |
// 0 <= v <= 8999999999999999 | |
// 0 <= (v % 1e14) <= 99999999999999 | |
c.push(v % 1e14); | |
i += 2; | |
} | |
} | |
i = k / 2; | |
// Node.js supporting crypto.randomBytes. | |
} else if (crypto && crypto.randomBytes) { | |
// buffer | |
a = crypto.randomBytes(k *= 7); | |
for (; i < k;) { | |
// 0x1000000000000 is 2^48, 0x10000000000 is 2^40 | |
// 0x100000000 is 2^32, 0x1000000 is 2^24 | |
// 11111 11111111 11111111 11111111 11111111 11111111 11111111 | |
// 0 <= v < 9007199254740992 | |
v = (a[i] & 31) * 0x1000000000000 + a[i + 1] * 0x10000000000 + a[i + 2] * 0x100000000 + a[i + 3] * 0x1000000 + (a[i + 4] << 16) + (a[i + 5] << 8) + a[i + 6]; | |
if (v >= 9e15) { | |
crypto.randomBytes(7).copy(a, i); | |
} else { | |
// 0 <= (v % 1e14) <= 99999999999999 | |
c.push(v % 1e14); | |
i += 7; | |
} | |
} | |
i = k / 7; | |
} else if (ERRORS) { | |
raise(14, 'crypto unavailable', crypto); | |
} | |
} | |
// Use Math.random: CRYPTO is false or crypto is unavailable and ERRORS is false. | |
if (!i) { | |
for (; i < k;) { | |
v = random53bitInt(); | |
if (v < 9e15) c[i++] = v % 1e14; | |
} | |
} | |
k = c[--i]; | |
dp %= LOG_BASE; | |
// Convert trailing digits to zeros according to dp. | |
if (k && dp) { | |
v = POWS_TEN[LOG_BASE - dp]; | |
c[i] = mathfloor(k / v) * v; | |
} | |
// Remove trailing elements which are zero. | |
for (; c[i] === 0; c.pop(), i--) {} | |
// Zero? | |
if (i < 0) { | |
c = [e = 0]; | |
} else { | |
// Remove leading elements which are zero and adjust exponent accordingly. | |
for (e = -1; c[0] === 0; c.shift(), e -= LOG_BASE) {} | |
// Count the digits of the first element of c to determine leading zeros, and... | |
for (i = 1, v = c[0]; v >= 10; v /= 10, i++) {} | |
// adjust the exponent accordingly. | |
if (i < LOG_BASE) e -= LOG_BASE - i; | |
} | |
rand.e = e; | |
rand.c = c; | |
return rand; | |
}; | |
}(); | |
// PRIVATE FUNCTIONS | |
// Convert a numeric string of baseIn to a numeric string of baseOut. | |
function convertBase(str, baseOut, baseIn, sign) { | |
var d, | |
e, | |
k, | |
r, | |
x, | |
xc, | |
y, | |
i = str.indexOf('.'), | |
dp = DECIMAL_PLACES, | |
rm = ROUNDING_MODE; | |
if (baseIn < 37) str = str.toLowerCase(); | |
// Non-integer. | |
if (i >= 0) { | |
k = POW_PRECISION; | |
// Unlimited precision. | |
POW_PRECISION = 0; | |
str = str.replace('.', ''); | |
y = new BigNumber(baseIn); | |
x = y.pow(str.length - i); | |
POW_PRECISION = k; | |
// Convert str as if an integer, then restore the fraction part by dividing the | |
// result by its base raised to a power. | |
y.c = toBaseOut(toFixedPoint(coeffToString(x.c), x.e), 10, baseOut); | |
y.e = y.c.length; | |
} | |
// Convert the number as integer. | |
xc = toBaseOut(str, baseIn, baseOut); | |
e = k = xc.length; | |
// Remove trailing zeros. | |
for (; xc[--k] == 0; xc.pop()) {} | |
if (!xc[0]) return '0'; | |
if (i < 0) { | |
--e; | |
} else { | |
x.c = xc; | |
x.e = e; | |
// sign is needed for correct rounding. | |
x.s = sign; | |
x = div(x, y, dp, rm, baseOut); | |
xc = x.c; | |
r = x.r; | |
e = x.e; | |
} | |
d = e + dp + 1; | |
// The rounding digit, i.e. the digit to the right of the digit that may be rounded up. | |
i = xc[d]; | |
k = baseOut / 2; | |
r = r || d < 0 || xc[d + 1] != null; | |
r = rm < 4 ? (i != null || r) && (rm == 0 || rm == (x.s < 0 ? 3 : 2)) : i > k || i == k && (rm == 4 || r || rm == 6 && xc[d - 1] & 1 || rm == (x.s < 0 ? 8 : 7)); | |
if (d < 1 || !xc[0]) { | |
// 1^-dp or 0. | |
str = r ? toFixedPoint('1', -dp) : '0'; | |
} else { | |
xc.length = d; | |
if (r) { | |
// Rounding up may mean the previous digit has to be rounded up and so on. | |
for (--baseOut; ++xc[--d] > baseOut;) { | |
xc[d] = 0; | |
if (!d) { | |
++e; | |
xc.unshift(1); | |
} | |
} | |
} | |
// Determine trailing zeros. | |
for (k = xc.length; !xc[--k];) {} | |
// E.g. [4, 11, 15] becomes 4bf. | |
for (i = 0, str = ''; i <= k; str += ALPHABET.charAt(xc[i++])) {} | |
str = toFixedPoint(str, e); | |
} | |
// The caller will add the sign. | |
return str; | |
} | |
// Perform division in the specified base. Called by div and convertBase. | |
div = function () { | |
// Assume non-zero x and k. | |
function multiply(x, k, base) { | |
var m, | |
temp, | |
xlo, | |
xhi, | |
carry = 0, | |
i = x.length, | |
klo = k % SQRT_BASE, | |
khi = k / SQRT_BASE | 0; | |
for (x = x.slice(); i--;) { | |
xlo = x[i] % SQRT_BASE; | |
xhi = x[i] / SQRT_BASE | 0; | |
m = khi * xlo + xhi * klo; | |
temp = klo * xlo + m % SQRT_BASE * SQRT_BASE + carry; | |
carry = (temp / base | 0) + (m / SQRT_BASE | 0) + khi * xhi; | |
x[i] = temp % base; | |
} | |
if (carry) x.unshift(carry); | |
return x; | |
} | |
function compare(a, b, aL, bL) { | |
var i, cmp; | |
if (aL != bL) { | |
cmp = aL > bL ? 1 : -1; | |
} else { | |
for (i = cmp = 0; i < aL; i++) { | |
if (a[i] != b[i]) { | |
cmp = a[i] > b[i] ? 1 : -1; | |
break; | |
} | |
} | |
} | |
return cmp; | |
} | |
function subtract(a, b, aL, base) { | |
var i = 0; | |
// Subtract b from a. | |
for (; aL--;) { | |
a[aL] -= i; | |
i = a[aL] < b[aL] ? 1 : 0; | |
a[aL] = i * base + a[aL] - b[aL]; | |
} | |
// Remove leading zeros. | |
for (; !a[0] && a.length > 1; a.shift()) {} | |
} | |
// x: dividend, y: divisor. | |
return function (x, y, dp, rm, base) { | |
var cmp, | |
e, | |
i, | |
more, | |
n, | |
prod, | |
prodL, | |
q, | |
qc, | |
rem, | |
remL, | |
rem0, | |
xi, | |
xL, | |
yc0, | |
yL, | |
yz, | |
s = x.s == y.s ? 1 : -1, | |
xc = x.c, | |
yc = y.c; | |
// Either NaN, Infinity or 0? | |
if (!xc || !xc[0] || !yc || !yc[0]) { | |
return new BigNumber( | |
// Return NaN if either NaN, or both Infinity or 0. | |
!x.s || !y.s || (xc ? yc && xc[0] == yc[0] : !yc) ? NaN : | |
// Return ±0 if x is ±0 or y is ±Infinity, or return ±Infinity as y is ±0. | |
xc && xc[0] == 0 || !yc ? s * 0 : s / 0); | |
} | |
q = new BigNumber(s); | |
qc = q.c = []; | |
e = x.e - y.e; | |
s = dp + e + 1; | |
if (!base) { | |
base = BASE; | |
e = bitFloor(x.e / LOG_BASE) - bitFloor(y.e / LOG_BASE); | |
s = s / LOG_BASE | 0; | |
} | |
// Result exponent may be one less then the current value of e. | |
// The coefficients of the BigNumbers from convertBase may have trailing zeros. | |
for (i = 0; yc[i] == (xc[i] || 0); i++) {} | |
if (yc[i] > (xc[i] || 0)) e--; | |
if (s < 0) { | |
qc.push(1); | |
more = true; | |
} else { | |
xL = xc.length; | |
yL = yc.length; | |
i = 0; | |
s += 2; | |
// Normalise xc and yc so highest order digit of yc is >= base / 2. | |
n = mathfloor(base / (yc[0] + 1)); | |
// Not necessary, but to handle odd bases where yc[0] == ( base / 2 ) - 1. | |
// if ( n > 1 || n++ == 1 && yc[0] < base / 2 ) { | |
if (n > 1) { | |
yc = multiply(yc, n, base); | |
xc = multiply(xc, n, base); | |
yL = yc.length; | |
xL = xc.length; | |
} | |
xi = yL; | |
rem = xc.slice(0, yL); | |
remL = rem.length; | |
// Add zeros to make remainder as long as divisor. | |
for (; remL < yL; rem[remL++] = 0) {} | |
yz = yc.slice(); | |
yz.unshift(0); | |
yc0 = yc[0]; | |
if (yc[1] >= base / 2) yc0++; | |
// Not necessary, but to prevent trial digit n > base, when using base 3. | |
// else if ( base == 3 && yc0 == 1 ) yc0 = 1 + 1e-15; | |
do { | |
n = 0; | |
// Compare divisor and remainder. | |
cmp = compare(yc, rem, yL, remL); | |
// If divisor < remainder. | |
if (cmp < 0) { | |
// Calculate trial digit, n. | |
rem0 = rem[0]; | |
if (yL != remL) rem0 = rem0 * base + (rem[1] || 0); | |
// n is how many times the divisor goes into the current remainder. | |
n = mathfloor(rem0 / yc0); | |
// Algorithm: | |
// 1. product = divisor * trial digit (n) | |
// 2. if product > remainder: product -= divisor, n-- | |
// 3. remainder -= product | |
// 4. if product was < remainder at 2: | |
// 5. compare new remainder and divisor | |
// 6. If remainder > divisor: remainder -= divisor, n++ | |
if (n > 1) { | |
// n may be > base only when base is 3. | |
if (n >= base) n = base - 1; | |
// product = divisor * trial digit. | |
prod = multiply(yc, n, base); | |
prodL = prod.length; | |
remL = rem.length; | |
// Compare product and remainder. | |
// If product > remainder. | |
// Trial digit n too high. | |
// n is 1 too high about 5% of the time, and is not known to have | |
// ever been more than 1 too high. | |
while (compare(prod, rem, prodL, remL) == 1) { | |
n--; | |
// Subtract divisor from product. | |
subtract(prod, yL < prodL ? yz : yc, prodL, base); | |
prodL = prod.length; | |
cmp = 1; | |
} | |
} else { | |
// n is 0 or 1, cmp is -1. | |
// If n is 0, there is no need to compare yc and rem again below, | |
// so change cmp to 1 to avoid it. | |
// If n is 1, leave cmp as -1, so yc and rem are compared again. | |
if (n == 0) { | |
// divisor < remainder, so n must be at least 1. | |
cmp = n = 1; | |
} | |
// product = divisor | |
prod = yc.slice(); | |
prodL = prod.length; | |
} | |
if (prodL < remL) prod.unshift(0); | |
// Subtract product from remainder. | |
subtract(rem, prod, remL, base); | |
remL = rem.length; | |
// If product was < remainder. | |
if (cmp == -1) { | |
// Compare divisor and new remainder. | |
// If divisor < new remainder, subtract divisor from remainder. | |
// Trial digit n too low. | |
// n is 1 too low about 5% of the time, and very rarely 2 too low. | |
while (compare(yc, rem, yL, remL) < 1) { | |
n++; | |
// Subtract divisor from remainder. | |
subtract(rem, yL < remL ? yz : yc, remL, base); | |
remL = rem.length; | |
} | |
} | |
} else if (cmp === 0) { | |
n++; | |
rem = [0]; | |
} // else cmp === 1 and n will be 0 | |
// Add the next digit, n, to the result array. | |
qc[i++] = n; | |
// Update the remainder. | |
if (rem[0]) { | |
rem[remL++] = xc[xi] || 0; | |
} else { | |
rem = [xc[xi]]; | |
remL = 1; | |
} | |
} while ((xi++ < xL || rem[0] != null) && s--); | |
more = rem[0] != null; | |
// Leading zero? | |
if (!qc[0]) qc.shift(); | |
} | |
if (base == BASE) { | |
// To calculate q.e, first get the number of digits of qc[0]. | |
for (i = 1, s = qc[0]; s >= 10; s /= 10, i++) {} | |
round(q, dp + (q.e = i + e * LOG_BASE - 1) + 1, rm, more); | |
// Caller is convertBase. | |
} else { | |
q.e = e; | |
q.r = +more; | |
} | |
return q; | |
}; | |
}(); | |
/* | |
* Return a string representing the value of BigNumber n in fixed-point or exponential | |
* notation rounded to the specified decimal places or significant digits. | |
* | |
* n is a BigNumber. | |
* i is the index of the last digit required (i.e. the digit that may be rounded up). | |
* rm is the rounding mode. | |
* caller is caller id: toExponential 19, toFixed 20, toFormat 21, toPrecision 24. | |
*/ | |
function format(n, i, rm, caller) { | |
var c0, e, ne, len, str; | |
rm = rm != null && isValidInt(rm, 0, 8, caller, roundingMode) ? rm | 0 : ROUNDING_MODE; | |
if (!n.c) return n.toString(); | |
c0 = n.c[0]; | |
ne = n.e; | |
if (i == null) { | |
str = coeffToString(n.c); | |
str = caller == 19 || caller == 24 && ne <= TO_EXP_NEG ? toExponential(str, ne) : toFixedPoint(str, ne); | |
} else { | |
n = round(new BigNumber(n), i, rm); | |
// n.e may have changed if the value was rounded up. | |
e = n.e; | |
str = coeffToString(n.c); | |
len = str.length; | |
// toPrecision returns exponential notation if the number of significant digits | |
// specified is less than the number of digits necessary to represent the integer | |
// part of the value in fixed-point notation. | |
// Exponential notation. | |
if (caller == 19 || caller == 24 && (i <= e || e <= TO_EXP_NEG)) { | |
// Append zeros? | |
for (; len < i; str += '0', len++) {} | |
str = toExponential(str, e); | |
// Fixed-point notation. | |
} else { | |
i -= ne; | |
str = toFixedPoint(str, e); | |
// Append zeros? | |
if (e + 1 > len) { | |
if (--i > 0) for (str += '.'; i--; str += '0') {} | |
} else { | |
i += e - len; | |
if (i > 0) { | |
if (e + 1 == len) str += '.'; | |
for (; i--; str += '0') {} | |
} | |
} | |
} | |
} | |
return n.s < 0 && c0 ? '-' + str : str; | |
} | |
// Handle BigNumber.max and BigNumber.min. | |
function maxOrMin(args, method) { | |
var m, | |
n, | |
i = 0; | |
if (isArray(args[0])) args = args[0]; | |
m = new BigNumber(args[0]); | |
for (; ++i < args.length;) { | |
n = new BigNumber(args[i]); | |
// If any number is NaN, return NaN. | |
if (!n.s) { | |
m = n; | |
break; | |
} else if (method.call(m, n)) { | |
m = n; | |
} | |
} | |
return m; | |
} | |
/* | |
* Return true if n is an integer in range, otherwise throw. | |
* Use for argument validation when ERRORS is true. | |
*/ | |
function intValidatorWithErrors(n, min, max, caller, name) { | |
if (n < min || n > max || n != truncate(n)) { | |
raise(caller, (name || 'decimal places') + (n < min || n > max ? ' out of range' : ' not an integer'), n); | |
} | |
return true; | |
} | |
/* | |
* Strip trailing zeros, calculate base 10 exponent and check against MIN_EXP and MAX_EXP. | |
* Called by minus, plus and times. | |
*/ | |
function normalise(n, c, e) { | |
var i = 1, | |
j = c.length; | |
// Remove trailing zeros. | |
for (; !c[--j]; c.pop()) {} | |
// Calculate the base 10 exponent. First get the number of digits of c[0]. | |
for (j = c[0]; j >= 10; j /= 10, i++) {} | |
// Overflow? | |
if ((e = i + e * LOG_BASE - 1) > MAX_EXP) { | |
// Infinity. | |
n.c = n.e = null; | |
// Underflow? | |
} else if (e < MIN_EXP) { | |
// Zero. | |
n.c = [n.e = 0]; | |
} else { | |
n.e = e; | |
n.c = c; | |
} | |
return n; | |
} | |
// Handle values that fail the validity test in BigNumber. | |
parseNumeric = function () { | |
var basePrefix = /^(-?)0([xbo])/i, | |
dotAfter = /^([^.]+)\.$/, | |
dotBefore = /^\.([^.]+)$/, | |
isInfinityOrNaN = /^-?(Infinity|NaN)$/, | |
whitespaceOrPlus = /^\s*\+|^\s+|\s+$/g; | |
return function (x, str, num, b) { | |
var base, | |
s = num ? str : str.replace(whitespaceOrPlus, ''); | |
// No exception on ±Infinity or NaN. | |
if (isInfinityOrNaN.test(s)) { | |
x.s = isNaN(s) ? null : s < 0 ? -1 : 1; | |
} else { | |
if (!num) { | |
// basePrefix = /^(-?)0([xbo])(?=\w[\w.]*$)/i | |
s = s.replace(basePrefix, function (m, p1, p2) { | |
base = (p2 = p2.toLowerCase()) == 'x' ? 16 : p2 == 'b' ? 2 : 8; | |
return !b || b == base ? p1 : m; | |
}); | |
if (b) { | |
base = b; | |
// E.g. '1.' to '1', '.1' to '0.1' | |
s = s.replace(dotAfter, '$1').replace(dotBefore, '0.$1'); | |
} | |
if (str != s) return new BigNumber(s, base); | |
} | |
// 'new BigNumber() not a number: {n}' | |
// 'new BigNumber() not a base {b} number: {n}' | |
if (ERRORS) raise(id, 'not a' + (b ? ' base ' + b : '') + ' number', str); | |
x.s = null; | |
} | |
x.c = x.e = null; | |
id = 0; | |
}; | |
}(); | |
// Throw a BigNumber Error. | |
function raise(caller, msg, val) { | |
var error = new Error(['new BigNumber', // 0 | |
'cmp', // 1 | |
'config', // 2 | |
'div', // 3 | |
'divToInt', // 4 | |
'eq', // 5 | |
'gt', // 6 | |
'gte', // 7 | |
'lt', // 8 | |
'lte', // 9 | |
'minus', // 10 | |
'mod', // 11 | |
'plus', // 12 | |
'precision', // 13 | |
'random', // 14 | |
'round', // 15 | |
'shift', // 16 | |
'times', // 17 | |
'toDigits', // 18 | |
'toExponential', // 19 | |
'toFixed', // 20 | |
'toFormat', // 21 | |
'toFraction', // 22 | |
'pow', // 23 | |
'toPrecision', // 24 | |
'toString', // 25 | |
'BigNumber' // 26 | |
][caller] + '() ' + msg + ': ' + val); | |
error.name = 'BigNumber Error'; | |
id = 0; | |
throw error; | |
} | |
/* | |
* Round x to sd significant digits using rounding mode rm. Check for over/under-flow. | |
* If r is truthy, it is known that there are more digits after the rounding digit. | |
*/ | |
function round(x, sd, rm, r) { | |
var d, | |
i, | |
j, | |
k, | |
n, | |
ni, | |
rd, | |
xc = x.c, | |
pows10 = POWS_TEN; | |
// if x is not Infinity or NaN... | |
if (xc) { | |
// rd is the rounding digit, i.e. the digit after the digit that may be rounded up. | |
// n is a base 1e14 number, the value of the element of array x.c containing rd. | |
// ni is the index of n within x.c. | |
// d is the number of digits of n. | |
// i is the index of rd within n including leading zeros. | |
// j is the actual index of rd within n (if < 0, rd is a leading zero). | |
out: { | |
// Get the number of digits of the first element of xc. | |
for (d = 1, k = xc[0]; k >= 10; k /= 10, d++) {} | |
i = sd - d; | |
// If the rounding digit is in the first element of xc... | |
if (i < 0) { | |
i += LOG_BASE; | |
j = sd; | |
n = xc[ni = 0]; | |
// Get the rounding digit at index j of n. | |
rd = n / pows10[d - j - 1] % 10 | 0; | |
} else { | |
ni = mathceil((i + 1) / LOG_BASE); | |
if (ni >= xc.length) { | |
if (r) { | |
// Needed by sqrt. | |
for (; xc.length <= ni; xc.push(0)) {} | |
n = rd = 0; | |
d = 1; | |
i %= LOG_BASE; | |
j = i - LOG_BASE + 1; | |
} else { | |
break out; | |
} | |
} else { | |
n = k = xc[ni]; | |
// Get the number of digits of n. | |
for (d = 1; k >= 10; k /= 10, d++) {} | |
// Get the index of rd within n. | |
i %= LOG_BASE; | |
// Get the index of rd within n, adjusted for leading zeros. | |
// The number of leading zeros of n is given by LOG_BASE - d. | |
j = i - LOG_BASE + d; | |
// Get the rounding digit at index j of n. | |
rd = j < 0 ? 0 : n / pows10[d - j - 1] % 10 | 0; | |
} | |
} | |
r = r || sd < 0 || | |
// Are there any non-zero digits after the rounding digit? | |
// The expression n % pows10[ d - j - 1 ] returns all digits of n to the right | |
// of the digit at j, e.g. if n is 908714 and j is 2, the expression gives 714. | |
xc[ni + 1] != null || (j < 0 ? n : n % pows10[d - j - 1]); | |
r = rm < 4 ? (rd || r) && (rm == 0 || rm == (x.s < 0 ? 3 : 2)) : rd > 5 || rd == 5 && (rm == 4 || r || rm == 6 && | |
// Check whether the digit to the left of the rounding digit is odd. | |
(i > 0 ? j > 0 ? n / pows10[d - j] : 0 : xc[ni - 1]) % 10 & 1 || rm == (x.s < 0 ? 8 : 7)); | |
if (sd < 1 || !xc[0]) { | |
xc.length = 0; | |
if (r) { | |
// Convert sd to decimal places. | |
sd -= x.e + 1; | |
// 1, 0.1, 0.01, 0.001, 0.0001 etc. | |
xc[0] = pows10[sd % LOG_BASE]; | |
x.e = -sd || 0; | |
} else { | |
// Zero. | |
xc[0] = x.e = 0; | |
} | |
return x; | |
} | |
// Remove excess digits. | |
if (i == 0) { | |
xc.length = ni; | |
k = 1; | |
ni--; | |
} else { | |
xc.length = ni + 1; | |
k = pows10[LOG_BASE - i]; | |
// E.g. 56700 becomes 56000 if 7 is the rounding digit. | |
// j > 0 means i > number of leading zeros of n. | |
xc[ni] = j > 0 ? mathfloor(n / pows10[d - j] % pows10[j]) * k : 0; | |
} | |
// Round up? | |
if (r) { | |
for (;;) { | |
// If the digit to be rounded up is in the first element of xc... | |
if (ni == 0) { | |
// i will be the length of xc[0] before k is added. | |
for (i = 1, j = xc[0]; j >= 10; j /= 10, i++) {} | |
j = xc[0] += k; | |
for (k = 1; j >= 10; j /= 10, k++) {} | |
// if i != k the length has increased. | |
if (i != k) { | |
x.e++; | |
if (xc[0] == BASE) xc[0] = 1; | |
} | |
break; | |
} else { | |
xc[ni] += k; | |
if (xc[ni] != BASE) break; | |
xc[ni--] = 0; | |
k = 1; | |
} | |
} | |
} | |
// Remove trailing zeros. | |
for (i = xc.length; xc[--i] === 0; xc.pop()) {} | |
} | |
// Overflow? Infinity. | |
if (x.e > MAX_EXP) { | |
x.c = x.e = null; | |
// Underflow? Zero. | |
} else if (x.e < MIN_EXP) { | |
x.c = [x.e = 0]; | |
} | |
} | |
return x; | |
} | |
// PROTOTYPE/INSTANCE METHODS | |
/* | |
* Return a new BigNumber whose value is the absolute value of this BigNumber. | |
*/ | |
P.absoluteValue = P.abs = function () { | |
var x = new BigNumber(this); | |
if (x.s < 0) x.s = 1; | |
return x; | |
}; | |
/* | |
* Return a new BigNumber whose value is the value of this BigNumber rounded to a whole | |
* number in the direction of Infinity. | |
*/ | |
P.ceil = function () { | |
return round(new BigNumber(this), this.e + 1, 2); | |
}; | |
/* | |
* Return | |
* 1 if the value of this BigNumber is greater than the value of BigNumber(y, b), | |
* -1 if the value of this BigNumber is less than the value of BigNumber(y, b), | |
* 0 if they have the same value, | |
* or null if the value of either is NaN. | |
*/ | |
P.comparedTo = P.cmp = function (y, b) { | |
id = 1; | |
return compare(this, new BigNumber(y, b)); | |
}; | |
/* | |
* Return the number of decimal places of the value of this BigNumber, or null if the value | |
* of this BigNumber is ±Infinity or NaN. | |
*/ | |
P.decimalPlaces = P.dp = function () { | |
var n, | |
v, | |
c = this.c; | |
if (!c) return null; | |
n = ((v = c.length - 1) - bitFloor(this.e / LOG_BASE)) * LOG_BASE; | |
// Subtract the number of trailing zeros of the last number. | |
if (v = c[v]) for (; v % 10 == 0; v /= 10, n--) {} | |
if (n < 0) n = 0; | |
return n; | |
}; | |
/* | |
* n / 0 = I | |
* n / N = N | |
* n / I = 0 | |
* 0 / n = 0 | |
* 0 / 0 = N | |
* 0 / N = N | |
* 0 / I = 0 | |
* N / n = N | |
* N / 0 = N | |
* N / N = N | |
* N / I = N | |
* I / n = I | |
* I / 0 = I | |
* I / N = N | |
* I / I = N | |
* | |
* Return a new BigNumber whose value is the value of this BigNumber divided by the value of | |
* BigNumber(y, b), rounded according to DECIMAL_PLACES and ROUNDING_MODE. | |
*/ | |
P.dividedBy = P.div = function (y, b) { | |
id = 3; | |
return div(this, new BigNumber(y, b), DECIMAL_PLACES, ROUNDING_MODE); | |
}; | |
/* | |
* Return a new BigNumber whose value is the integer part of dividing the value of this | |
* BigNumber by the value of BigNumber(y, b). | |
*/ | |
P.dividedToIntegerBy = P.divToInt = function (y, b) { | |
id = 4; | |
return div(this, new BigNumber(y, b), 0, 1); | |
}; | |
/* | |
* Return true if the value of this BigNumber is equal to the value of BigNumber(y, b), | |
* otherwise returns false. | |
*/ | |
P.equals = P.eq = function (y, b) { | |
id = 5; | |
return compare(this, new BigNumber(y, b)) === 0; | |
}; | |
/* | |
* Return a new BigNumber whose value is the value of this BigNumber rounded to a whole | |
* number in the direction of -Infinity. | |
*/ | |
P.floor = function () { | |
return round(new BigNumber(this), this.e + 1, 3); | |
}; | |
/* | |
* Return true if the value of this BigNumber is greater than the value of BigNumber(y, b), | |
* otherwise returns false. | |
*/ | |
P.greaterThan = P.gt = function (y, b) { | |
id = 6; | |
return compare(this, new BigNumber(y, b)) > 0; | |
}; | |
/* | |
* Return true if the value of this BigNumber is greater than or equal to the value of | |
* BigNumber(y, b), otherwise returns false. | |
*/ | |
P.greaterThanOrEqualTo = P.gte = function (y, b) { | |
id = 7; | |
return (b = compare(this, new BigNumber(y, b))) === 1 || b === 0; | |
}; | |
/* | |
* Return true if the value of this BigNumber is a finite number, otherwise returns false. | |
*/ | |
P.isFinite = function () { | |
return !!this.c; | |
}; | |
/* | |
* Return true if the value of this BigNumber is an integer, otherwise return false. | |
*/ | |
P.isInteger = P.isInt = function () { | |
return !!this.c && bitFloor(this.e / LOG_BASE) > this.c.length - 2; | |
}; | |
/* | |
* Return true if the value of this BigNumber is NaN, otherwise returns false. | |
*/ | |
P.isNaN = function () { | |
return !this.s; | |
}; | |
/* | |
* Return true if the value of this BigNumber is negative, otherwise returns false. | |
*/ | |
P.isNegative = P.isNeg = function () { | |
return this.s < 0; | |
}; | |
/* | |
* Return true if the value of this BigNumber is 0 or -0, otherwise returns false. | |
*/ | |
P.isZero = function () { | |
return !!this.c && this.c[0] == 0; | |
}; | |
/* | |
* Return true if the value of this BigNumber is less than the value of BigNumber(y, b), | |
* otherwise returns false. | |
*/ | |
P.lessThan = P.lt = function (y, b) { | |
id = 8; | |
return compare(this, new BigNumber(y, b)) < 0; | |
}; | |
/* | |
* Return true if the value of this BigNumber is less than or equal to the value of | |
* BigNumber(y, b), otherwise returns false. | |
*/ | |
P.lessThanOrEqualTo = P.lte = function (y, b) { | |
id = 9; | |
return (b = compare(this, new BigNumber(y, b))) === -1 || b === 0; | |
}; | |
/* | |
* n - 0 = n | |
* n - N = N | |
* n - I = -I | |
* 0 - n = -n | |
* 0 - 0 = 0 | |
* 0 - N = N | |
* 0 - I = -I | |
* N - n = N | |
* N - 0 = N | |
* N - N = N | |
* N - I = N | |
* I - n = I | |
* I - 0 = I | |
* I - N = N | |
* I - I = N | |
* | |
* Return a new BigNumber whose value is the value of this BigNumber minus the value of | |
* BigNumber(y, b). | |
*/ | |
P.minus = P.sub = function (y, b) { | |
var i, | |
j, | |
t, | |
xLTy, | |
x = this, | |
a = x.s; | |
id = 10; | |
y = new BigNumber(y, b); | |
b = y.s; | |
// Either NaN? | |
if (!a || !b) return new BigNumber(NaN); | |
// Signs differ? | |
if (a != b) { | |
y.s = -b; | |
return x.plus(y); | |
} | |
var xe = x.e / LOG_BASE, | |
ye = y.e / LOG_BASE, | |
xc = x.c, | |
yc = y.c; | |
if (!xe || !ye) { | |
// Either Infinity? | |
if (!xc || !yc) return xc ? (y.s = -b, y) : new BigNumber(yc ? x : NaN); | |
// Either zero? | |
if (!xc[0] || !yc[0]) { | |
// Return y if y is non-zero, x if x is non-zero, or zero if both are zero. | |
return yc[0] ? (y.s = -b, y) : new BigNumber(xc[0] ? x : | |
// IEEE 754 (2008) 6.3: n - n = -0 when rounding to -Infinity | |
ROUNDING_MODE == 3 ? -0 : 0); | |
} | |
} | |
xe = bitFloor(xe); | |
ye = bitFloor(ye); | |
xc = xc.slice(); | |
// Determine which is the bigger number. | |
if (a = xe - ye) { | |
if (xLTy = a < 0) { | |
a = -a; | |
t = xc; | |
} else { | |
ye = xe; | |
t = yc; | |
} | |
t.reverse(); | |
// Prepend zeros to equalise exponents. | |
for (b = a; b--; t.push(0)) {} | |
t.reverse(); | |
} else { | |
// Exponents equal. Check digit by digit. | |
j = (xLTy = (a = xc.length) < (b = yc.length)) ? a : b; | |
for (a = b = 0; b < j; b++) { | |
if (xc[b] != yc[b]) { | |
xLTy = xc[b] < yc[b]; | |
break; | |
} | |
} | |
} | |
// x < y? Point xc to the array of the bigger number. | |
if (xLTy) t = xc, xc = yc, yc = t, y.s = -y.s; | |
b = (j = yc.length) - (i = xc.length); | |
// Append zeros to xc if shorter. | |
// No need to add zeros to yc if shorter as subtract only needs to start at yc.length. | |
if (b > 0) for (; b--; xc[i++] = 0) {} | |
b = BASE - 1; | |
// Subtract yc from xc. | |
for (; j > a;) { | |
if (xc[--j] < yc[j]) { | |
for (i = j; i && !xc[--i]; xc[i] = b) {} | |
--xc[i]; | |
xc[j] += BASE; | |
} | |
xc[j] -= yc[j]; | |
} | |
// Remove leading zeros and adjust exponent accordingly. | |
for (; xc[0] == 0; xc.shift(), --ye) {} | |
// Zero? | |
if (!xc[0]) { | |
// Following IEEE 754 (2008) 6.3, | |
// n - n = +0 but n - n = -0 when rounding towards -Infinity. | |
y.s = ROUNDING_MODE == 3 ? -1 : 1; | |
y.c = [y.e = 0]; | |
return y; | |
} | |
// No need to check for Infinity as +x - +y != Infinity && -x - -y != Infinity | |
// for finite x and y. | |
return normalise(y, xc, ye); | |
}; | |
/* | |
* n % 0 = N | |
* n % N = N | |
* n % I = n | |
* 0 % n = 0 | |
* -0 % n = -0 | |
* 0 % 0 = N | |
* 0 % N = N | |
* 0 % I = 0 | |
* N % n = N | |
* N % 0 = N | |
* N % N = N | |
* N % I = N | |
* I % n = N | |
* I % 0 = N | |
* I % N = N | |
* I % I = N | |
* | |
* Return a new BigNumber whose value is the value of this BigNumber modulo the value of | |
* BigNumber(y, b). The result depends on the value of MODULO_MODE. | |
*/ | |
P.modulo = P.mod = function (y, b) { | |
var q, | |
s, | |
x = this; | |
id = 11; | |
y = new BigNumber(y, b); | |
// Return NaN if x is Infinity or NaN, or y is NaN or zero. | |
if (!x.c || !y.s || y.c && !y.c[0]) { | |
return new BigNumber(NaN); | |
// Return x if y is Infinity or x is zero. | |
} else if (!y.c || x.c && !x.c[0]) { | |
return new BigNumber(x); | |
} | |
if (MODULO_MODE == 9) { | |
// Euclidian division: q = sign(y) * floor(x / abs(y)) | |
// r = x - qy where 0 <= r < abs(y) | |
s = y.s; | |
y.s = 1; | |
q = div(x, y, 0, 3); | |
y.s = s; | |
q.s *= s; | |
} else { | |
q = div(x, y, 0, MODULO_MODE); | |
} | |
return x.minus(q.times(y)); | |
}; | |
/* | |
* Return a new BigNumber whose value is the value of this BigNumber negated, | |
* i.e. multiplied by -1. | |
*/ | |
P.negated = P.neg = function () { | |
var x = new BigNumber(this); | |
x.s = -x.s || null; | |
return x; | |
}; | |
/* | |
* n + 0 = n | |
* n + N = N | |
* n + I = I | |
* 0 + n = n | |
* 0 + 0 = 0 | |
* 0 + N = N | |
* 0 + I = I | |
* N + n = N | |
* N + 0 = N | |
* N + N = N | |
* N + I = N | |
* I + n = I | |
* I + 0 = I | |
* I + N = N | |
* I + I = I | |
* | |
* Return a new BigNumber whose value is the value of this BigNumber plus the value of | |
* BigNumber(y, b). | |
*/ | |
P.plus = P.add = function (y, b) { | |
var t, | |
x = this, | |
a = x.s; | |
id = 12; | |
y = new BigNumber(y, b); | |
b = y.s; | |
// Either NaN? | |
if (!a || !b) return new BigNumber(NaN); | |
// Signs differ? | |
if (a != b) { | |
y.s = -b; | |
return x.minus(y); | |
} | |
var xe = x.e / LOG_BASE, | |
ye = y.e / LOG_BASE, | |
xc = x.c, | |
yc = y.c; | |
if (!xe || !ye) { | |
// Return ±Infinity if either ±Infinity. | |
if (!xc || !yc) return new BigNumber(a / 0); | |
// Either zero? | |
// Return y if y is non-zero, x if x is non-zero, or zero if both are zero. | |
if (!xc[0] || !yc[0]) return yc[0] ? y : new BigNumber(xc[0] ? x : a * 0); | |
} | |
xe = bitFloor(xe); | |
ye = bitFloor(ye); | |
xc = xc.slice(); | |
// Prepend zeros to equalise exponents. Faster to use reverse then do unshifts. | |
if (a = xe - ye) { | |
if (a > 0) { | |
ye = xe; | |
t = yc; | |
} else { | |
a = -a; | |
t = xc; | |
} | |
t.reverse(); | |
for (; a--; t.push(0)) {} | |
t.reverse(); | |
} | |
a = xc.length; | |
b = yc.length; | |
// Point xc to the longer array, and b to the shorter length. | |
if (a - b < 0) t = yc, yc = xc, xc = t, b = a; | |
// Only start adding at yc.length - 1 as the further digits of xc can be ignored. | |
for (a = 0; b;) { | |
a = (xc[--b] = xc[b] + yc[b] + a) / BASE | 0; | |
xc[b] %= BASE; | |
} | |
if (a) { | |
xc.unshift(a); | |
++ye; | |
} | |
// No need to check for zero, as +x + +y != 0 && -x + -y != 0 | |
// ye = MAX_EXP + 1 possible | |
return normalise(y, xc, ye); | |
}; | |
/* | |
* Return the number of significant digits of the value of this BigNumber. | |
* | |
* [z] {boolean|number} Whether to count integer-part trailing zeros: true, false, 1 or 0. | |
*/ | |
P.precision = P.sd = function (z) { | |
var n, | |
v, | |
x = this, | |
c = x.c; | |
// 'precision() argument not a boolean or binary digit: {z}' | |
if (z != null && z !== !!z && z !== 1 && z !== 0) { | |
if (ERRORS) raise(13, 'argument' + notBool, z); | |
if (z != !!z) z = null; | |
} | |
if (!c) return null; | |
v = c.length - 1; | |
n = v * LOG_BASE + 1; | |
if (v = c[v]) { | |
// Subtract the number of trailing zeros of the last element. | |
for (; v % 10 == 0; v /= 10, n--) {} | |
// Add the number of digits of the first element. | |
for (v = c[0]; v >= 10; v /= 10, n++) {} | |
} | |
if (z && x.e + 1 > n) n = x.e + 1; | |
return n; | |
}; | |
/* | |
* Return a new BigNumber whose value is the value of this BigNumber rounded to a maximum of | |
* dp decimal places using rounding mode rm, or to 0 and ROUNDING_MODE respectively if | |
* omitted. | |
* | |
* [dp] {number} Decimal places. Integer, 0 to MAX inclusive. | |
* [rm] {number} Rounding mode. Integer, 0 to 8 inclusive. | |
* | |
* 'round() decimal places out of range: {dp}' | |
* 'round() decimal places not an integer: {dp}' | |
* 'round() rounding mode not an integer: {rm}' | |
* 'round() rounding mode out of range: {rm}' | |
*/ | |
P.round = function (dp, rm) { | |
var n = new BigNumber(this); | |
if (dp == null || isValidInt(dp, 0, MAX, 15)) { | |
round(n, ~~dp + this.e + 1, rm == null || !isValidInt(rm, 0, 8, 15, roundingMode) ? ROUNDING_MODE : rm | 0); | |
} | |
return n; | |
}; | |
/* | |
* Return a new BigNumber whose value is the value of this BigNumber shifted by k places | |
* (powers of 10). Shift to the right if n > 0, and to the left if n < 0. | |
* | |
* k {number} Integer, -MAX_SAFE_INTEGER to MAX_SAFE_INTEGER inclusive. | |
* | |
* If k is out of range and ERRORS is false, the result will be ±0 if k < 0, or ±Infinity | |
* otherwise. | |
* | |
* 'shift() argument not an integer: {k}' | |
* 'shift() argument out of range: {k}' | |
*/ | |
P.shift = function (k) { | |
var n = this; | |
return isValidInt(k, -MAX_SAFE_INTEGER, MAX_SAFE_INTEGER, 16, 'argument') | |
// k < 1e+21, or truncate(k) will produce exponential notation. | |
? n.times('1e' + truncate(k)) : new BigNumber(n.c && n.c[0] && (k < -MAX_SAFE_INTEGER || k > MAX_SAFE_INTEGER) ? n.s * (k < 0 ? 0 : 1 / 0) : n); | |
}; | |
/* | |
* sqrt(-n) = N | |
* sqrt( N) = N | |
* sqrt(-I) = N | |
* sqrt( I) = I | |
* sqrt( 0) = 0 | |
* sqrt(-0) = -0 | |
* | |
* Return a new BigNumber whose value is the square root of the value of this BigNumber, | |
* rounded according to DECIMAL_PLACES and ROUNDING_MODE. | |
*/ | |
P.squareRoot = P.sqrt = function () { | |
var m, | |
n, | |
r, | |
rep, | |
t, | |
x = this, | |
c = x.c, | |
s = x.s, | |
e = x.e, | |
dp = DECIMAL_PLACES + 4, | |
half = new BigNumber('0.5'); | |
// Negative/NaN/Infinity/zero? | |
if (s !== 1 || !c || !c[0]) { | |
return new BigNumber(!s || s < 0 && (!c || c[0]) ? NaN : c ? x : 1 / 0); | |
} | |
// Initial estimate. | |
s = Math.sqrt(+x); | |
// Math.sqrt underflow/overflow? | |
// Pass x to Math.sqrt as integer, then adjust the exponent of the result. | |
if (s == 0 || s == 1 / 0) { | |
n = coeffToString(c); | |
if ((n.length + e) % 2 == 0) n += '0'; | |
s = Math.sqrt(n); | |
e = bitFloor((e + 1) / 2) - (e < 0 || e % 2); | |
if (s == 1 / 0) { | |
n = '1e' + e; | |
} else { | |
n = s.toExponential(); | |
n = n.slice(0, n.indexOf('e') + 1) + e; | |
} | |
r = new BigNumber(n); | |
} else { | |
r = new BigNumber(s + ''); | |
} | |
// Check for zero. | |
// r could be zero if MIN_EXP is changed after the this value was created. | |
// This would cause a division by zero (x/t) and hence Infinity below, which would cause | |
// coeffToString to throw. | |
if (r.c[0]) { | |
e = r.e; | |
s = e + dp; | |
if (s < 3) s = 0; | |
// Newton-Raphson iteration. | |
for (;;) { | |
t = r; | |
r = half.times(t.plus(div(x, t, dp, 1))); | |
if (coeffToString(t.c).slice(0, s) === (n = coeffToString(r.c)).slice(0, s)) { | |
// The exponent of r may here be one less than the final result exponent, | |
// e.g 0.0009999 (e-4) --> 0.001 (e-3), so adjust s so the rounding digits | |
// are indexed correctly. | |
if (r.e < e) --s; | |
n = n.slice(s - 3, s + 1); | |
// The 4th rounding digit may be in error by -1 so if the 4 rounding digits | |
// are 9999 or 4999 (i.e. approaching a rounding boundary) continue the | |
// iteration. | |
if (n == '9999' || !rep && n == '4999') { | |
// On the first iteration only, check to see if rounding up gives the | |
// exact result as the nines may infinitely repeat. | |
if (!rep) { | |
round(t, t.e + DECIMAL_PLACES + 2, 0); | |
if (t.times(t).eq(x)) { | |
r = t; | |
break; | |
} | |
} | |
dp += 4; | |
s += 4; | |
rep = 1; | |
} else { | |
// If rounding digits are null, 0{0,4} or 50{0,3}, check for exact | |
// result. If not, then there are further digits and m will be truthy. | |
if (!+n || !+n.slice(1) && n.charAt(0) == '5') { | |
// Truncate to the first rounding digit. | |
round(r, r.e + DECIMAL_PLACES + 2, 1); | |
m = !r.times(r).eq(x); | |
} | |
break; | |
} | |
} | |
} | |
} | |
return round(r, r.e + DECIMAL_PLACES + 1, ROUNDING_MODE, m); | |
}; | |
/* | |
* n * 0 = 0 | |
* n * N = N | |
* n * I = I | |
* 0 * n = 0 | |
* 0 * 0 = 0 | |
* 0 * N = N | |
* 0 * I = N | |
* N * n = N | |
* N * 0 = N | |
* N * N = N | |
* N * I = N | |
* I * n = I | |
* I * 0 = N | |
* I * N = N | |
* I * I = I | |
* | |
* Return a new BigNumber whose value is the value of this BigNumber times the value of | |
* BigNumber(y, b). | |
*/ | |
P.times = P.mul = function (y, b) { | |
var c, | |
e, | |
i, | |
j, | |
k, | |
m, | |
xcL, | |
xlo, | |
xhi, | |
ycL, | |
ylo, | |
yhi, | |
zc, | |
base, | |
sqrtBase, | |
x = this, | |
xc = x.c, | |
yc = (id = 17, y = new BigNumber(y, b)).c; | |
// Either NaN, ±Infinity or ±0? | |
if (!xc || !yc || !xc[0] || !yc[0]) { | |
// Return NaN if either is NaN, or one is 0 and the other is Infinity. | |
if (!x.s || !y.s || xc && !xc[0] && !yc || yc && !yc[0] && !xc) { | |
y.c = y.e = y.s = null; | |
} else { | |
y.s *= x.s; | |
// Return ±Infinity if either is ±Infinity. | |
if (!xc || !yc) { | |
y.c = y.e = null; | |
// Return ±0 if either is ±0. | |
} else { | |
y.c = [0]; | |
y.e = 0; | |
} | |
} | |
return y; | |
} | |
e = bitFloor(x.e / LOG_BASE) + bitFloor(y.e / LOG_BASE); | |
y.s *= x.s; | |
xcL = xc.length; | |
ycL = yc.length; | |
// Ensure xc points to longer array and xcL to its length. | |
if (xcL < ycL) zc = xc, xc = yc, yc = zc, i = xcL, xcL = ycL, ycL = i; | |
// Initialise the result array with zeros. | |
for (i = xcL + ycL, zc = []; i--; zc.push(0)) {} | |
base = BASE; | |
sqrtBase = SQRT_BASE; | |
for (i = ycL; --i >= 0;) { | |
c = 0; | |
ylo = yc[i] % sqrtBase; | |
yhi = yc[i] / sqrtBase | 0; | |
for (k = xcL, j = i + k; j > i;) { | |
xlo = xc[--k] % sqrtBase; | |
xhi = xc[k] / sqrtBase | 0; | |
m = yhi * xlo + xhi * ylo; | |
xlo = ylo * xlo + m % sqrtBase * sqrtBase + zc[j] + c; | |
c = (xlo / base | 0) + (m / sqrtBase | 0) + yhi * xhi; | |
zc[j--] = xlo % base; | |
} | |
zc[j] = c; | |
} | |
if (c) { | |
++e; | |
} else { | |
zc.shift(); | |
} | |
return normalise(y, zc, e); | |
}; | |
/* | |
* Return a new BigNumber whose value is the value of this BigNumber rounded to a maximum of | |
* sd significant digits using rounding mode rm, or ROUNDING_MODE if rm is omitted. | |
* | |
* [sd] {number} Significant digits. Integer, 1 to MAX inclusive. | |
* [rm] {number} Rounding mode. Integer, 0 to 8 inclusive. | |
* | |
* 'toDigits() precision out of range: {sd}' | |
* 'toDigits() precision not an integer: {sd}' | |
* 'toDigits() rounding mode not an integer: {rm}' | |
* 'toDigits() rounding mode out of range: {rm}' | |
*/ | |
P.toDigits = function (sd, rm) { | |
var n = new BigNumber(this); | |
sd = sd == null || !isValidInt(sd, 1, MAX, 18, 'precision') ? null : sd | 0; | |
rm = rm == null || !isValidInt(rm, 0, 8, 18, roundingMode) ? ROUNDING_MODE : rm | 0; | |
return sd ? round(n, sd, rm) : n; | |
}; | |
/* | |
* Return a string representing the value of this BigNumber in exponential notation and | |
* rounded using ROUNDING_MODE to dp fixed decimal places. | |
* | |
* [dp] {number} Decimal places. Integer, 0 to MAX inclusive. | |
* [rm] {number} Rounding mode. Integer, 0 to 8 inclusive. | |
* | |
* 'toExponential() decimal places not an integer: {dp}' | |
* 'toExponential() decimal places out of range: {dp}' | |
* 'toExponential() rounding mode not an integer: {rm}' | |
* 'toExponential() rounding mode out of range: {rm}' | |
*/ | |
P.toExponential = function (dp, rm) { | |
return format(this, dp != null && isValidInt(dp, 0, MAX, 19) ? ~~dp + 1 : null, rm, 19); | |
}; | |
/* | |
* Return a string representing the value of this BigNumber in fixed-point notation rounding | |
* to dp fixed decimal places using rounding mode rm, or ROUNDING_MODE if rm is omitted. | |
* | |
* Note: as with JavaScript's number type, (-0).toFixed(0) is '0', | |
* but e.g. (-0.00001).toFixed(0) is '-0'. | |
* | |
* [dp] {number} Decimal places. Integer, 0 to MAX inclusive. | |
* [rm] {number} Rounding mode. Integer, 0 to 8 inclusive. | |
* | |
* 'toFixed() decimal places not an integer: {dp}' | |
* 'toFixed() decimal places out of range: {dp}' | |
* 'toFixed() rounding mode not an integer: {rm}' | |
* 'toFixed() rounding mode out of range: {rm}' | |
*/ | |
P.toFixed = function (dp, rm) { | |
return format(this, dp != null && isValidInt(dp, 0, MAX, 20) ? ~~dp + this.e + 1 : null, rm, 20); | |
}; | |
/* | |
* Return a string representing the value of this BigNumber in fixed-point notation rounded | |
* using rm or ROUNDING_MODE to dp decimal places, and formatted according to the properties | |
* of the FORMAT object (see BigNumber.config). | |
* | |
* FORMAT = { | |
* decimalSeparator : '.', | |
* groupSeparator : ',', | |
* groupSize : 3, | |
* secondaryGroupSize : 0, | |
* fractionGroupSeparator : '\xA0', // non-breaking space | |
* fractionGroupSize : 0 | |
* }; | |
* | |
* [dp] {number} Decimal places. Integer, 0 to MAX inclusive. | |
* [rm] {number} Rounding mode. Integer, 0 to 8 inclusive. | |
* | |
* 'toFormat() decimal places not an integer: {dp}' | |
* 'toFormat() decimal places out of range: {dp}' | |
* 'toFormat() rounding mode not an integer: {rm}' | |
* 'toFormat() rounding mode out of range: {rm}' | |
*/ | |
P.toFormat = function (dp, rm) { | |
var str = format(this, dp != null && isValidInt(dp, 0, MAX, 21) ? ~~dp + this.e + 1 : null, rm, 21); | |
if (this.c) { | |
var i, | |
arr = str.split('.'), | |
g1 = +FORMAT.groupSize, | |
g2 = +FORMAT.secondaryGroupSize, | |
groupSeparator = FORMAT.groupSeparator, | |
intPart = arr[0], | |
fractionPart = arr[1], | |
isNeg = this.s < 0, | |
intDigits = isNeg ? intPart.slice(1) : intPart, | |
len = intDigits.length; | |
if (g2) i = g1, g1 = g2, g2 = i, len -= i; | |
if (g1 > 0 && len > 0) { | |
i = len % g1 || g1; | |
intPart = intDigits.substr(0, i); | |
for (; i < len; i += g1) { | |
intPart += groupSeparator + intDigits.substr(i, g1); | |
} | |
if (g2 > 0) intPart += groupSeparator + intDigits.slice(i); | |
if (isNeg) intPart = '-' + intPart; | |
} | |
str = fractionPart ? intPart + FORMAT.decimalSeparator + ((g2 = +FORMAT.fractionGroupSize) ? fractionPart.replace(new RegExp('\\d{' + g2 + '}\\B', 'g'), '$&' + FORMAT.fractionGroupSeparator) : fractionPart) : intPart; | |
} | |
return str; | |
}; | |
/* | |
* Return a string array representing the value of this BigNumber as a simple fraction with | |
* an integer numerator and an integer denominator. The denominator will be a positive | |
* non-zero value less than or equal to the specified maximum denominator. If a maximum | |
* denominator is not specified, the denominator will be the lowest value necessary to | |
* represent the number exactly. | |
* | |
* [md] {number|string|BigNumber} Integer >= 1 and < Infinity. The maximum denominator. | |
* | |
* 'toFraction() max denominator not an integer: {md}' | |
* 'toFraction() max denominator out of range: {md}' | |
*/ | |
P.toFraction = function (md) { | |
var arr, | |
d0, | |
d2, | |
e, | |
exp, | |
n, | |
n0, | |
q, | |
s, | |
k = ERRORS, | |
x = this, | |
xc = x.c, | |
d = new BigNumber(ONE), | |
n1 = d0 = new BigNumber(ONE), | |
d1 = n0 = new BigNumber(ONE); | |
if (md != null) { | |
ERRORS = false; | |
n = new BigNumber(md); | |
ERRORS = k; | |
if (!(k = n.isInt()) || n.lt(ONE)) { | |
if (ERRORS) { | |
raise(22, 'max denominator ' + (k ? 'out of range' : 'not an integer'), md); | |
} | |
// ERRORS is false: | |
// If md is a finite non-integer >= 1, round it to an integer and use it. | |
md = !k && n.c && round(n, n.e + 1, 1).gte(ONE) ? n : null; | |
} | |
} | |
if (!xc) return x.toString(); | |
s = coeffToString(xc); | |
// Determine initial denominator. | |
// d is a power of 10 and the minimum max denominator that specifies the value exactly. | |
e = d.e = s.length - x.e - 1; | |
d.c[0] = POWS_TEN[(exp = e % LOG_BASE) < 0 ? LOG_BASE + exp : exp]; | |
md = !md || n.cmp(d) > 0 ? e > 0 ? d : n1 : n; | |
exp = MAX_EXP; | |
MAX_EXP = 1 / 0; | |
n = new BigNumber(s); | |
// n0 = d1 = 0 | |
n0.c[0] = 0; | |
for (;;) { | |
q = div(n, d, 0, 1); | |
d2 = d0.plus(q.times(d1)); | |
if (d2.cmp(md) == 1) break; | |
d0 = d1; | |
d1 = d2; | |
n1 = n0.plus(q.times(d2 = n1)); | |
n0 = d2; | |
d = n.minus(q.times(d2 = d)); | |
n = d2; | |
} | |
d2 = div(md.minus(d0), d1, 0, 1); | |
n0 = n0.plus(d2.times(n1)); | |
d0 = d0.plus(d2.times(d1)); | |
n0.s = n1.s = x.s; | |
e *= 2; | |
// Determine which fraction is closer to x, n0/d0 or n1/d1 | |
arr = div(n1, d1, e, ROUNDING_MODE).minus(x).abs().cmp(div(n0, d0, e, ROUNDING_MODE).minus(x).abs()) < 1 ? [n1.toString(), d1.toString()] : [n0.toString(), d0.toString()]; | |
MAX_EXP = exp; | |
return arr; | |
}; | |
/* | |
* Return the value of this BigNumber converted to a number primitive. | |
*/ | |
P.toNumber = function () { | |
var x = this; | |
// Ensure zero has correct sign. | |
return +x || (x.s ? x.s * 0 : NaN); | |
}; | |
/* | |
* Return a BigNumber whose value is the value of this BigNumber raised to the power n. | |
* If n is negative round according to DECIMAL_PLACES and ROUNDING_MODE. | |
* If POW_PRECISION is not 0, round to POW_PRECISION using ROUNDING_MODE. | |
* | |
* n {number} Integer, -9007199254740992 to 9007199254740992 inclusive. | |
* (Performs 54 loop iterations for n of 9007199254740992.) | |
* | |
* 'pow() exponent not an integer: {n}' | |
* 'pow() exponent out of range: {n}' | |
*/ | |
P.toPower = P.pow = function (n) { | |
var k, | |
y, | |
i = mathfloor(n < 0 ? -n : +n), | |
x = this; | |
// Pass ±Infinity to Math.pow if exponent is out of range. | |
if (!isValidInt(n, -MAX_SAFE_INTEGER, MAX_SAFE_INTEGER, 23, 'exponent') && (!isFinite(n) || i > MAX_SAFE_INTEGER && (n /= 0) || parseFloat(n) != n && !(n = NaN))) { | |
return new BigNumber(Math.pow(+x, n)); | |
} | |
// Truncating each coefficient array to a length of k after each multiplication equates | |
// to truncating significant digits to POW_PRECISION + [28, 41], i.e. there will be a | |
// minimum of 28 guard digits retained. (Using + 1.5 would give [9, 21] guard digits.) | |
k = POW_PRECISION ? mathceil(POW_PRECISION / LOG_BASE + 2) : 0; | |
y = new BigNumber(ONE); | |
for (;;) { | |
if (i % 2) { | |
y = y.times(x); | |
if (!y.c) break; | |
if (k && y.c.length > k) y.c.length = k; | |
} | |
i = mathfloor(i / 2); | |
if (!i) break; | |
x = x.times(x); | |
if (k && x.c && x.c.length > k) x.c.length = k; | |
} | |
if (n < 0) y = ONE.div(y); | |
return k ? round(y, POW_PRECISION, ROUNDING_MODE) : y; | |
}; | |
/* | |
* Return a string representing the value of this BigNumber rounded to sd significant digits | |
* using rounding mode rm or ROUNDING_MODE. If sd is less than the number of digits | |
* necessary to represent the integer part of the value in fixed-point notation, then use | |
* exponential notation. | |
* | |
* [sd] {number} Significant digits. Integer, 1 to MAX inclusive. | |
* [rm] {number} Rounding mode. Integer, 0 to 8 inclusive. | |
* | |
* 'toPrecision() precision not an integer: {sd}' | |
* 'toPrecision() precision out of range: {sd}' | |
* 'toPrecision() rounding mode not an integer: {rm}' | |
* 'toPrecision() rounding mode out of range: {rm}' | |
*/ | |
P.toPrecision = function (sd, rm) { | |
return format(this, sd != null && isValidInt(sd, 1, MAX, 24, 'precision') ? sd | 0 : null, rm, 24); | |
}; | |
/* | |
* Return a string representing the value of this BigNumber in base b, or base 10 if b is | |
* omitted. If a base is specified, including base 10, round according to DECIMAL_PLACES and | |
* ROUNDING_MODE. If a base is not specified, and this BigNumber has a positive exponent | |
* that is equal to or greater than TO_EXP_POS, or a negative exponent equal to or less than | |
* TO_EXP_NEG, return exponential notation. | |
* | |
* [b] {number} Integer, 2 to 64 inclusive. | |
* | |
* 'toString() base not an integer: {b}' | |
* 'toString() base out of range: {b}' | |
*/ | |
P.toString = function (b) { | |
var str, | |
n = this, | |
s = n.s, | |
e = n.e; | |
// Infinity or NaN? | |
if (e === null) { | |
if (s) { | |
str = 'Infinity'; | |
if (s < 0) str = '-' + str; | |
} else { | |
str = 'NaN'; | |
} | |
} else { | |
str = coeffToString(n.c); | |
if (b == null || !isValidInt(b, 2, 64, 25, 'base')) { | |
str = e <= TO_EXP_NEG || e >= TO_EXP_POS ? toExponential(str, e) : toFixedPoint(str, e); | |
} else { | |
str = convertBase(toFixedPoint(str, e), b | 0, 10, s); | |
} | |
if (s < 0 && n.c[0]) str = '-' + str; | |
} | |
return str; | |
}; | |
/* | |
* Return a new BigNumber whose value is the value of this BigNumber truncated to a whole | |
* number. | |
*/ | |
P.truncated = P.trunc = function () { | |
return round(new BigNumber(this), this.e + 1, 1); | |
}; | |
/* | |
* Return as toString, but do not accept a base argument. | |
*/ | |
P.valueOf = P.toJSON = function () { | |
return this.toString(); | |
}; | |
// Aliases for BigDecimal methods. | |
//P.add = P.plus; // P.add included above | |
//P.subtract = P.minus; // P.sub included above | |
//P.multiply = P.times; // P.mul included above | |
//P.divide = P.div; | |
//P.remainder = P.mod; | |
//P.compareTo = P.cmp; | |
//P.negate = P.neg; | |
if (configObj != null) BigNumber.config(configObj); | |
return BigNumber; | |
} | |
// PRIVATE HELPER FUNCTIONS | |
function bitFloor(n) { | |
var i = n | 0; | |
return n > 0 || n === i ? i : i - 1; | |
} | |
// Return a coefficient array as a string of base 10 digits. | |
function coeffToString(a) { | |
var s, | |
z, | |
i = 1, | |
j = a.length, | |
r = a[0] + ''; | |
for (; i < j;) { | |
s = a[i++] + ''; | |
z = LOG_BASE - s.length; | |
for (; z--; s = '0' + s) {} | |
r += s; | |
} | |
// Determine trailing zeros. | |
for (j = r.length; r.charCodeAt(--j) === 48;) {} | |
return r.slice(0, j + 1 || 1); | |
} | |
// Compare the value of BigNumbers x and y. | |
function compare(x, y) { | |
var a, | |
b, | |
xc = x.c, | |
yc = y.c, | |
i = x.s, | |
j = y.s, | |
k = x.e, | |
l = y.e; | |
// Either NaN? | |
if (!i || !j) return null; | |
a = xc && !xc[0]; | |
b = yc && !yc[0]; | |
// Either zero? | |
if (a || b) return a ? b ? 0 : -j : i; | |
// Signs differ? | |
if (i != j) return i; | |
a = i < 0; | |
b = k == l; | |
// Either Infinity? | |
if (!xc || !yc) return b ? 0 : !xc ^ a ? 1 : -1; | |
// Compare exponents. | |
if (!b) return k > l ^ a ? 1 : -1; | |
j = (k = xc.length) < (l = yc.length) ? k : l; | |
// Compare digit by digit. | |
for (i = 0; i < j; i++) { | |
if (xc[i] != yc[i]) return xc[i] > yc[i] ^ a ? 1 : -1; | |
} // Compare lengths. | |
return k == l ? 0 : k > l ^ a ? 1 : -1; | |
} | |
/* | |
* Return true if n is a valid number in range, otherwise false. | |
* Use for argument validation when ERRORS is false. | |
* Note: parseInt('1e+1') == 1 but parseFloat('1e+1') == 10. | |
*/ | |
function intValidatorNoErrors(n, min, max) { | |
return (n = truncate(n)) >= min && n <= max; | |
} | |
function isArray(obj) { | |
return Object.prototype.toString.call(obj) == '[object Array]'; | |
} | |
/* | |
* Convert string of baseIn to an array of numbers of baseOut. | |
* Eg. convertBase('255', 10, 16) returns [15, 15]. | |
* Eg. convertBase('ff', 16, 10) returns [2, 5, 5]. | |
*/ | |
function toBaseOut(str, baseIn, baseOut) { | |
var j, | |
arr = [0], | |
arrL, | |
i = 0, | |
len = str.length; | |
for (; i < len;) { | |
for (arrL = arr.length; arrL--; arr[arrL] *= baseIn) {} | |
arr[j = 0] += ALPHABET.indexOf(str.charAt(i++)); | |
for (; j < arr.length; j++) { | |
if (arr[j] > baseOut - 1) { | |
if (arr[j + 1] == null) arr[j + 1] = 0; | |
arr[j + 1] += arr[j] / baseOut | 0; | |
arr[j] %= baseOut; | |
} | |
} | |
} | |
return arr.reverse(); | |
} | |
function toExponential(str, e) { | |
return (str.length > 1 ? str.charAt(0) + '.' + str.slice(1) : str) + (e < 0 ? 'e' : 'e+') + e; | |
} | |
function toFixedPoint(str, e) { | |
var len, z; | |
// Negative exponent? | |
if (e < 0) { | |
// Prepend zeros. | |
for (z = '0.'; ++e; z += '0') {} | |
str = z + str; | |
// Positive exponent | |
} else { | |
len = str.length; | |
// Append zeros. | |
if (++e > len) { | |
for (z = '0', e -= len; --e; z += '0') {} | |
str += z; | |
} else if (e < len) { | |
str = str.slice(0, e) + '.' + str.slice(e); | |
} | |
} | |
return str; | |
} | |
function truncate(n) { | |
n = parseFloat(n); | |
return n < 0 ? mathceil(n) : mathfloor(n); | |
} | |
// EXPORT | |
BigNumber = another(); | |
// AMD. | |
if (typeof define == 'function' && define.amd) { | |
define(function () { | |
return BigNumber; | |
}); | |
// Node and other environments that support module.exports. | |
} else if (typeof module != 'undefined' && module.exports) { | |
module.exports = BigNumber; | |
if (!crypto) try { | |
crypto = require('crypto'); | |
} catch (e) {} | |
// Browser. | |
} else { | |
global.BigNumber = BigNumber; | |
} | |
})(undefined); | |
},{"crypto":173}],25:[function(require,module,exports){ | |
'use strict'; | |
// Reference https://github.com/bitcoin/bips/blob/master/bip-0066.mediawiki | |
// Format: 0x30 [total-length] 0x02 [R-length] [R] 0x02 [S-length] [S] | |
// NOTE: SIGHASH byte ignored AND restricted, truncate before use | |
var Buffer = require('safe-buffer').Buffer; | |
function check(buffer) { | |
if (buffer.length < 8) return false; | |
if (buffer.length > 72) return false; | |
if (buffer[0] !== 0x30) return false; | |
if (buffer[1] !== buffer.length - 2) return false; | |
if (buffer[2] !== 0x02) return false; | |
var lenR = buffer[3]; | |
if (lenR === 0) return false; | |
if (5 + lenR >= buffer.length) return false; | |
if (buffer[4 + lenR] !== 0x02) return false; | |
var lenS = buffer[5 + lenR]; | |
if (lenS === 0) return false; | |
if (6 + lenR + lenS !== buffer.length) return false; | |
if (buffer[4] & 0x80) return false; | |
if (lenR > 1 && buffer[4] === 0x00 && !(buffer[5] & 0x80)) return false; | |
if (buffer[lenR + 6] & 0x80) return false; | |
if (lenS > 1 && buffer[lenR + 6] === 0x00 && !(buffer[lenR + 7] & 0x80)) return false; | |
return true; | |
} | |
function decode(buffer) { | |
if (buffer.length < 8) throw new Error('DER sequence length is too short'); | |
if (buffer.length > 72) throw new Error('DER sequence length is too long'); | |
if (buffer[0] !== 0x30) throw new Error('Expected DER sequence'); | |
if (buffer[1] !== buffer.length - 2) throw new Error('DER sequence length is invalid'); | |
if (buffer[2] !== 0x02) throw new Error('Expected DER integer'); | |
var lenR = buffer[3]; | |
if (lenR === 0) throw new Error('R length is zero'); | |
if (5 + lenR >= buffer.length) throw new Error('R length is too long'); | |
if (buffer[4 + lenR] !== 0x02) throw new Error('Expected DER integer (2)'); | |
var lenS = buffer[5 + lenR]; | |
if (lenS === 0) throw new Error('S length is zero'); | |
if (6 + lenR + lenS !== buffer.length) throw new Error('S length is invalid'); | |
if (buffer[4] & 0x80) throw new Error('R value is negative'); | |
if (lenR > 1 && buffer[4] === 0x00 && !(buffer[5] & 0x80)) throw new Error('R value excessively padded'); | |
if (buffer[lenR + 6] & 0x80) throw new Error('S value is negative'); | |
if (lenS > 1 && buffer[lenR + 6] === 0x00 && !(buffer[lenR + 7] & 0x80)) throw new Error('S value excessively padded'); | |
// non-BIP66 - extract R, S values | |
return { | |
r: buffer.slice(4, 4 + lenR), | |
s: buffer.slice(6 + lenR) | |
}; | |
} | |
/* | |
* Expects r and s to be positive DER integers. | |
* | |
* The DER format uses the most significant bit as a sign bit (& 0x80). | |
* If the significant bit is set AND the integer is positive, a 0x00 is prepended. | |
* | |
* Examples: | |
* | |
* 0 => 0x00 | |
* 1 => 0x01 | |
* -1 => 0xff | |
* 127 => 0x7f | |
* -127 => 0x81 | |
* 128 => 0x0080 | |
* -128 => 0x80 | |
* 255 => 0x00ff | |
* -255 => 0xff01 | |
* 16300 => 0x3fac | |
* -16300 => 0xc054 | |
* 62300 => 0x00f35c | |
* -62300 => 0xff0ca4 | |
*/ | |
function encode(r, s) { | |
var lenR = r.length; | |
var lenS = s.length; | |
if (lenR === 0) throw new Error('R length is zero'); | |
if (lenS === 0) throw new Error('S length is zero'); | |
if (lenR > 33) throw new Error('R length is too long'); | |
if (lenS > 33) throw new Error('S length is too long'); | |
if (r[0] & 0x80) throw new Error('R value is negative'); | |
if (s[0] & 0x80) throw new Error('S value is negative'); | |
if (lenR > 1 && r[0] === 0x00 && !(r[1] & 0x80)) throw new Error('R value excessively padded'); | |
if (lenS > 1 && s[0] === 0x00 && !(s[1] & 0x80)) throw new Error('S value excessively padded'); | |
var signature = Buffer.allocUnsafe(6 + lenR + lenS); | |
// 0x30 [total-length] 0x02 [R-length] [R] 0x02 [S-length] [S] | |
signature[0] = 0x30; | |
signature[1] = signature.length - 2; | |
signature[2] = 0x02; | |
signature[3] = r.length; | |
r.copy(signature, 4); | |
signature[4 + lenR] = 0x02; | |
signature[5 + lenR] = s.length; | |
s.copy(signature, 6 + lenR); | |
return signature; | |
} | |
module.exports = { | |
check: check, | |
decode: decode, | |
encode: encode | |
}; | |
},{"safe-buffer":314}],26:[function(require,module,exports){ | |
(function (global,Buffer){ | |
'use strict'; | |
var bitcore = module.exports; | |
// module information | |
bitcore.version = 'v' + require('./package.json').version; | |
bitcore.versionGuard = function (version) { | |
if (version !== undefined) { | |
var message = 'More than one instance of bitcore-lib found. ' + 'Please make sure to require bitcore-lib and check that submodules do' + ' not also include their own bitcore-lib dependency.'; | |
throw new Error(message); | |
} | |
}; | |
bitcore.versionGuard(global._bitcore); | |
global._bitcore = bitcore.version; | |
// crypto | |
bitcore.crypto = {}; | |
bitcore.crypto.BN = require('./lib/crypto/bn'); | |
bitcore.crypto.ECDSA = require('./lib/crypto/ecdsa'); | |
bitcore.crypto.Hash = require('./lib/crypto/hash'); | |
bitcore.crypto.Random = require('./lib/crypto/random'); | |
bitcore.crypto.Point = require('./lib/crypto/point'); | |
bitcore.crypto.Signature = require('./lib/crypto/signature'); | |
// encoding | |
bitcore.encoding = {}; | |
bitcore.encoding.Base58 = require('./lib/encoding/base58'); | |
bitcore.encoding.Base58Check = require('./lib/encoding/base58check'); | |
bitcore.encoding.BufferReader = require('./lib/encoding/bufferreader'); | |
bitcore.encoding.BufferWriter = require('./lib/encoding/bufferwriter'); | |
bitcore.encoding.Varint = require('./lib/encoding/varint'); | |
// utilities | |
bitcore.util = {}; | |
bitcore.util.buffer = require('./lib/util/buffer'); | |
bitcore.util.js = require('./lib/util/js'); | |
bitcore.util.preconditions = require('./lib/util/preconditions'); | |
// errors thrown by the library | |
bitcore.errors = require('./lib/errors'); | |
// main bitcoin library | |
bitcore.Address = require('./lib/address'); | |
bitcore.Block = require('./lib/block'); | |
bitcore.MerkleBlock = require('./lib/block/merkleblock'); | |
bitcore.BlockHeader = require('./lib/block/blockheader'); | |
bitcore.HDPrivateKey = require('./lib/hdprivatekey.js'); | |
bitcore.HDPublicKey = require('./lib/hdpublickey.js'); | |
bitcore.Networks = require('./lib/networks'); | |
bitcore.Opcode = require('./lib/opcode'); | |
bitcore.PrivateKey = require('./lib/privatekey'); | |
bitcore.PublicKey = require('./lib/publickey'); | |
bitcore.Script = require('./lib/script'); | |
bitcore.Transaction = require('./lib/transaction'); | |
bitcore.URI = require('./lib/uri'); | |
bitcore.Unit = require('./lib/unit'); | |
// dependencies, subject to change | |
bitcore.deps = {}; | |
bitcore.deps.bnjs = require('bn.js'); | |
bitcore.deps.bs58 = require('bs58'); | |
bitcore.deps.Buffer = Buffer; | |
bitcore.deps.elliptic = require('elliptic'); | |
bitcore.deps._ = require('lodash'); | |
// Internal usage, exposed for testing/advanced tweaking | |
bitcore.Transaction.sighash = require('./lib/transaction/sighash'); | |
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {},require("buffer").Buffer) | |
},{"./lib/address":27,"./lib/block":30,"./lib/block/blockheader":29,"./lib/block/merkleblock":31,"./lib/crypto/bn":32,"./lib/crypto/ecdsa":33,"./lib/crypto/hash":34,"./lib/crypto/point":35,"./lib/crypto/random":36,"./lib/crypto/signature":37,"./lib/encoding/base58":38,"./lib/encoding/base58check":39,"./lib/encoding/bufferreader":40,"./lib/encoding/bufferwriter":41,"./lib/encoding/varint":42,"./lib/errors":43,"./lib/hdprivatekey.js":45,"./lib/hdpublickey.js":46,"./lib/networks":47,"./lib/opcode":48,"./lib/privatekey":49,"./lib/publickey":50,"./lib/script":51,"./lib/transaction":54,"./lib/transaction/sighash":62,"./lib/unit":66,"./lib/uri":67,"./lib/util/buffer":68,"./lib/util/js":69,"./lib/util/preconditions":70,"./package.json":87,"bn.js":99,"bs58":145,"buffer":148,"elliptic":71,"lodash":267}],27:[function(require,module,exports){ | |
(function (Buffer){ | |
'use strict'; | |
var _ = require('lodash'); | |
var $ = require('./util/preconditions'); | |
var errors = require('./errors'); | |
var Base58Check = require('./encoding/base58check'); | |
var Networks = require('./networks'); | |
var Hash = require('./crypto/hash'); | |
var JSUtil = require('./util/js'); | |
var PublicKey = require('./publickey'); | |
/** | |
* Instantiate an address from an address String or Buffer, a public key or script hash Buffer, | |
* or an instance of {@link PublicKey} or {@link Script}. | |
* | |
* This is an immutable class, and if the first parameter provided to this constructor is an | |
* `Address` instance, the same argument will be returned. | |
* | |
* An address has two key properties: `network` and `type`. The type is either | |
* `Address.PayToPublicKeyHash` (value is the `'pubkeyhash'` string) | |
* or `Address.PayToScriptHash` (the string `'scripthash'`). The network is an instance of {@link Network}. | |
* You can quickly check whether an address is of a given kind by using the methods | |
* `isPayToPublicKeyHash` and `isPayToScriptHash` | |
* | |
* @example | |
* ```javascript | |
* // validate that an input field is valid | |
* var error = Address.getValidationError(input, 'testnet'); | |
* if (!error) { | |
* var address = Address(input, 'testnet'); | |
* } else { | |
* // invalid network or checksum (typo?) | |
* var message = error.messsage; | |
* } | |
* | |
* // get an address from a public key | |
* var address = Address(publicKey, 'testnet').toString(); | |
* ``` | |
* | |
* @param {*} data - The encoded data in various formats | |
* @param {Network|String|number=} network - The network: 'livenet' or 'testnet' | |
* @param {string=} type - The type of address: 'script' or 'pubkey' | |
* @returns {Address} A new valid and frozen instance of an Address | |
* @constructor | |
*/ | |
function Address(data, network, type) { | |
/* jshint maxcomplexity: 12 */ | |
/* jshint maxstatements: 20 */ | |
if (!(this instanceof Address)) { | |
return new Address(data, network, type); | |
} | |
if (_.isArray(data) && _.isNumber(network)) { | |
return Address.createMultisig(data, network, type); | |
} | |
if (data instanceof Address) { | |
// Immutable instance | |
return data; | |
} | |
$.checkArgument(data, 'First argument is required, please include address data.', 'guide/address.html'); | |
if (network && !Networks.get(network)) { | |
throw new TypeError('Second argument must be "livenet" or "testnet".'); | |
} | |
if (type && type !== Address.PayToPublicKeyHash && type !== Address.PayToScriptHash) { | |
throw new TypeError('Third argument must be "pubkeyhash" or "scripthash".'); | |
} | |
var info = this._classifyArguments(data, network, type); | |
// set defaults if not set | |
info.network = info.network || Networks.get(network) || Networks.defaultNetwork; | |
info.type = info.type || type || Address.PayToPublicKeyHash; | |
JSUtil.defineImmutable(this, { | |
hashBuffer: info.hashBuffer, | |
network: info.network, | |
type: info.type | |
}); | |
return this; | |
} | |
/** | |
* Internal function used to split different kinds of arguments of the constructor | |
* @param {*} data - The encoded data in various formats | |
* @param {Network|String|number=} network - The network: 'livenet' or 'testnet' | |
* @param {string=} type - The type of address: 'script' or 'pubkey' | |
* @returns {Object} An "info" object with "type", "network", and "hashBuffer" | |
*/ | |
Address.prototype._classifyArguments = function (data, network, type) { | |
/* jshint maxcomplexity: 10 */ | |
// transform and validate input data | |
if ((data instanceof Buffer || data instanceof Uint8Array) && data.length === 20) { | |
return Address._transformHash(data); | |
} else if ((data instanceof Buffer || data instanceof Uint8Array) && data.length === 21) { | |
return Address._transformBuffer(data, network, type); | |
} else if (data instanceof PublicKey) { | |
return Address._transformPublicKey(data); | |
} else if (data instanceof Script) { | |
return Address._transformScript(data, network); | |
} else if (typeof data === 'string') { | |
return Address._transformString(data, network, type); | |
} else if (_.isObject(data)) { | |
return Address._transformObject(data); | |
} else { | |
throw new TypeError('First argument is an unrecognized data format.'); | |
} | |
}; | |
/** @static */ | |
Address.PayToPublicKeyHash = 'pubkeyhash'; | |
/** @static */ | |
Address.PayToScriptHash = 'scripthash'; | |
/** | |
* @param {Buffer} hash - An instance of a hash Buffer | |
* @returns {Object} An object with keys: hashBuffer | |
* @private | |
*/ | |
Address._transformHash = function (hash) { | |
var info = {}; | |
if (!(hash instanceof Buffer) && !(hash instanceof Uint8Array)) { | |
throw new TypeError('Address supplied is not a buffer.'); | |
} | |
if (hash.length !== 20) { | |
throw new TypeError('Address hashbuffers must be exactly 20 bytes.'); | |
} | |
info.hashBuffer = hash; | |
return info; | |
}; | |
/** | |
* Deserializes an address serialized through `Address#toObject()` | |
* @param {Object} data | |
* @param {string} data.hash - the hash that this address encodes | |
* @param {string} data.type - either 'pubkeyhash' or 'scripthash' | |
* @param {Network=} data.network - the name of the network associated | |
* @return {Address} | |
*/ | |
Address._transformObject = function (data) { | |
$.checkArgument(data.hash || data.hashBuffer, 'Must provide a `hash` or `hashBuffer` property'); | |
$.checkArgument(data.type, 'Must provide a `type` property'); | |
return { | |
hashBuffer: data.hash ? new Buffer(data.hash, 'hex') : data.hashBuffer, | |
network: Networks.get(data.network) || Networks.defaultNetwork, | |
type: data.type | |
}; | |
}; | |
/** | |
* Internal function to discover the network and type based on the first data byte | |
* | |
* @param {Buffer} buffer - An instance of a hex encoded address Buffer | |
* @returns {Object} An object with keys: network and type | |
* @private | |
*/ | |
Address._classifyFromVersion = function (buffer) { | |
var version = {}; | |
var pubkeyhashNetwork = Networks.get(buffer[0], 'pubkeyhash'); | |
var scripthashNetwork = Networks.get(buffer[0], 'scripthash'); | |
if (pubkeyhashNetwork) { | |
version.network = pubkeyhashNetwork; | |
version.type = Address.PayToPublicKeyHash; | |
} else if (scripthashNetwork) { | |
version.network = scripthashNetwork; | |
version.type = Address.PayToScriptHash; | |
} | |
return version; | |
}; | |
/** | |
* Internal function to transform a bitcoin address buffer | |
* | |
* @param {Buffer} buffer - An instance of a hex encoded address Buffer | |
* @param {string=} network - The network: 'livenet' or 'testnet' | |
* @param {string=} type - The type: 'pubkeyhash' or 'scripthash' | |
* @returns {Object} An object with keys: hashBuffer, network and type | |
* @private | |
*/ | |
Address._transformBuffer = function (buffer, network, type) { | |
/* jshint maxcomplexity: 9 */ | |
var info = {}; | |
if (!(buffer instanceof Buffer) && !(buffer instanceof Uint8Array)) { | |
throw new TypeError('Address supplied is not a buffer.'); | |
} | |
if (buffer.length !== 1 + 20) { | |
throw new TypeError('Address buffers must be exactly 21 bytes.'); | |
} | |
var networkObj = Networks.get(network); | |
var bufferVersion = Address._classifyFromVersion(buffer); | |
if (network && !networkObj) { | |
throw new TypeError('Unknown network'); | |
} | |
if (!bufferVersion.network || networkObj && networkObj !== bufferVersion.network) { | |
throw new TypeError('Address has mismatched network type.'); | |
} | |
if (!bufferVersion.type || type && type !== bufferVersion.type) { | |
throw new TypeError('Address has mismatched type.'); | |
} | |
info.hashBuffer = buffer.slice(1); | |
info.network = bufferVersion.network; | |
info.type = bufferVersion.type; | |
return info; | |
}; | |
/** | |
* Internal function to transform a {@link PublicKey} | |
* | |
* @param {PublicKey} pubkey - An instance of PublicKey | |
* @returns {Object} An object with keys: hashBuffer, type | |
* @private | |
*/ | |
Address._transformPublicKey = function (pubkey) { | |
var info = {}; | |
if (!(pubkey instanceof PublicKey)) { | |
throw new TypeError('Address must be an instance of PublicKey.'); | |
} | |
info.hashBuffer = Hash.sha256ripemd160(pubkey.toBuffer()); | |
info.type = Address.PayToPublicKeyHash; | |
return info; | |
}; | |
/** | |
* Internal function to transform a {@link Script} into a `info` object. | |
* | |
* @param {Script} script - An instance of Script | |
* @returns {Object} An object with keys: hashBuffer, type | |
* @private | |
*/ | |
Address._transformScript = function (script, network) { | |
$.checkArgument(script instanceof Script, 'script must be a Script instance'); | |
var info = script.getAddressInfo(network); | |
if (!info) { | |
throw new errors.Script.CantDeriveAddress(script); | |
} | |
return info; | |
}; | |
/** | |
* Creates a P2SH address from a set of public keys and a threshold. | |
* | |
* The addresses will be sorted lexicographically, as that is the trend in bitcoin. | |
* To create an address from unsorted public keys, use the {@link Script#buildMultisigOut} | |
* interface. | |
* | |
* @param {Array} publicKeys - a set of public keys to create an address | |
* @param {number} threshold - the number of signatures needed to release the funds | |
* @param {String|Network} network - either a Network instance, 'livenet', or 'testnet' | |
* @return {Address} | |
*/ | |
Address.createMultisig = function (publicKeys, threshold, network) { | |
network = network || publicKeys[0].network || Networks.defaultNetwork; | |
return Address.payingTo(Script.buildMultisigOut(publicKeys, threshold), network); | |
}; | |
/** | |
* Internal function to transform a bitcoin address string | |
* | |
* @param {string} data | |
* @param {String|Network=} network - either a Network instance, 'livenet', or 'testnet' | |
* @param {string=} type - The type: 'pubkeyhash' or 'scripthash' | |
* @returns {Object} An object with keys: hashBuffer, network and type | |
* @private | |
*/ | |
Address._transformString = function (data, network, type) { | |
if (typeof data !== 'string') { | |
throw new TypeError('data parameter supplied is not a string.'); | |
} | |
data = data.trim(); | |
var addressBuffer = Base58Check.decode(data); | |
var info = Address._transformBuffer(addressBuffer, network, type); | |
return info; | |
}; | |
/** | |
* Instantiate an address from a PublicKey instance | |
* | |
* @param {PublicKey} data | |
* @param {String|Network} network - either a Network instance, 'livenet', or 'testnet' | |
* @returns {Address} A new valid and frozen instance of an Address | |
*/ | |
Address.fromPublicKey = function (data, network) { | |
var info = Address._transformPublicKey(data); | |
network = network || Networks.defaultNetwork; | |
return new Address(info.hashBuffer, network, info.type); | |
}; | |
/** | |
* Instantiate an address from a ripemd160 public key hash | |
* | |
* @param {Buffer} hash - An instance of buffer of the hash | |
* @param {String|Network} network - either a Network instance, 'livenet', or 'testnet' | |
* @returns {Address} A new valid and frozen instance of an Address | |
*/ | |
Address.fromPublicKeyHash = function (hash, network) { | |
var info = Address._transformHash(hash); | |
return new Address(info.hashBuffer, network, Address.PayToPublicKeyHash); | |
}; | |
/** | |
* Instantiate an address from a ripemd160 script hash | |
* | |
* @param {Buffer} hash - An instance of buffer of the hash | |
* @param {String|Network} network - either a Network instance, 'livenet', or 'testnet' | |
* @returns {Address} A new valid and frozen instance of an Address | |
*/ | |
Address.fromScriptHash = function (hash, network) { | |
$.checkArgument(hash, 'hash parameter is required'); | |
var info = Address._transformHash(hash); | |
return new Address(info.hashBuffer, network, Address.PayToScriptHash); | |
}; | |
/** | |
* Builds a p2sh address paying to script. This will hash the script and | |
* use that to create the address. | |
* If you want to extract an address associated with a script instead, | |
* see {{Address#fromScript}} | |
* | |
* @param {Script} script - An instance of Script | |
* @param {String|Network} network - either a Network instance, 'livenet', or 'testnet' | |
* @returns {Address} A new valid and frozen instance of an Address | |
*/ | |
Address.payingTo = function (script, network) { | |
$.checkArgument(script, 'script is required'); | |
$.checkArgument(script instanceof Script, 'script must be instance of Script'); | |
return Address.fromScriptHash(Hash.sha256ripemd160(script.toBuffer()), network); | |
}; | |
/** | |
* Extract address from a Script. The script must be of one | |
* of the following types: p2pkh input, p2pkh output, p2sh input | |
* or p2sh output. | |
* This will analyze the script and extract address information from it. | |
* If you want to transform any script to a p2sh Address paying | |
* to that script's hash instead, use {{Address#payingTo}} | |
* | |
* @param {Script} script - An instance of Script | |
* @param {String|Network} network - either a Network instance, 'livenet', or 'testnet' | |
* @returns {Address} A new valid and frozen instance of an Address | |
*/ | |
Address.fromScript = function (script, network) { | |
$.checkArgument(script instanceof Script, 'script must be a Script instance'); | |
var info = Address._transformScript(script, network); | |
return new Address(info.hashBuffer, network, info.type); | |
}; | |
/** | |
* Instantiate an address from a buffer of the address | |
* | |
* @param {Buffer} buffer - An instance of buffer of the address | |
* @param {String|Network=} network - either a Network instance, 'livenet', or 'testnet' | |
* @param {string=} type - The type of address: 'script' or 'pubkey' | |
* @returns {Address} A new valid and frozen instance of an Address | |
*/ | |
Address.fromBuffer = function (buffer, network, type) { | |
var info = Address._transformBuffer(buffer, network, type); | |
return new Address(info.hashBuffer, info.network, info.type); | |
}; | |
/** | |
* Instantiate an address from an address string | |
* | |
* @param {string} str - An string of the bitcoin address | |
* @param {String|Network=} network - either a Network instance, 'livenet', or 'testnet' | |
* @param {string=} type - The type of address: 'script' or 'pubkey' | |
* @returns {Address} A new valid and frozen instance of an Address | |
*/ | |
Address.fromString = function (str, network, type) { | |
var info = Address._transformString(str, network, type); | |
return new Address(info.hashBuffer, info.network, info.type); | |
}; | |
/** | |
* Instantiate an address from an Object | |
* | |
* @param {string} json - An JSON string or Object with keys: hash, network and type | |
* @returns {Address} A new valid instance of an Address | |
*/ | |
Address.fromObject = function fromObject(obj) { | |
$.checkState(JSUtil.isHexa(obj.hash), 'Unexpected hash property, "' + obj.hash + '", expected to be hex.'); | |
var hashBuffer = new Buffer(obj.hash, 'hex'); | |
return new Address(hashBuffer, obj.network, obj.type); | |
}; | |
/** | |
* Will return a validation error if exists | |
* | |
* @example | |
* ```javascript | |
* // a network mismatch error | |
* var error = Address.getValidationError('15vkcKf7gB23wLAnZLmbVuMiiVDc1Nm4a2', 'testnet'); | |
* ``` | |
* | |
* @param {string} data - The encoded data | |
* @param {String|Network} network - either a Network instance, 'livenet', or 'testnet' | |
* @param {string} type - The type of address: 'script' or 'pubkey' | |
* @returns {null|Error} The corresponding error message | |
*/ | |
Address.getValidationError = function (data, network, type) { | |
var error; | |
try { | |
/* jshint nonew: false */ | |
new Address(data, network, type); | |
} catch (e) { | |
error = e; | |
} | |
return error; | |
}; | |
/** | |
* Will return a boolean if an address is valid | |
* | |
* @example | |
* ```javascript | |
* assert(Address.isValid('15vkcKf7gB23wLAnZLmbVuMiiVDc1Nm4a2', 'livenet')); | |
* ``` | |
* | |
* @param {string} data - The encoded data | |
* @param {String|Network} network - either a Network instance, 'livenet', or 'testnet' | |
* @param {string} type - The type of address: 'script' or 'pubkey' | |
* @returns {boolean} The corresponding error message | |
*/ | |
Address.isValid = function (data, network, type) { | |
return !Address.getValidationError(data, network, type); | |
}; | |
/** | |
* Returns true if an address is of pay to public key hash type | |
* @return boolean | |
*/ | |
Address.prototype.isPayToPublicKeyHash = function () { | |
return this.type === Address.PayToPublicKeyHash; | |
}; | |
/** | |
* Returns true if an address is of pay to script hash type | |
* @return boolean | |
*/ | |
Address.prototype.isPayToScriptHash = function () { | |
return this.type === Address.PayToScriptHash; | |
}; | |
/** | |
* Will return a buffer representation of the address | |
* | |
* @returns {Buffer} Bitcoin address buffer | |
*/ | |
Address.prototype.toBuffer = function () { | |
var version = new Buffer([this.network[this.type]]); | |
var buf = Buffer.concat([version, this.hashBuffer]); | |
return buf; | |
}; | |
/** | |
* @returns {Object} A plain object with the address information | |
*/ | |
Address.prototype.toObject = Address.prototype.toJSON = function toObject() { | |
return { | |
hash: this.hashBuffer.toString('hex'), | |
type: this.type, | |
network: this.network.toString() | |
}; | |
}; | |
/** | |
* Will return a the string representation of the address | |
* | |
* @returns {string} Bitcoin address | |
*/ | |
Address.prototype.toString = function () { | |
return Base58Check.encode(this.toBuffer()); | |
}; | |
/** | |
* Will return a string formatted for the console | |
* | |
* @returns {string} Bitcoin address | |
*/ | |
Address.prototype.inspect = function () { | |
return '<Address: ' + this.toString() + ', type: ' + this.type + ', network: ' + this.network + '>'; | |
}; | |
module.exports = Address; | |
var Script = require('./script'); | |
}).call(this,require("buffer").Buffer) | |
},{"./crypto/hash":34,"./encoding/base58check":39,"./errors":43,"./networks":47,"./publickey":50,"./script":51,"./util/js":69,"./util/preconditions":70,"buffer":148,"lodash":267}],28:[function(require,module,exports){ | |
(function (Buffer){ | |
'use strict'; | |
var _ = require('lodash'); | |
var BlockHeader = require('./blockheader'); | |
var BN = require('../crypto/bn'); | |
var BufferUtil = require('../util/buffer'); | |
var BufferReader = require('../encoding/bufferreader'); | |
var BufferWriter = require('../encoding/bufferwriter'); | |
var Hash = require('../crypto/hash'); | |
var Transaction = require('../transaction'); | |
var $ = require('../util/preconditions'); | |
/** | |
* Instantiate a Block from a Buffer, JSON object, or Object with | |
* the properties of the Block | |
* | |
* @param {*} - A Buffer, JSON string, or Object | |
* @returns {Block} | |
* @constructor | |
*/ | |
function Block(arg) { | |
if (!(this instanceof Block)) { | |
return new Block(arg); | |
} | |
_.extend(this, Block._from(arg)); | |
return this; | |
} | |
// https://github.com/bitcoin/bitcoin/blob/b5fa132329f0377d787a4a21c1686609c2bfaece/src/primitives/block.h#L14 | |
Block.MAX_BLOCK_SIZE = 1000000; | |
/** | |
* @param {*} - A Buffer, JSON string or Object | |
* @returns {Object} - An object representing block data | |
* @throws {TypeError} - If the argument was not recognized | |
* @private | |
*/ | |
Block._from = function _from(arg) { | |
var info = {}; | |
if (BufferUtil.isBuffer(arg)) { | |
info = Block._fromBufferReader(BufferReader(arg)); | |
} else if (_.isObject(arg)) { | |
info = Block._fromObject(arg); | |
} else { | |
throw new TypeError('Unrecognized argument for Block'); | |
} | |
return info; | |
}; | |
/** | |
* @param {Object} - A plain JavaScript object | |
* @returns {Object} - An object representing block data | |
* @private | |
*/ | |
Block._fromObject = function _fromObject(data) { | |
var transactions = []; | |
data.transactions.forEach(function (tx) { | |
if (tx instanceof Transaction) { | |
transactions.push(tx); | |
} else { | |
transactions.push(Transaction().fromObject(tx)); | |
} | |
}); | |
var info = { | |
header: BlockHeader.fromObject(data.header), | |
transactions: transactions | |
}; | |
return info; | |
}; | |
/** | |
* @param {Object} - A plain JavaScript object | |
* @returns {Block} - An instance of block | |
*/ | |
Block.fromObject = function fromObject(obj) { | |
var info = Block._fromObject(obj); | |
return new Block(info); | |
}; | |
/** | |
* @param {BufferReader} - Block data | |
* @returns {Object} - An object representing the block data | |
* @private | |
*/ | |
Block._fromBufferReader = function _fromBufferReader(br) { | |
var info = {}; | |
$.checkState(!br.finished(), 'No block data received'); | |
info.header = BlockHeader.fromBufferReader(br); | |
var transactions = br.readVarintNum(); | |
info.transactions = []; | |
for (var i = 0; i < transactions; i++) { | |
info.transactions.push(Transaction().fromBufferReader(br)); | |
} | |
return info; | |
}; | |
/** | |
* @param {BufferReader} - A buffer reader of the block | |
* @returns {Block} - An instance of block | |
*/ | |
Block.fromBufferReader = function fromBufferReader(br) { | |
$.checkArgument(br, 'br is required'); | |
var info = Block._fromBufferReader(br); | |
return new Block(info); | |
}; | |
/** | |
* @param {Buffer} - A buffer of the block | |
* @returns {Block} - An instance of block | |
*/ | |
Block.fromBuffer = function fromBuffer(buf) { | |
return Block.fromBufferReader(new BufferReader(buf)); | |
}; | |
/** | |
* @param {string} - str - A hex encoded string of the block | |
* @returns {Block} - A hex encoded string of the block | |
*/ | |
Block.fromString = function fromString(str) { | |
var buf = new Buffer(str, 'hex'); | |
return Block.fromBuffer(buf); | |
}; | |
/** | |
* @param {Binary} - Raw block binary data or buffer | |
* @returns {Block} - An instance of block | |
*/ | |
Block.fromRawBlock = function fromRawBlock(data) { | |
if (!BufferUtil.isBuffer(data)) { | |
data = new Buffer(data, 'binary'); | |
} | |
var br = BufferReader(data); | |
br.pos = Block.Values.START_OF_BLOCK; | |
var info = Block._fromBufferReader(br); | |
return new Block(info); | |
}; | |
/** | |
* @returns {Object} - A plain object with the block properties | |
*/ | |
Block.prototype.toObject = Block.prototype.toJSON = function toObject() { | |
var transactions = []; | |
this.transactions.forEach(function (tx) { | |
transactions.push(tx.toObject()); | |
}); | |
return { | |
header: this.header.toObject(), | |
transactions: transactions | |
}; | |
}; | |
/** | |
* @returns {Buffer} - A buffer of the block | |
*/ | |
Block.prototype.toBuffer = function toBuffer() { | |
return this.toBufferWriter().concat(); | |
}; | |
/** | |
* @returns {string} - A hex encoded string of the block | |
*/ | |
Block.prototype.toString = function toString() { | |
return this.toBuffer().toString('hex'); | |
}; | |
/** | |
* @param {BufferWriter} - An existing instance of BufferWriter | |
* @returns {BufferWriter} - An instance of BufferWriter representation of the Block | |
*/ | |
Block.prototype.toBufferWriter = function toBufferWriter(bw) { | |
if (!bw) { | |
bw = new BufferWriter(); | |
} | |
bw.write(this.header.toBuffer()); | |
bw.writeVarintNum(this.transactions.length); | |
for (var i = 0; i < this.transactions.length; i++) { | |
this.transactions[i].toBufferWriter(bw); | |
} | |
return bw; | |
}; | |
/** | |
* Will iterate through each transaction and return an array of hashes | |
* @returns {Array} - An array with transaction hashes | |
*/ | |
Block.prototype.getTransactionHashes = function getTransactionHashes() { | |
var hashes = []; | |
if (this.transactions.length === 0) { | |
return [Block.Values.NULL_HASH]; | |
} | |
for (var t = 0; t < this.transactions.length; t++) { | |
hashes.push(this.transactions[t]._getHash()); | |
} | |
return hashes; | |
}; | |
/** | |
* Will build a merkle tree of all the transactions, ultimately arriving at | |
* a single point, the merkle root. | |
* @link https://en.bitcoin.it/wiki/Protocol_specification#Merkle_Trees | |
* @returns {Array} - An array with each level of the tree after the other. | |
*/ | |
Block.prototype.getMerkleTree = function getMerkleTree() { | |
var tree = this.getTransactionHashes(); | |
var j = 0; | |
for (var size = this.transactions.length; size > 1; size = Math.floor((size + 1) / 2)) { | |
for (var i = 0; i < size; i += 2) { | |
var i2 = Math.min(i + 1, size - 1); | |
var buf = Buffer.concat([tree[j + i], tree[j + i2]]); | |
tree.push(Hash.sha256sha256(buf)); | |
} | |
j += size; | |
} | |
return tree; | |
}; | |
/** | |
* Calculates the merkleRoot from the transactions. | |
* @returns {Buffer} - A buffer of the merkle root hash | |
*/ | |
Block.prototype.getMerkleRoot = function getMerkleRoot() { | |
var tree = this.getMerkleTree(); | |
return tree[tree.length - 1]; | |
}; | |
/** | |
* Verifies that the transactions in the block match the header merkle root | |
* @returns {Boolean} - If the merkle roots match | |
*/ | |
Block.prototype.validMerkleRoot = function validMerkleRoot() { | |
var h = new BN(this.header.merkleRoot.toString('hex'), 'hex'); | |
var c = new BN(this.getMerkleRoot().toString('hex'), 'hex'); | |
if (h.cmp(c) !== 0) { | |
return false; | |
} | |
return true; | |
}; | |
/** | |
* @returns {Buffer} - The little endian hash buffer of the header | |
*/ | |
Block.prototype._getHash = function () { | |
return this.header._getHash(); | |
}; | |
var idProperty = { | |
configurable: false, | |
enumerable: true, | |
/** | |
* @returns {string} - The big endian hash buffer of the header | |
*/ | |
get: function get() { | |
if (!this._id) { | |
this._id = this.header.id; | |
} | |
return this._id; | |
}, | |
set: _.noop | |
}; | |
Object.defineProperty(Block.prototype, 'id', idProperty); | |
Object.defineProperty(Block.prototype, 'hash', idProperty); | |
/** | |
* @returns {string} - A string formatted for the console | |
*/ | |
Block.prototype.inspect = function inspect() { | |
return '<Block ' + this.id + '>'; | |
}; | |
Block.Values = { | |
START_OF_BLOCK: 8, // Start of block in raw block data | |
NULL_HASH: new Buffer('0000000000000000000000000000000000000000000000000000000000000000', 'hex') | |
}; | |
module.exports = Block; | |
}).call(this,require("buffer").Buffer) | |
},{"../crypto/bn":32,"../crypto/hash":34,"../encoding/bufferreader":40,"../encoding/bufferwriter":41,"../transaction":54,"../util/buffer":68,"../util/preconditions":70,"./blockheader":29,"buffer":148,"lodash":267}],29:[function(require,module,exports){ | |
(function (Buffer){ | |
'use strict'; | |
var _ = require('lodash'); | |
var BN = require('../crypto/bn'); | |
var BufferUtil = require('../util/buffer'); | |
var BufferReader = require('../encoding/bufferreader'); | |
var BufferWriter = require('../encoding/bufferwriter'); | |
var Hash = require('../crypto/hash'); | |
var JSUtil = require('../util/js'); | |
var $ = require('../util/preconditions'); | |
var GENESIS_BITS = 0x1d00ffff; | |
/** | |
* Instantiate a BlockHeader from a Buffer, JSON object, or Object with | |
* the properties of the BlockHeader | |
* | |
* @param {*} - A Buffer, JSON string, or Object | |
* @returns {BlockHeader} - An instance of block header | |
* @constructor | |
*/ | |
var BlockHeader = function BlockHeader(arg) { | |
if (!(this instanceof BlockHeader)) { | |
return new BlockHeader(arg); | |
} | |
var info = BlockHeader._from(arg); | |
this.version = info.version; | |
this.prevHash = info.prevHash; | |
this.merkleRoot = info.merkleRoot; | |
this.time = info.time; | |
this.timestamp = info.time; | |
this.bits = info.bits; | |
this.nonce = info.nonce; | |
if (info.hash) { | |
$.checkState(this.hash === info.hash, 'Argument object hash property does not match block hash.'); | |
} | |
return this; | |
}; | |
/** | |
* @param {*} - A Buffer, JSON string or Object | |
* @returns {Object} - An object representing block header data | |
* @throws {TypeError} - If the argument was not recognized | |
* @private | |
*/ | |
BlockHeader._from = function _from(arg) { | |
var info = {}; | |
if (BufferUtil.isBuffer(arg)) { | |
info = BlockHeader._fromBufferReader(BufferReader(arg)); | |
} else if (_.isObject(arg)) { | |
info = BlockHeader._fromObject(arg); | |
} else { | |
throw new TypeError('Unrecognized argument for BlockHeader'); | |
} | |
return info; | |
}; | |
/** | |
* @param {Object} - A JSON string | |
* @returns {Object} - An object representing block header data | |
* @private | |
*/ | |
BlockHeader._fromObject = function _fromObject(data) { | |
$.checkArgument(data, 'data is required'); | |
var prevHash = data.prevHash; | |
var merkleRoot = data.merkleRoot; | |
if (_.isString(data.prevHash)) { | |
prevHash = BufferUtil.reverse(new Buffer(data.prevHash, 'hex')); | |
} | |
if (_.isString(data.merkleRoot)) { | |
merkleRoot = BufferUtil.reverse(new Buffer(data.merkleRoot, 'hex')); | |
} | |
var info = { | |
hash: data.hash, | |
version: data.version, | |
prevHash: prevHash, | |
merkleRoot: merkleRoot, | |
time: data.time, | |
timestamp: data.time, | |
bits: data.bits, | |
nonce: data.nonce | |
}; | |
return info; | |
}; | |
/** | |
* @param {Object} - A plain JavaScript object | |
* @returns {BlockHeader} - An instance of block header | |
*/ | |
BlockHeader.fromObject = function fromObject(obj) { | |
var info = BlockHeader._fromObject(obj); | |
return new BlockHeader(info); | |
}; | |
/** | |
* @param {Binary} - Raw block binary data or buffer | |
* @returns {BlockHeader} - An instance of block header | |
*/ | |
BlockHeader.fromRawBlock = function fromRawBlock(data) { | |
if (!BufferUtil.isBuffer(data)) { | |
data = new Buffer(data, 'binary'); | |
} | |
var br = BufferReader(data); | |
br.pos = BlockHeader.Constants.START_OF_HEADER; | |
var info = BlockHeader._fromBufferReader(br); | |
return new BlockHeader(info); | |
}; | |
/** | |
* @param {Buffer} - A buffer of the block header | |
* @returns {BlockHeader} - An instance of block header | |
*/ | |
BlockHeader.fromBuffer = function fromBuffer(buf) { | |
var info = BlockHeader._fromBufferReader(BufferReader(buf)); | |
return new BlockHeader(info); | |
}; | |
/** | |
* @param {string} - A hex encoded buffer of the block header | |
* @returns {BlockHeader} - An instance of block header | |
*/ | |
BlockHeader.fromString = function fromString(str) { | |
var buf = new Buffer(str, 'hex'); | |
return BlockHeader.fromBuffer(buf); | |
}; | |
/** | |
* @param {BufferReader} - A BufferReader of the block header | |
* @returns {Object} - An object representing block header data | |
* @private | |
*/ | |
BlockHeader._fromBufferReader = function _fromBufferReader(br) { | |
var info = {}; | |
info.version = br.readInt32LE(); | |
info.prevHash = br.read(32); | |
info.merkleRoot = br.read(32); | |
info.time = br.readUInt32LE(); | |
info.bits = br.readUInt32LE(); | |
info.nonce = br.readUInt32LE(); | |
return info; | |
}; | |
/** | |
* @param {BufferReader} - A BufferReader of the block header | |
* @returns {BlockHeader} - An instance of block header | |
*/ | |
BlockHeader.fromBufferReader = function fromBufferReader(br) { | |
var info = BlockHeader._fromBufferReader(br); | |
return new BlockHeader(info); | |
}; | |
/** | |
* @returns {Object} - A plain object of the BlockHeader | |
*/ | |
BlockHeader.prototype.toObject = BlockHeader.prototype.toJSON = function toObject() { | |
return { | |
hash: this.hash, | |
version: this.version, | |
prevHash: BufferUtil.reverse(this.prevHash).toString('hex'), | |
merkleRoot: BufferUtil.reverse(this.merkleRoot).toString('hex'), | |
time: this.time, | |
bits: this.bits, | |
nonce: this.nonce | |
}; | |
}; | |
/** | |
* @returns {Buffer} - A Buffer of the BlockHeader | |
*/ | |
BlockHeader.prototype.toBuffer = function toBuffer() { | |
return this.toBufferWriter().concat(); | |
}; | |
/** | |
* @returns {string} - A hex encoded string of the BlockHeader | |
*/ | |
BlockHeader.prototype.toString = function toString() { | |
return this.toBuffer().toString('hex'); | |
}; | |
/** | |
* @param {BufferWriter} - An existing instance BufferWriter | |
* @returns {BufferWriter} - An instance of BufferWriter representation of the BlockHeader | |
*/ | |
BlockHeader.prototype.toBufferWriter = function toBufferWriter(bw) { | |
if (!bw) { | |
bw = new BufferWriter(); | |
} | |
bw.writeInt32LE(this.version); | |
bw.write(this.prevHash); | |
bw.write(this.merkleRoot); | |
bw.writeUInt32LE(this.time); | |
bw.writeUInt32LE(this.bits); | |
bw.writeUInt32LE(this.nonce); | |
return bw; | |
}; | |
/** | |
* Returns the target difficulty for this block | |
* @param {Number} bits | |
* @returns {BN} An instance of BN with the decoded difficulty bits | |
*/ | |
BlockHeader.prototype.getTargetDifficulty = function getTargetDifficulty(bits) { | |
bits = bits || this.bits; | |
var target = new BN(bits & 0xffffff); | |
var mov = 8 * ((bits >>> 24) - 3); | |
while (mov-- > 0) { | |
target = target.mul(new BN(2)); | |
} | |
return target; | |
}; | |
/** | |
* @link https://en.bitcoin.it/wiki/Difficulty | |
* @return {Number} | |
*/ | |
BlockHeader.prototype.getDifficulty = function getDifficulty() { | |
var difficulty1TargetBN = this.getTargetDifficulty(GENESIS_BITS).mul(new BN(Math.pow(10, 8))); | |
var currentTargetBN = this.getTargetDifficulty(); | |
var difficultyString = difficulty1TargetBN.div(currentTargetBN).toString(10); | |
var decimalPos = difficultyString.length - 8; | |
difficultyString = difficultyString.slice(0, decimalPos) + '.' + difficultyString.slice(decimalPos); | |
return parseFloat(difficultyString); | |
}; | |
/** | |
* @returns {Buffer} - The little endian hash buffer of the header | |
*/ | |
BlockHeader.prototype._getHash = function hash() { | |
var buf = this.toBuffer(); | |
return Hash.sha256sha256(buf); | |
}; | |
var idProperty = { | |
configurable: false, | |
enumerable: true, | |
/** | |
* @returns {string} - The big endian hash buffer of the header | |
*/ | |
get: function get() { | |
if (!this._id) { | |
this._id = BufferReader(this._getHash()).readReverse().toString('hex'); | |
} | |
return this._id; | |
}, | |
set: _.noop | |
}; | |
Object.defineProperty(BlockHeader.prototype, 'id', idProperty); | |
Object.defineProperty(BlockHeader.prototype, 'hash', idProperty); | |
/** | |
* @returns {Boolean} - If timestamp is not too far in the future | |
*/ | |
BlockHeader.prototype.validTimestamp = function validTimestamp() { | |
var currentTime = Math.round(new Date().getTime() / 1000); | |
if (this.time > currentTime + BlockHeader.Constants.MAX_TIME_OFFSET) { | |
return false; | |
} | |
return true; | |
}; | |
/** | |
* @returns {Boolean} - If the proof-of-work hash satisfies the target difficulty | |
*/ | |
BlockHeader.prototype.validProofOfWork = function validProofOfWork() { | |
var pow = new BN(this.id, 'hex'); | |
var target = this.getTargetDifficulty(); | |
if (pow.cmp(target) > 0) { | |
return false; | |
} | |
return true; | |
}; | |
/** | |
* @returns {string} - A string formatted for the console | |
*/ | |
BlockHeader.prototype.inspect = function inspect() { | |
return '<BlockHeader ' + this.id + '>'; | |
}; | |
BlockHeader.Constants = { | |
START_OF_HEADER: 8, // Start buffer position in raw block data | |
MAX_TIME_OFFSET: 2 * 60 * 60, // The max a timestamp can be in the future | |
LARGEST_HASH: new BN('10000000000000000000000000000000000000000000000000000000000000000', 'hex') | |
}; | |
module.exports = BlockHeader; | |
}).call(this,require("buffer").Buffer) | |
},{"../crypto/bn":32,"../crypto/hash":34,"../encoding/bufferreader":40,"../encoding/bufferwriter":41,"../util/buffer":68,"../util/js":69,"../util/preconditions":70,"buffer":148,"lodash":267}],30:[function(require,module,exports){ | |
'use strict'; | |
module.exports = require('./block'); | |
module.exports.BlockHeader = require('./blockheader'); | |
module.exports.MerkleBlock = require('./merkleblock'); | |
},{"./block":28,"./blockheader":29,"./merkleblock":31}],31:[function(require,module,exports){ | |
(function (Buffer){ | |
'use strict'; | |
var _ = require('lodash'); | |
var BlockHeader = require('./blockheader'); | |
var BufferUtil = require('../util/buffer'); | |
var BufferReader = require('../encoding/bufferreader'); | |
var BufferWriter = require('../encoding/bufferwriter'); | |
var Hash = require('../crypto/hash'); | |
var JSUtil = require('../util/js'); | |
var Transaction = require('../transaction'); | |
var errors = require('../errors'); | |
var $ = require('../util/preconditions'); | |
/** | |
* Instantiate a MerkleBlock from a Buffer, JSON object, or Object with | |
* the properties of the Block | |
* | |
* @param {*} - A Buffer, JSON string, or Object representing a MerkleBlock | |
* @returns {MerkleBlock} | |
* @constructor | |
*/ | |
function MerkleBlock(arg) { | |
/* jshint maxstatements: 18 */ | |
if (!(this instanceof MerkleBlock)) { | |
return new MerkleBlock(arg); | |
} | |
var info = {}; | |
if (BufferUtil.isBuffer(arg)) { | |
info = MerkleBlock._fromBufferReader(BufferReader(arg)); | |
} else if (_.isObject(arg)) { | |
var header; | |
if (arg.header instanceof BlockHeader) { | |
header = arg.header; | |
} else { | |
header = BlockHeader.fromObject(arg.header); | |
} | |
info = { | |
/** | |
* @name MerkleBlock#header | |
* @type {BlockHeader} | |
*/ | |
header: header, | |
/** | |
* @name MerkleBlock#numTransactions | |
* @type {Number} | |
*/ | |
numTransactions: arg.numTransactions, | |
/** | |
* @name MerkleBlock#hashes | |
* @type {String[]} | |
*/ | |
hashes: arg.hashes, | |
/** | |
* @name MerkleBlock#flags | |
* @type {Number[]} | |
*/ | |
flags: arg.flags | |
}; | |
} else { | |
throw new TypeError('Unrecognized argument for MerkleBlock'); | |
} | |
_.extend(this, info); | |
this._flagBitsUsed = 0; | |
this._hashesUsed = 0; | |
return this; | |
} | |
/** | |
* @param {Buffer} - MerkleBlock data in a Buffer object | |
* @returns {MerkleBlock} - A MerkleBlock object | |
*/ | |
MerkleBlock.fromBuffer = function fromBuffer(buf) { | |
return MerkleBlock.fromBufferReader(BufferReader(buf)); | |
}; | |
/** | |
* @param {BufferReader} - MerkleBlock data in a BufferReader object | |
* @returns {MerkleBlock} - A MerkleBlock object | |
*/ | |
MerkleBlock.fromBufferReader = function fromBufferReader(br) { | |
return new MerkleBlock(MerkleBlock._fromBufferReader(br)); | |
}; | |
/** | |
* @returns {Buffer} - A buffer of the block | |
*/ | |
MerkleBlock.prototype.toBuffer = function toBuffer() { | |
return this.toBufferWriter().concat(); | |
}; | |
/** | |
* @param {BufferWriter} - An existing instance of BufferWriter | |
* @returns {BufferWriter} - An instance of BufferWriter representation of the MerkleBlock | |
*/ | |
MerkleBlock.prototype.toBufferWriter = function toBufferWriter(bw) { | |
if (!bw) { | |
bw = new BufferWriter(); | |
} | |
bw.write(this.header.toBuffer()); | |
bw.writeUInt32LE(this.numTransactions); | |
bw.writeVarintNum(this.hashes.length); | |
for (var i = 0; i < this.hashes.length; i++) { | |
bw.write(new Buffer(this.hashes[i], 'hex')); | |
} | |
bw.writeVarintNum(this.flags.length); | |
for (i = 0; i < this.flags.length; i++) { | |
bw.writeUInt8(this.flags[i]); | |
} | |
return bw; | |
}; | |
/** | |
* @returns {Object} - A plain object with the MerkleBlock properties | |
*/ | |
MerkleBlock.prototype.toObject = MerkleBlock.prototype.toJSON = function toObject() { | |
return { | |
header: this.header.toObject(), | |
numTransactions: this.numTransactions, | |
hashes: this.hashes, | |
flags: this.flags | |
}; | |
}; | |
/** | |
* Verify that the MerkleBlock is valid | |
* @returns {Boolean} - True/False whether this MerkleBlock is Valid | |
*/ | |
MerkleBlock.prototype.validMerkleTree = function validMerkleTree() { | |
$.checkState(_.isArray(this.flags), 'MerkleBlock flags is not an array'); | |
$.checkState(_.isArray(this.hashes), 'MerkleBlock hashes is not an array'); | |
// Can't have more hashes than numTransactions | |
if (this.hashes.length > this.numTransactions) { | |
return false; | |
} | |
// Can't have more flag bits than num hashes | |
if (this.flags.length * 8 < this.hashes.length) { | |
return false; | |
} | |
var height = this._calcTreeHeight(); | |
var opts = { hashesUsed: 0, flagBitsUsed: 0 }; | |
var root = this._traverseMerkleTree(height, 0, opts); | |
if (opts.hashesUsed !== this.hashes.length) { | |
return false; | |
} | |
return BufferUtil.equals(root, this.header.merkleRoot); | |
}; | |
/** | |
* Return a list of all the txs hash that match the filter | |
* @returns {Array} - txs hash that match the filter | |
*/ | |
MerkleBlock.prototype.filterdTxsHash = function filterdTxsHash() { | |
$.checkState(_.isArray(this.flags), 'MerkleBlock flags is not an array'); | |
$.checkState(_.isArray(this.hashes), 'MerkleBlock hashes is not an array'); | |
// Can't have more hashes than numTransactions | |
if (this.hashes.length > this.numTransactions) { | |
throw new errors.MerkleBlock.InvalidMerkleTree(); | |
} | |
// Can't have more flag bits than num hashes | |
if (this.flags.length * 8 < this.hashes.length) { | |
throw new errors.MerkleBlock.InvalidMerkleTree(); | |
} | |
// If there is only one hash the filter do not match any txs in the block | |
if (this.hashes.length === 1) { | |
return []; | |
}; | |
var height = this._calcTreeHeight(); | |
var opts = { hashesUsed: 0, flagBitsUsed: 0 }; | |
var txs = this._traverseMerkleTree(height, 0, opts, true); | |
if (opts.hashesUsed !== this.hashes.length) { | |
throw new errors.MerkleBlock.InvalidMerkleTree(); | |
} | |
return txs; | |
}; | |
/** | |
* Traverse a the tree in this MerkleBlock, validating it along the way | |
* Modeled after Bitcoin Core merkleblock.cpp TraverseAndExtract() | |
* @param {Number} - depth - Current height | |
* @param {Number} - pos - Current position in the tree | |
* @param {Object} - opts - Object with values that need to be mutated throughout the traversal | |
* @param {Boolean} - checkForTxs - if true return opts.txs else return the Merkle Hash | |
* @param {Number} - opts.flagBitsUsed - Number of flag bits used, should start at 0 | |
* @param {Number} - opts.hashesUsed - Number of hashes used, should start at 0 | |
* @param {Array} - opts.txs - Will finish populated by transactions found during traversal that match the filter | |
* @returns {Buffer|null} - Buffer containing the Merkle Hash for that height | |
* @returns {Array} - transactions found during traversal that match the filter | |
* @private | |
*/ | |
MerkleBlock.prototype._traverseMerkleTree = function traverseMerkleTree(depth, pos, opts, checkForTxs) { | |
/* jshint maxcomplexity: 12*/ | |
/* jshint maxstatements: 20 */ | |
opts = opts || {}; | |
opts.txs = opts.txs || []; | |
opts.flagBitsUsed = opts.flagBitsUsed || 0; | |
opts.hashesUsed = opts.hashesUsed || 0; | |
var checkForTxs = checkForTxs || false; | |
if (opts.flagBitsUsed > this.flags.length * 8) { | |
return null; | |
} | |
var isParentOfMatch = this.flags[opts.flagBitsUsed >> 3] >>> (opts.flagBitsUsed++ & 7) & 1; | |
if (depth === 0 || !isParentOfMatch) { | |
if (opts.hashesUsed >= this.hashes.length) { | |
return null; | |
} | |
var hash = this.hashes[opts.hashesUsed++]; | |
if (depth === 0 && isParentOfMatch) { | |
opts.txs.push(hash); | |
} | |
return new Buffer(hash, 'hex'); | |
} else { | |
var left = this._traverseMerkleTree(depth - 1, pos * 2, opts); | |
var right = left; | |
if (pos * 2 + 1 < this._calcTreeWidth(depth - 1)) { | |
right = this._traverseMerkleTree(depth - 1, pos * 2 + 1, opts); | |
} | |
if (checkForTxs) { | |
return opts.txs; | |
} else { | |
return Hash.sha256sha256(new Buffer.concat([left, right])); | |
}; | |
} | |
}; | |
/** Calculates the width of a merkle tree at a given height. | |
* Modeled after Bitcoin Core merkleblock.h CalcTreeWidth() | |
* @param {Number} - Height at which we want the tree width | |
* @returns {Number} - Width of the tree at a given height | |
* @private | |
*/ | |
MerkleBlock.prototype._calcTreeWidth = function calcTreeWidth(height) { | |
return this.numTransactions + (1 << height) - 1 >> height; | |
}; | |
/** Calculates the height of the merkle tree in this MerkleBlock | |
* @param {Number} - Height at which we want the tree width | |
* @returns {Number} - Height of the merkle tree in this MerkleBlock | |
* @private | |
*/ | |
MerkleBlock.prototype._calcTreeHeight = function calcTreeHeight() { | |
var height = 0; | |
while (this._calcTreeWidth(height) > 1) { | |
height++; | |
} | |
return height; | |
}; | |
/** | |
* @param {Transaction|String} - Transaction or Transaction ID Hash | |
* @returns {Boolean} - return true/false if this MerkleBlock has the TX or not | |
* @private | |
*/ | |
MerkleBlock.prototype.hasTransaction = function hasTransaction(tx) { | |
$.checkArgument(!_.isUndefined(tx), 'tx cannot be undefined'); | |
$.checkArgument(tx instanceof Transaction || typeof tx === 'string', 'Invalid tx given, tx must be a "string" or "Transaction"'); | |
var hash = tx; | |
if (tx instanceof Transaction) { | |
// We need to reverse the id hash for the lookup | |
hash = BufferUtil.reverse(new Buffer(tx.id, 'hex')).toString('hex'); | |
} | |
var txs = []; | |
var height = this._calcTreeHeight(); | |
this._traverseMerkleTree(height, 0, { txs: txs }); | |
return txs.indexOf(hash) !== -1; | |
}; | |
/** | |
* @param {Buffer} - MerkleBlock data | |
* @returns {Object} - An Object representing merkleblock data | |
* @private | |
*/ | |
MerkleBlock._fromBufferReader = function _fromBufferReader(br) { | |
$.checkState(!br.finished(), 'No merkleblock data received'); | |
var info = {}; | |
info.header = BlockHeader.fromBufferReader(br); | |
info.numTransactions = br.readUInt32LE(); | |
var numHashes = br.readVarintNum(); | |
info.hashes = []; | |
for (var i = 0; i < numHashes; i++) { | |
info.hashes.push(br.read(32).toString('hex')); | |
} | |
var numFlags = br.readVarintNum(); | |
info.flags = []; | |
for (i = 0; i < numFlags; i++) { | |
info.flags.push(br.readUInt8()); | |
} | |
return info; | |
}; | |
/** | |
* @param {Object} - A plain JavaScript object | |
* @returns {Block} - An instance of block | |
*/ | |
MerkleBlock.fromObject = function fromObject(obj) { | |
return new MerkleBlock(obj); | |
}; | |
module.exports = MerkleBlock; | |
}).call(this,require("buffer").Buffer) | |
},{"../crypto/hash":34,"../encoding/bufferreader":40,"../encoding/bufferwriter":41,"../errors":43,"../transaction":54,"../util/buffer":68,"../util/js":69,"../util/preconditions":70,"./blockheader":29,"buffer":148,"lodash":267}],32:[function(require,module,exports){ | |
(function (Buffer){ | |
'use strict'; | |
var BN = require('bn.js'); | |
var $ = require('../util/preconditions'); | |
var _ = require('lodash'); | |
var reversebuf = function reversebuf(buf) { | |
var buf2 = new Buffer(buf.length); | |
for (var i = 0; i < buf.length; i++) { | |
buf2[i] = buf[buf.length - 1 - i]; | |
} | |
return buf2; | |
}; | |
BN.Zero = new BN(0); | |
BN.One = new BN(1); | |
BN.Minus1 = new BN(-1); | |
BN.fromNumber = function (n) { | |
$.checkArgument(_.isNumber(n)); | |
return new BN(n); | |
}; | |
BN.fromString = function (str, base) { | |
$.checkArgument(_.isString(str)); | |
return new BN(str, base); | |
}; | |
BN.fromBuffer = function (buf, opts) { | |
if (typeof opts !== 'undefined' && opts.endian === 'little') { | |
buf = reversebuf(buf); | |
} | |
var hex = buf.toString('hex'); | |
var bn = new BN(hex, 16); | |
return bn; | |
}; | |
/** | |
* Instantiate a BigNumber from a "signed magnitude buffer" | |
* (a buffer where the most significant bit represents the sign (0 = positive, -1 = negative)) | |
*/ | |
BN.fromSM = function (buf, opts) { | |
var ret; | |
if (buf.length === 0) { | |
return BN.fromBuffer(new Buffer([0])); | |
} | |
var endian = 'big'; | |
if (opts) { | |
endian = opts.endian; | |
} | |
if (endian === 'little') { | |
buf = reversebuf(buf); | |
} | |
if (buf[0] & 0x80) { | |
buf[0] = buf[0] & 0x7f; | |
ret = BN.fromBuffer(buf); | |
ret.neg().copy(ret); | |
} else { | |
ret = BN.fromBuffer(buf); | |
} | |
return ret; | |
}; | |
BN.prototype.toNumber = function () { | |
return parseInt(this.toString(10), 10); | |
}; | |
BN.prototype.toBuffer = function (opts) { | |
var buf, hex; | |
if (opts && opts.size) { | |
hex = this.toString(16, 2); | |
var natlen = hex.length / 2; | |
buf = new Buffer(hex, 'hex'); | |
if (natlen === opts.size) { | |
buf = buf; | |
} else if (natlen > opts.size) { | |
buf = BN.trim(buf, natlen); | |
} else if (natlen < opts.size) { | |
buf = BN.pad(buf, natlen, opts.size); | |
} | |
} else { | |
hex = this.toString(16, 2); | |
buf = new Buffer(hex, 'hex'); | |
} | |
if (typeof opts !== 'undefined' && opts.endian === 'little') { | |
buf = reversebuf(buf); | |
} | |
return buf; | |
}; | |
BN.prototype.toSMBigEndian = function () { | |
var buf; | |
if (this.cmp(BN.Zero) === -1) { | |
buf = this.neg().toBuffer(); | |
if (buf[0] & 0x80) { | |
buf = Buffer.concat([new Buffer([0x80]), buf]); | |
} else { | |
buf[0] = buf[0] | 0x80; | |
} | |
} else { | |
buf = this.toBuffer(); | |
if (buf[0] & 0x80) { | |
buf = Buffer.concat([new Buffer([0x00]), buf]); | |
} | |
} | |
if (buf.length === 1 & buf[0] === 0) { | |
buf = new Buffer([]); | |
} | |
return buf; | |
}; | |
BN.prototype.toSM = function (opts) { | |
var endian = opts ? opts.endian : 'big'; | |
var buf = this.toSMBigEndian(); | |
if (endian === 'little') { | |
buf = reversebuf(buf); | |
} | |
return buf; | |
}; | |
/** | |
* Create a BN from a "ScriptNum": | |
* This is analogous to the constructor for CScriptNum in bitcoind. Many ops in | |
* bitcoind's script interpreter use CScriptNum, which is not really a proper | |
* bignum. Instead, an error is thrown if trying to input a number bigger than | |
* 4 bytes. We copy that behavior here. A third argument, `size`, is provided to | |
* extend the hard limit of 4 bytes, as some usages require more than 4 bytes. | |
*/ | |
BN.fromScriptNumBuffer = function (buf, fRequireMinimal, size) { | |
var nMaxNumSize = size || 4; | |
$.checkArgument(buf.length <= nMaxNumSize, new Error('script number overflow')); | |
if (fRequireMinimal && buf.length > 0) { | |
// Check that the number is encoded with the minimum possible | |
// number of bytes. | |
// | |
// If the most-significant-byte - excluding the sign bit - is zero | |
// then we're not minimal. Note how this test also rejects the | |
// negative-zero encoding, 0x80. | |
if ((buf[buf.length - 1] & 0x7f) === 0) { | |
// One exception: if there's more than one byte and the most | |
// significant bit of the second-most-significant-byte is set | |
// it would conflict with the sign bit. An example of this case | |
// is +-255, which encode to 0xff00 and 0xff80 respectively. | |
// (big-endian). | |
if (buf.length <= 1 || (buf[buf.length - 2] & 0x80) === 0) { | |
throw new Error('non-minimally encoded script number'); | |
} | |
} | |
} | |
return BN.fromSM(buf, { | |
endian: 'little' | |
}); | |
}; | |
/** | |
* The corollary to the above, with the notable exception that we do not throw | |
* an error if the output is larger than four bytes. (Which can happen if | |
* performing a numerical operation that results in an overflow to more than 4 | |
* bytes). | |
*/ | |
BN.prototype.toScriptNumBuffer = function () { | |
return this.toSM({ | |
endian: 'little' | |
}); | |
}; | |
BN.prototype.gt = function (b) { | |
return this.cmp(b) > 0; | |
}; | |
BN.prototype.gte = function (b) { | |
return this.cmp(b) >= 0; | |
}; | |
BN.prototype.lt = function (b) { | |
return this.cmp(b) < 0; | |
}; | |
BN.trim = function (buf, natlen) { | |
return buf.slice(natlen - buf.length, buf.length); | |
}; | |
BN.pad = function (buf, natlen, size) { | |
var rbuf = new Buffer(size); | |
for (var i = 0; i < buf.length; i++) { | |
rbuf[rbuf.length - 1 - i] = buf[buf.length - 1 - i]; | |
} | |
for (i = 0; i < size - natlen; i++) { | |
rbuf[i] = 0; | |
} | |
return rbuf; | |
}; | |
module.exports = BN; | |
}).call(this,require("buffer").Buffer) | |
},{"../util/preconditions":70,"bn.js":99,"buffer":148,"lodash":267}],33:[function(require,module,exports){ | |
(function (Buffer){ | |
'use strict'; | |
var BN = require('./bn'); | |
var Point = require('./point'); | |
var Signature = require('./signature'); | |
var PublicKey = require('../publickey'); | |
var Random = require('./random'); | |
var Hash = require('./hash'); | |
var BufferUtil = require('../util/buffer'); | |
var _ = require('lodash'); | |
var $ = require('../util/preconditions'); | |
var ECDSA = function ECDSA(obj) { | |
if (!(this instanceof ECDSA)) { | |
return new ECDSA(obj); | |
} | |
if (obj) { | |
this.set(obj); | |
} | |
}; | |
/* jshint maxcomplexity: 9 */ | |
ECDSA.prototype.set = function (obj) { | |
this.hashbuf = obj.hashbuf || this.hashbuf; | |
this.endian = obj.endian || this.endian; //the endianness of hashbuf | |
this.privkey = obj.privkey || this.privkey; | |
this.pubkey = obj.pubkey || (this.privkey ? this.privkey.publicKey : this.pubkey); | |
this.sig = obj.sig || this.sig; | |
this.k = obj.k || this.k; | |
this.verified = obj.verified || this.verified; | |
return this; | |
}; | |
ECDSA.prototype.privkey2pubkey = function () { | |
this.pubkey = this.privkey.toPublicKey(); | |
}; | |
ECDSA.prototype.calci = function () { | |
for (var i = 0; i < 4; i++) { | |
this.sig.i = i; | |
var Qprime; | |
try { | |
Qprime = this.toPublicKey(); | |
} catch (e) { | |
console.error(e); | |
continue; | |
} | |
if (Qprime.point.eq(this.pubkey.point)) { | |
this.sig.compressed = this.pubkey.compressed; | |
return this; | |
} | |
} | |
this.sig.i = undefined; | |
throw new Error('Unable to find valid recovery factor'); | |
}; | |
ECDSA.fromString = function (str) { | |
var obj = JSON.parse(str); | |
return new ECDSA(obj); | |
}; | |
ECDSA.prototype.randomK = function () { | |
var N = Point.getN(); | |
var k; | |
do { | |
k = BN.fromBuffer(Random.getRandomBuffer(32)); | |
} while (!(k.lt(N) && k.gt(BN.Zero))); | |
this.k = k; | |
return this; | |
}; | |
// https://tools.ietf.org/html/rfc6979#section-3.2 | |
ECDSA.prototype.deterministicK = function (badrs) { | |
/* jshint maxstatements: 25 */ | |
// if r or s were invalid when this function was used in signing, | |
// we do not want to actually compute r, s here for efficiency, so, | |
// we can increment badrs. explained at end of RFC 6979 section 3.2 | |
if (_.isUndefined(badrs)) { | |
badrs = 0; | |
} | |
var v = new Buffer(32); | |
v.fill(0x01); | |
var k = new Buffer(32); | |
k.fill(0x00); | |
var x = this.privkey.bn.toBuffer({ | |
size: 32 | |
}); | |
var hashbuf = this.endian === 'little' ? BufferUtil.reverse(this.hashbuf) : this.hashbuf; | |
k = Hash.sha256hmac(Buffer.concat([v, new Buffer([0x00]), x, hashbuf]), k); | |
v = Hash.sha256hmac(v, k); | |
k = Hash.sha256hmac(Buffer.concat([v, new Buffer([0x01]), x, hashbuf]), k); | |
v = Hash.sha256hmac(v, k); | |
v = Hash.sha256hmac(v, k); | |
var T = BN.fromBuffer(v); | |
var N = Point.getN(); | |
// also explained in 3.2, we must ensure T is in the proper range (0, N) | |
for (var i = 0; i < badrs || !(T.lt(N) && T.gt(BN.Zero)); i++) { | |
k = Hash.sha256hmac(Buffer.concat([v, new Buffer([0x00])]), k); | |
v = Hash.sha256hmac(v, k); | |
v = Hash.sha256hmac(v, k); | |
T = BN.fromBuffer(v); | |
} | |
this.k = T; | |
return this; | |
}; | |
// Information about public key recovery: | |
// https://bitcointalk.org/index.php?topic=6430.0 | |
// http://stackoverflow.com/questions/19665491/how-do-i-get-an-ecdsa-public-key-from-just-a-bitcoin-signature-sec1-4-1-6-k | |
ECDSA.prototype.toPublicKey = function () { | |
/* jshint maxstatements: 25 */ | |
var i = this.sig.i; | |
$.checkArgument(i === 0 || i === 1 || i === 2 || i === 3, new Error('i must be equal to 0, 1, 2, or 3')); | |
var e = BN.fromBuffer(this.hashbuf); | |
var r = this.sig.r; | |
var s = this.sig.s; | |
// A set LSB signifies that the y-coordinate is odd | |
var isYOdd = i & 1; | |
// The more significant bit specifies whether we should use the | |
// first or second candidate key. | |
var isSecondKey = i >> 1; | |
var n = Point.getN(); | |
var G = Point.getG(); | |
// 1.1 Let x = r + jn | |
var x = isSecondKey ? r.add(n) : r; | |
var R = Point.fromX(isYOdd, x); | |
// 1.4 Check that nR is at infinity | |
var nR = R.mul(n); | |
if (!nR.isInfinity()) { | |
throw new Error('nR is not a valid curve point'); | |
} | |
// Compute -e from e | |
var eNeg = e.neg().umod(n); | |
// 1.6.1 Compute Q = r^-1 (sR - eG) | |
// Q = r^-1 (sR + -eG) | |
var rInv = r.invm(n); | |
//var Q = R.multiplyTwo(s, G, eNeg).mul(rInv); | |
var Q = R.mul(s).add(G.mul(eNeg)).mul(rInv); | |
var pubkey = PublicKey.fromPoint(Q, this.sig.compressed); | |
return pubkey; | |
}; | |
ECDSA.prototype.sigError = function () { | |
/* jshint maxstatements: 25 */ | |
if (!BufferUtil.isBuffer(this.hashbuf) || this.hashbuf.length !== 32) { | |
return 'hashbuf must be a 32 byte buffer'; | |
} | |
var r = this.sig.r; | |
var s = this.sig.s; | |
if (!(r.gt(BN.Zero) && r.lt(Point.getN())) || !(s.gt(BN.Zero) && s.lt(Point.getN()))) { | |
return 'r and s not in range'; | |
} | |
var e = BN.fromBuffer(this.hashbuf, this.endian ? { | |
endian: this.endian | |
} : undefined); | |
var n = Point.getN(); | |
var sinv = s.invm(n); | |
var u1 = sinv.mul(e).umod(n); | |
var u2 = sinv.mul(r).umod(n); | |
var p = Point.getG().mulAdd(u1, this.pubkey.point, u2); | |
if (p.isInfinity()) { | |
return 'p is infinity'; | |
} | |
if (p.getX().umod(n).cmp(r) !== 0) { | |
return 'Invalid signature'; | |
} else { | |
return false; | |
} | |
}; | |
ECDSA.toLowS = function (s) { | |
//enforce low s | |
//see BIP 62, "low S values in signatures" | |
if (s.gt(BN.fromBuffer(new Buffer('7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0', 'hex')))) { | |
s = Point.getN().sub(s); | |
} | |
return s; | |
}; | |
ECDSA.prototype._findSignature = function (d, e) { | |
var N = Point.getN(); | |
var G = Point.getG(); | |
// try different values of k until r, s are valid | |
var badrs = 0; | |
var k, Q, r, s; | |
do { | |
if (!this.k || badrs > 0) { | |
this.deterministicK(badrs); | |
} | |
badrs++; | |
k = this.k; | |
Q = G.mul(k); | |
r = Q.x.umod(N); | |
s = k.invm(N).mul(e.add(d.mul(r))).umod(N); | |
} while (r.cmp(BN.Zero) <= 0 || s.cmp(BN.Zero) <= 0); | |
s = ECDSA.toLowS(s); | |
return { | |
s: s, | |
r: r | |
}; | |
}; | |
ECDSA.prototype.sign = function () { | |
var hashbuf = this.hashbuf; | |
var privkey = this.privkey; | |
var d = privkey.bn; | |
$.checkState(hashbuf && privkey && d, new Error('invalid parameters')); | |
$.checkState(BufferUtil.isBuffer(hashbuf) && hashbuf.length === 32, new Error('hashbuf must be a 32 byte buffer')); | |
var e = BN.fromBuffer(hashbuf, this.endian ? { | |
endian: this.endian | |
} : undefined); | |
var obj = this._findSignature(d, e); | |
obj.compressed = this.pubkey.compressed; | |
this.sig = new Signature(obj); | |
return this; | |
}; | |
ECDSA.prototype.signRandomK = function () { | |
this.randomK(); | |
return this.sign(); | |
}; | |
ECDSA.prototype.toString = function () { | |
var obj = {}; | |
if (this.hashbuf) { | |
obj.hashbuf = this.hashbuf.toString('hex'); | |
} | |
if (this.privkey) { | |
obj.privkey = this.privkey.toString(); | |
} | |
if (this.pubkey) { | |
obj.pubkey = this.pubkey.toString(); | |
} | |
if (this.sig) { | |
obj.sig = this.sig.toString(); | |
} | |
if (this.k) { | |
obj.k = this.k.toString(); | |
} | |
return JSON.stringify(obj); | |
}; | |
ECDSA.prototype.verify = function () { | |
if (!this.sigError()) { | |
this.verified = true; | |
} else { | |
this.verified = false; | |
} | |
return this; | |
}; | |
ECDSA.sign = function (hashbuf, privkey, endian) { | |
return ECDSA().set({ | |
hashbuf: hashbuf, | |
endian: endian, | |
privkey: privkey | |
}).sign().sig; | |
}; | |
ECDSA.verify = function (hashbuf, sig, pubkey, endian) { | |
return ECDSA().set({ | |
hashbuf: hashbuf, | |
endian: endian, | |
sig: sig, | |
pubkey: pubkey | |
}).verify().verified; | |
}; | |
module.exports = ECDSA; | |
}).call(this,require("buffer").Buffer) | |
},{"../publickey":50,"../util/buffer":68,"../util/preconditions":70,"./bn":32,"./hash":34,"./point":35,"./random":36,"./signature":37,"buffer":148,"lodash":267}],34:[function(require,module,exports){ | |
(function (Buffer){ | |
'use strict'; | |
var crypto = require('crypto'); | |
var BufferUtil = require('../util/buffer'); | |
var $ = require('../util/preconditions'); | |
var Hash = module.exports; | |
Hash.sha1 = function (buf) { | |
$.checkArgument(BufferUtil.isBuffer(buf)); | |
return crypto.createHash('sha1').update(buf).digest(); | |
}; | |
Hash.sha1.blocksize = 512; | |
Hash.sha256 = function (buf) { | |
$.checkArgument(BufferUtil.isBuffer(buf)); | |
return crypto.createHash('sha256').update(buf).digest(); | |
}; | |
Hash.sha256.blocksize = 512; | |
Hash.sha256sha256 = function (buf) { | |
$.checkArgument(BufferUtil.isBuffer(buf)); | |
return Hash.sha256(Hash.sha256(buf)); | |
}; | |
Hash.ripemd160 = function (buf) { | |
$.checkArgument(BufferUtil.isBuffer(buf)); | |
return crypto.createHash('ripemd160').update(buf).digest(); | |
}; | |
Hash.sha256ripemd160 = function (buf) { | |
$.checkArgument(BufferUtil.isBuffer(buf)); | |
return Hash.ripemd160(Hash.sha256(buf)); | |
}; | |
Hash.sha512 = function (buf) { | |
$.checkArgument(BufferUtil.isBuffer(buf)); | |
return crypto.createHash('sha512').update(buf).digest(); | |
}; | |
Hash.sha512.blocksize = 1024; | |
Hash.hmac = function (hashf, data, key) { | |
//http://en.wikipedia.org/wiki/Hash-based_message_authentication_code | |
//http://tools.ietf.org/html/rfc4868#section-2 | |
$.checkArgument(BufferUtil.isBuffer(data)); | |
$.checkArgument(BufferUtil.isBuffer(key)); | |
$.checkArgument(hashf.blocksize); | |
var blocksize = hashf.blocksize / 8; | |
if (key.length > blocksize) { | |
key = hashf(key); | |
} else if (key < blocksize) { | |
var fill = new Buffer(blocksize); | |
fill.fill(0); | |
key.copy(fill); | |
key = fill; | |
} | |
var o_key = new Buffer(blocksize); | |
o_key.fill(0x5c); | |
var i_key = new Buffer(blocksize); | |
i_key.fill(0x36); | |
var o_key_pad = new Buffer(blocksize); | |
var i_key_pad = new Buffer(blocksize); | |
for (var i = 0; i < blocksize; i++) { | |
o_key_pad[i] = o_key[i] ^ key[i]; | |
i_key_pad[i] = i_key[i] ^ key[i]; | |
} | |
return hashf(Buffer.concat([o_key_pad, hashf(Buffer.concat([i_key_pad, data]))])); | |
}; | |
Hash.sha256hmac = function (data, key) { | |
return Hash.hmac(Hash.sha256, data, key); | |
}; | |
Hash.sha512hmac = function (data, key) { | |
return Hash.hmac(Hash.sha512, data, key); | |
}; | |
}).call(this,require("buffer").Buffer) | |
},{"../util/buffer":68,"../util/preconditions":70,"buffer":148,"crypto":173}],35:[function(require,module,exports){ | |
(function (Buffer){ | |
'use strict'; | |
var BN = require('./bn'); | |
var BufferUtil = require('../util/buffer'); | |
var EC = require('elliptic').ec; | |
var ec = new EC('secp256k1'); | |
var ecPoint = ec.curve.point.bind(ec.curve); | |
var ecPointFromX = ec.curve.pointFromX.bind(ec.curve); | |
/** | |
* | |
* Instantiate a valid secp256k1 Point from the X and Y coordinates. | |
* | |
* @param {BN|String} x - The X coordinate | |
* @param {BN|String} y - The Y coordinate | |
* @link https://github.com/indutny/elliptic | |
* @augments elliptic.curve.point | |
* @throws {Error} A validation error if exists | |
* @returns {Point} An instance of Point | |
* @constructor | |
*/ | |
var Point = function Point(x, y, isRed) { | |
try { | |
var point = ecPoint(x, y, isRed); | |
} catch (e) { | |
throw new Error('Invalid Point'); | |
} | |
point.validate(); | |
return point; | |
}; | |
Point.prototype = Object.getPrototypeOf(ec.curve.point()); | |
/** | |
* | |
* Instantiate a valid secp256k1 Point from only the X coordinate | |
* | |
* @param {boolean} odd - If the Y coordinate is odd | |
* @param {BN|String} x - The X coordinate | |
* @throws {Error} A validation error if exists | |
* @returns {Point} An instance of Point | |
*/ | |
Point.fromX = function fromX(odd, x) { | |
try { | |
var point = ecPointFromX(x, odd); | |
} catch (e) { | |
throw new Error('Invalid X'); | |
} | |
point.validate(); | |
return point; | |
}; | |
/** | |
* | |
* Will return a secp256k1 ECDSA base point. | |
* | |
* @link https://en.bitcoin.it/wiki/Secp256k1 | |
* @returns {Point} An instance of the base point. | |
*/ | |
Point.getG = function getG() { | |
return ec.curve.g; | |
}; | |
/** | |
* | |
* Will return the max of range of valid private keys as governed by the secp256k1 ECDSA standard. | |
* | |
* @link https://en.bitcoin.it/wiki/Private_key#Range_of_valid_ECDSA_private_keys | |
* @returns {BN} A BN instance of the number of points on the curve | |
*/ | |
Point.getN = function getN() { | |
return new BN(ec.curve.n.toArray()); | |
}; | |
Point.prototype._getX = Point.prototype.getX; | |
/** | |
* | |
* Will return the X coordinate of the Point | |
* | |
* @returns {BN} A BN instance of the X coordinate | |
*/ | |
Point.prototype.getX = function getX() { | |
return new BN(this._getX().toArray()); | |
}; | |
Point.prototype._getY = Point.prototype.getY; | |
/** | |
* | |
* Will return the Y coordinate of the Point | |
* | |
* @returns {BN} A BN instance of the Y coordinate | |
*/ | |
Point.prototype.getY = function getY() { | |
return new BN(this._getY().toArray()); | |
}; | |
/** | |
* | |
* Will determine if the point is valid | |
* | |
* @link https://www.iacr.org/archive/pkc2003/25670211/25670211.pdf | |
* @param {Point} An instance of Point | |
* @throws {Error} A validation error if exists | |
* @returns {Point} An instance of the same Point | |
*/ | |
Point.prototype.validate = function validate() { | |
if (this.isInfinity()) { | |
throw new Error('Point cannot be equal to Infinity'); | |
} | |
var p2; | |
try { | |
p2 = ecPointFromX(this.getX(), this.getY().isOdd()); | |
} catch (e) { | |
throw new Error('Point does not lie on the curve'); | |
} | |
if (p2.y.cmp(this.y) !== 0) { | |
throw new Error('Invalid y value for curve.'); | |
} | |
//todo: needs test case | |
if (!this.mul(Point.getN()).isInfinity()) { | |
throw new Error('Point times N must be infinity'); | |
} | |
return this; | |
}; | |
Point.pointToCompressed = function pointToCompressed(point) { | |
var xbuf = point.getX().toBuffer({ size: 32 }); | |
var ybuf = point.getY().toBuffer({ size: 32 }); | |
var prefix; | |
var odd = ybuf[ybuf.length - 1] % 2; | |
if (odd) { | |
prefix = new Buffer([0x03]); | |
} else { | |
prefix = new Buffer([0x02]); | |
} | |
return BufferUtil.concat([prefix, xbuf]); | |
}; | |
module.exports = Point; | |
}).call(this,require("buffer").Buffer) | |
},{"../util/buffer":68,"./bn":32,"buffer":148,"elliptic":71}],36:[function(require,module,exports){ | |
(function (process,Buffer){ | |
'use strict'; | |
function Random() {} | |
/* secure random bytes that sometimes throws an error due to lack of entropy */ | |
Random.getRandomBuffer = function (size) { | |
if (process.browser) return Random.getRandomBufferBrowser(size);else return Random.getRandomBufferNode(size); | |
}; | |
Random.getRandomBufferNode = function (size) { | |
var crypto = require('crypto'); | |
return crypto.randomBytes(size); | |
}; | |
Random.getRandomBufferBrowser = function (size) { | |
if (!window.crypto && !window.msCrypto) throw new Error('window.crypto not available'); | |
if (window.crypto && window.crypto.getRandomValues) var crypto = window.crypto;else if (window.msCrypto && window.msCrypto.getRandomValues) //internet explorer | |
var crypto = window.msCrypto;else throw new Error('window.crypto.getRandomValues not available'); | |
var bbuf = new Uint8Array(size); | |
crypto.getRandomValues(bbuf); | |
var buf = new Buffer(bbuf); | |
return buf; | |
}; | |
/* insecure random bytes, but it never fails */ | |
Random.getPseudoRandomBuffer = function (size) { | |
var b32 = 0x100000000; | |
var b = new Buffer(size); | |
var r; | |
for (var i = 0; i <= size; i++) { | |
var j = Math.floor(i / 4); | |
var k = i - j * 4; | |
if (k === 0) { | |
r = Math.random() * b32; | |
b[i] = r & 0xff; | |
} else { | |
b[i] = (r = r >>> 8) & 0xff; | |
} | |
} | |
return b; | |
}; | |
module.exports = Random; | |
}).call(this,require('_process'),require("buffer").Buffer) | |
},{"_process":284,"buffer":148,"crypto":173}],37:[function(require,module,exports){ | |
(function (Buffer){ | |
'use strict'; | |
var BN = require('./bn'); | |
var _ = require('lodash'); | |
var $ = require('../util/preconditions'); | |
var BufferUtil = require('../util/buffer'); | |
var JSUtil = require('../util/js'); | |
var Signature = function Signature(r, s) { | |
if (!(this instanceof Signature)) { | |
return new Signature(r, s); | |
} | |
if (r instanceof BN) { | |
this.set({ | |
r: r, | |
s: s | |
}); | |
} else if (r) { | |
var obj = r; | |
this.set(obj); | |
} | |
}; | |
/* jshint maxcomplexity: 7 */ | |
Signature.prototype.set = function (obj) { | |
this.r = obj.r || this.r || undefined; | |
this.s = obj.s || this.s || undefined; | |
this.i = typeof obj.i !== 'undefined' ? obj.i : this.i; //public key recovery parameter in range [0, 3] | |
this.compressed = typeof obj.compressed !== 'undefined' ? obj.compressed : this.compressed; //whether the recovered pubkey is compressed | |
this.nhashtype = obj.nhashtype || this.nhashtype || undefined; | |
return this; | |
}; | |
Signature.fromCompact = function (buf) { | |
$.checkArgument(BufferUtil.isBuffer(buf), 'Argument is expected to be a Buffer'); | |
var sig = new Signature(); | |
var compressed = true; | |
var i = buf.slice(0, 1)[0] - 27 - 4; | |
if (i < 0) { | |
compressed = false; | |
i = i + 4; | |
} | |
var b2 = buf.slice(1, 33); | |
var b3 = buf.slice(33, 65); | |
$.checkArgument(i === 0 || i === 1 || i === 2 || i === 3, new Error('i must be 0, 1, 2, or 3')); | |
$.checkArgument(b2.length === 32, new Error('r must be 32 bytes')); | |
$.checkArgument(b3.length === 32, new Error('s must be 32 bytes')); | |
sig.compressed = compressed; | |
sig.i = i; | |
sig.r = BN.fromBuffer(b2); | |
sig.s = BN.fromBuffer(b3); | |
return sig; | |
}; | |
Signature.fromDER = Signature.fromBuffer = function (buf, strict) { | |
var obj = Signature.parseDER(buf, strict); | |
var sig = new Signature(); | |
sig.r = obj.r; | |
sig.s = obj.s; | |
return sig; | |
}; | |
// The format used in a tx | |
Signature.fromTxFormat = function (buf) { | |
var nhashtype = buf.readUInt8(buf.length - 1); | |
var derbuf = buf.slice(0, buf.length - 1); | |
var sig = new Signature.fromDER(derbuf, false); | |
sig.nhashtype = nhashtype; | |
return sig; | |
}; | |
Signature.fromString = function (str) { | |
var buf = new Buffer(str, 'hex'); | |
return Signature.fromDER(buf); | |
}; | |
/** | |
* In order to mimic the non-strict DER encoding of OpenSSL, set strict = false. | |
*/ | |
Signature.parseDER = function (buf, strict) { | |
$.checkArgument(BufferUtil.isBuffer(buf), new Error('DER formatted signature should be a buffer')); | |
if (_.isUndefined(strict)) { | |
strict = true; | |
} | |
var header = buf[0]; | |
$.checkArgument(header === 0x30, new Error('Header byte should be 0x30')); | |
var length = buf[1]; | |
var buflength = buf.slice(2).length; | |
$.checkArgument(!strict || length === buflength, new Error('Length byte should length of what follows')); | |
length = length < buflength ? length : buflength; | |
var rheader = buf[2 + 0]; | |
$.checkArgument(rheader === 0x02, new Error('Integer byte for r should be 0x02')); | |
var rlength = buf[2 + 1]; | |
var rbuf = buf.slice(2 + 2, 2 + 2 + rlength); | |
var r = BN.fromBuffer(rbuf); | |
var rneg = buf[2 + 1 + 1] === 0x00 ? true : false; | |
$.checkArgument(rlength === rbuf.length, new Error('Length of r incorrect')); | |
var sheader = buf[2 + 2 + rlength + 0]; | |
$.checkArgument(sheader === 0x02, new Error('Integer byte for s should be 0x02')); | |
var slength = buf[2 + 2 + rlength + 1]; | |
var sbuf = buf.slice(2 + 2 + rlength + 2, 2 + 2 + rlength + 2 + slength); | |
var s = BN.fromBuffer(sbuf); | |
var sneg = buf[2 + 2 + rlength + 2 + 2] === 0x00 ? true : false; | |
$.checkArgument(slength === sbuf.length, new Error('Length of s incorrect')); | |
var sumlength = 2 + 2 + rlength + 2 + slength; | |
$.checkArgument(length === sumlength - 2, new Error('Length of signature incorrect')); | |
var obj = { | |
header: header, | |
length: length, | |
rheader: rheader, | |
rlength: rlength, | |
rneg: rneg, | |
rbuf: rbuf, | |
r: r, | |
sheader: sheader, | |
slength: slength, | |
sneg: sneg, | |
sbuf: sbuf, | |
s: s | |
}; | |
return obj; | |
}; | |
Signature.prototype.toCompact = function (i, compressed) { | |
i = typeof i === 'number' ? i : this.i; | |
compressed = typeof compressed === 'boolean' ? compressed : this.compressed; | |
if (!(i === 0 || i === 1 || i === 2 || i === 3)) { | |
throw new Error('i must be equal to 0, 1, 2, or 3'); | |
} | |
var val = i + 27 + 4; | |
if (compressed === false) { | |
val = val - 4; | |
} | |
var b1 = new Buffer([val]); | |
var b2 = this.r.toBuffer({ | |
size: 32 | |
}); | |
var b3 = this.s.toBuffer({ | |
size: 32 | |
}); | |
return Buffer.concat([b1, b2, b3]); | |
}; | |
Signature.prototype.toBuffer = Signature.prototype.toDER = function () { | |
var rnbuf = this.r.toBuffer(); | |
var snbuf = this.s.toBuffer(); | |
var rneg = rnbuf[0] & 0x80 ? true : false; | |
var sneg = snbuf[0] & 0x80 ? true : false; | |
var rbuf = rneg ? Buffer.concat([new Buffer([0x00]), rnbuf]) : rnbuf; | |
var sbuf = sneg ? Buffer.concat([new Buffer([0x00]), snbuf]) : snbuf; | |
var rlength = rbuf.length; | |
var slength = sbuf.length; | |
var length = 2 + rlength + 2 + slength; | |
var rheader = 0x02; | |
var sheader = 0x02; | |
var header = 0x30; | |
var der = Buffer.concat([new Buffer([header, length, rheader, rlength]), rbuf, new Buffer([sheader, slength]), sbuf]); | |
return der; | |
}; | |
Signature.prototype.toString = function () { | |
var buf = this.toDER(); | |
return buf.toString('hex'); | |
}; | |
/** | |
* This function is translated from bitcoind's IsDERSignature and is used in | |
* the script interpreter. This "DER" format actually includes an extra byte, | |
* the nhashtype, at the end. It is really the tx format, not DER format. | |
* | |
* A canonical signature exists of: [30] [total len] [02] [len R] [R] [02] [len S] [S] [hashtype] | |
* Where R and S are not negative (their first byte has its highest bit not set), and not | |
* excessively padded (do not start with a 0 byte, unless an otherwise negative number follows, | |
* in which case a single 0 byte is necessary and even required). | |
* | |
* See https://bitcointalk.org/index.php?topic=8392.msg127623#msg127623 | |
*/ | |
Signature.isTxDER = function (buf) { | |
if (buf.length < 9) { | |
// Non-canonical signature: too short | |
return false; | |
} | |
if (buf.length > 73) { | |
// Non-canonical signature: too long | |
return false; | |
} | |
if (buf[0] !== 0x30) { | |
// Non-canonical signature: wrong type | |
return false; | |
} | |
if (buf[1] !== buf.length - 3) { | |
// Non-canonical signature: wrong length marker | |
return false; | |
} | |
var nLenR = buf[3]; | |
if (5 + nLenR >= buf.length) { | |
// Non-canonical signature: S length misplaced | |
return false; | |
} | |
var nLenS = buf[5 + nLenR]; | |
if (nLenR + nLenS + 7 !== buf.length) { | |
// Non-canonical signature: R+S length mismatch | |
return false; | |
} | |
var R = buf.slice(4); | |
if (buf[4 - 2] !== 0x02) { | |
// Non-canonical signature: R value type mismatch | |
return false; | |
} | |
if (nLenR === 0) { | |
// Non-canonical signature: R length is zero | |
return false; | |
} | |
if (R[0] & 0x80) { | |
// Non-canonical signature: R value negative | |
return false; | |
} | |
if (nLenR > 1 && R[0] === 0x00 && !(R[1] & 0x80)) { | |
// Non-canonical signature: R value excessively padded | |
return false; | |
} | |
var S = buf.slice(6 + nLenR); | |
if (buf[6 + nLenR - 2] !== 0x02) { | |
// Non-canonical signature: S value type mismatch | |
return false; | |
} | |
if (nLenS === 0) { | |
// Non-canonical signature: S length is zero | |
return false; | |
} | |
if (S[0] & 0x80) { | |
// Non-canonical signature: S value negative | |
return false; | |
} | |
if (nLenS > 1 && S[0] === 0x00 && !(S[1] & 0x80)) { | |
// Non-canonical signature: S value excessively padded | |
return false; | |
} | |
return true; | |
}; | |
/** | |
* Compares to bitcoind's IsLowDERSignature | |
* See also ECDSA signature algorithm which enforces this. | |
* See also BIP 62, "low S values in signatures" | |
*/ | |
Signature.prototype.hasLowS = function () { | |
if (this.s.lt(new BN(1)) || this.s.gt(new BN('7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0', 'hex'))) { | |
return false; | |
} | |
return true; | |
}; | |
/** | |
* @returns true if the nhashtype is exactly equal to one of the standard options or combinations thereof. | |
* Translated from bitcoind's IsDefinedHashtypeSignature | |
*/ | |
Signature.prototype.hasDefinedHashtype = function () { | |
if (!JSUtil.isNaturalNumber(this.nhashtype)) { | |
return false; | |
} | |
// accept with or without Signature.SIGHASH_ANYONECANPAY by ignoring the bit | |
var temp = this.nhashtype & ~Signature.SIGHASH_ANYONECANPAY; | |
if (temp < Signature.SIGHASH_ALL || temp > Signature.SIGHASH_SINGLE) { | |
return false; | |
} | |
return true; | |
}; | |
Signature.prototype.toTxFormat = function () { | |
var derbuf = this.toDER(); | |
var buf = new Buffer(1); | |
buf.writeUInt8(this.nhashtype, 0); | |
return Buffer.concat([derbuf, buf]); | |
}; | |
Signature.SIGHASH_ALL = 0x01; | |
Signature.SIGHASH_NONE = 0x02; | |
Signature.SIGHASH_SINGLE = 0x03; | |
Signature.SIGHASH_ANYONECANPAY = 0x80; | |
module.exports = Signature; | |
}).call(this,require("buffer").Buffer) | |
},{"../util/buffer":68,"../util/js":69,"../util/preconditions":70,"./bn":32,"buffer":148,"lodash":267}],38:[function(require,module,exports){ | |
(function (Buffer){ | |
'use strict'; | |
var _ = require('lodash'); | |
var bs58 = require('bs58'); | |
var buffer = require('buffer'); | |
var ALPHABET = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'.split(''); | |
var Base58 = function Base58(obj) { | |
/* jshint maxcomplexity: 8 */ | |
if (!(this instanceof Base58)) { | |
return new Base58(obj); | |
} | |
if (Buffer.isBuffer(obj)) { | |
var buf = obj; | |
this.fromBuffer(buf); | |
} else if (typeof obj === 'string') { | |
var str = obj; | |
this.fromString(str); | |
} else if (obj) { | |
this.set(obj); | |
} | |
}; | |
Base58.validCharacters = function validCharacters(chars) { | |
if (buffer.Buffer.isBuffer(chars)) { | |
chars = chars.toString(); | |
} | |
return _.every(_.map(chars, function (char) { | |
return _.includes(ALPHABET, char); | |
})); | |
}; | |
Base58.prototype.set = function (obj) { | |
this.buf = obj.buf || this.buf || undefined; | |
return this; | |
}; | |
Base58.encode = function (buf) { | |
if (!buffer.Buffer.isBuffer(buf)) { | |
throw new Error('Input should be a buffer'); | |
} | |
return bs58.encode(buf); | |
}; | |
Base58.decode = function (str) { | |
if (typeof str !== 'string') { | |
throw new Error('Input should be a string'); | |
} | |
return new Buffer(bs58.decode(str)); | |
}; | |
Base58.prototype.fromBuffer = function (buf) { | |
this.buf = buf; | |
return this; | |
}; | |
Base58.prototype.fromString = function (str) { | |
var buf = Base58.decode(str); | |
this.buf = buf; | |
return this; | |
}; | |
Base58.prototype.toBuffer = function () { | |
return this.buf; | |
}; | |
Base58.prototype.toString = function () { | |
return Base58.encode(this.buf); | |
}; | |
module.exports = Base58; | |
}).call(this,require("buffer").Buffer) | |
},{"bs58":145,"buffer":148,"lodash":267}],39:[function(require,module,exports){ | |
(function (Buffer){ | |
'use strict'; | |
var _ = require('lodash'); | |
var Base58 = require('./base58'); | |
var buffer = require('buffer'); | |
var sha256sha256 = require('../crypto/hash').sha256sha256; | |
var Base58Check = function Base58Check(obj) { | |
if (!(this instanceof Base58Check)) return new Base58Check(obj); | |
if (Buffer.isBuffer(obj)) { | |
var buf = obj; | |
this.fromBuffer(buf); | |
} else if (typeof obj === 'string') { | |
var str = obj; | |
this.fromString(str); | |
} else if (obj) { | |
this.set(obj); | |
} | |
}; | |
Base58Check.prototype.set = function (obj) { | |
this.buf = obj.buf || this.buf || undefined; | |
return this; | |
}; | |
Base58Check.validChecksum = function validChecksum(data, checksum) { | |
if (_.isString(data)) { | |
data = new buffer.Buffer(Base58.decode(data)); | |
} | |
if (_.isString(checksum)) { | |
checksum = new buffer.Buffer(Base58.decode(checksum)); | |
} | |
if (!checksum) { | |
checksum = data.slice(-4); | |
data = data.slice(0, -4); | |
} | |
return Base58Check.checksum(data).toString('hex') === checksum.toString('hex'); | |
}; | |
Base58Check.decode = function (s) { | |
if (typeof s !== 'string') throw new Error('Input must be a string'); | |
var buf = new Buffer(Base58.decode(s)); | |
if (buf.length < 4) throw new Error("Input string too short"); | |
var data = buf.slice(0, -4); | |
var csum = buf.slice(-4); | |
var hash = sha256sha256(data); | |
var hash4 = hash.slice(0, 4); | |
if (csum.toString('hex') !== hash4.toString('hex')) throw new Error("Checksum mismatch"); | |
return data; | |
}; | |
Base58Check.checksum = function (buffer) { | |
return sha256sha256(buffer).slice(0, 4); | |
}; | |
Base58Check.encode = function (buf) { | |
if (!Buffer.isBuffer(buf)) throw new Error('Input must be a buffer'); | |
var checkedBuf = new Buffer(buf.length + 4); | |
var hash = Base58Check.checksum(buf); | |
buf.copy(checkedBuf); | |
hash.copy(checkedBuf, buf.length); | |
return Base58.encode(checkedBuf); | |
}; | |
Base58Check.prototype.fromBuffer = function (buf) { | |
this.buf = buf; | |
return this; | |
}; | |
Base58Check.prototype.fromString = function (str) { | |
var buf = Base58Check.decode(str); | |
this.buf = buf; | |
return this; | |
}; | |
Base58Check.prototype.toBuffer = function () { | |
return this.buf; | |
}; | |
Base58Check.prototype.toString = function () { | |
return Base58Check.encode(this.buf); | |
}; | |
module.exports = Base58Check; | |
}).call(this,require("buffer").Buffer) | |
},{"../crypto/hash":34,"./base58":38,"buffer":148,"lodash":267}],40:[function(require,module,exports){ | |
(function (Buffer){ | |
'use strict'; | |
var _ = require('lodash'); | |
var $ = require('../util/preconditions'); | |
var BufferUtil = require('../util/buffer'); | |
var BN = require('../crypto/bn'); | |
var BufferReader = function BufferReader(buf) { | |
if (!(this instanceof BufferReader)) { | |
return new BufferReader(buf); | |
} | |
if (_.isUndefined(buf)) { | |
return; | |
} | |
if (Buffer.isBuffer(buf)) { | |
this.set({ | |
buf: buf | |
}); | |
} else if (_.isString(buf)) { | |
this.set({ | |
buf: new Buffer(buf, 'hex') | |
}); | |
} else if (_.isObject(buf)) { | |
var obj = buf; | |
this.set(obj); | |
} else { | |
throw new TypeError('Unrecognized argument for BufferReader'); | |
} | |
}; | |
BufferReader.prototype.set = function (obj) { | |
this.buf = obj.buf || this.buf || undefined; | |
this.pos = obj.pos || this.pos || 0; | |
return this; | |
}; | |
BufferReader.prototype.eof = function () { | |
return this.pos >= this.buf.length; | |
}; | |
BufferReader.prototype.finished = BufferReader.prototype.eof; | |
BufferReader.prototype.read = function (len) { | |
$.checkArgument(!_.isUndefined(len), 'Must specify a length'); | |
var buf = this.buf.slice(this.pos, this.pos + len); | |
this.pos = this.pos + len; | |
return buf; | |
}; | |
BufferReader.prototype.readAll = function () { | |
var buf = this.buf.slice(this.pos, this.buf.length); | |
this.pos = this.buf.length; | |
return buf; | |
}; | |
BufferReader.prototype.readUInt8 = function () { | |
var val = this.buf.readUInt8(this.pos); | |
this.pos = this.pos + 1; | |
return val; | |
}; | |
BufferReader.prototype.readUInt16BE = function () { | |
var val = this.buf.readUInt16BE(this.pos); | |
this.pos = this.pos + 2; | |
return val; | |
}; | |
BufferReader.prototype.readUInt16LE = function () { | |
var val = this.buf.readUInt16LE(this.pos); | |
this.pos = this.pos + 2; | |
return val; | |
}; | |
BufferReader.prototype.readUInt32BE = function () { | |
var val = this.buf.readUInt32BE(this.pos); | |
this.pos = this.pos + 4; | |
return val; | |
}; | |
BufferReader.prototype.readUInt32LE = function () { | |
var val = this.buf.readUInt32LE(this.pos); | |
this.pos = this.pos + 4; | |
return val; | |
}; | |
BufferReader.prototype.readInt32LE = function () { | |
var val = this.buf.readInt32LE(this.pos); | |
this.pos = this.pos + 4; | |
return val; | |
}; | |
BufferReader.prototype.readUInt64BEBN = function () { | |
var buf = this.buf.slice(this.pos, this.pos + 8); | |
var bn = BN.fromBuffer(buf); | |
this.pos = this.pos + 8; | |
return bn; | |
}; | |
BufferReader.prototype.readUInt64LEBN = function () { | |
var second = this.buf.readUInt32LE(this.pos); | |
var first = this.buf.readUInt32LE(this.pos + 4); | |
var combined = first * 0x100000000 + second; | |
// Instantiating an instance of BN with a number is faster than with an | |
// array or string. However, the maximum safe number for a double precision | |
// floating point is 2 ^ 52 - 1 (0x1fffffffffffff), thus we can safely use | |
// non-floating point numbers less than this amount (52 bits). And in the case | |
// that the number is larger, we can instatiate an instance of BN by passing | |
// an array from the buffer (slower) and specifying the endianness. | |
var bn; | |
if (combined <= 0x1fffffffffffff) { | |
bn = new BN(combined); | |
} else { | |
var data = Array.prototype.slice.call(this.buf, this.pos, this.pos + 8); | |
bn = new BN(data, 10, 'le'); | |
} | |
this.pos = this.pos + 8; | |
return bn; | |
}; | |
BufferReader.prototype.readVarintNum = function () { | |
var first = this.readUInt8(); | |
switch (first) { | |
case 0xFD: | |
return this.readUInt16LE(); | |
case 0xFE: | |
return this.readUInt32LE(); | |
case 0xFF: | |
var bn = this.readUInt64LEBN(); | |
var n = bn.toNumber(); | |
if (n <= Math.pow(2, 53)) { | |
return n; | |
} else { | |
throw new Error('number too large to retain precision - use readVarintBN'); | |
} | |
break; | |
default: | |
return first; | |
} | |
}; | |
/** | |
* reads a length prepended buffer | |
*/ | |
BufferReader.prototype.readVarLengthBuffer = function () { | |
var len = this.readVarintNum(); | |
var buf = this.read(len); | |
$.checkState(buf.length === len, 'Invalid length while reading varlength buffer. ' + 'Expected to read: ' + len + ' and read ' + buf.length); | |
return buf; | |
}; | |
BufferReader.prototype.readVarintBuf = function () { | |
var first = this.buf.readUInt8(this.pos); | |
switch (first) { | |
case 0xFD: | |
return this.read(1 + 2); | |
case 0xFE: | |
return this.read(1 + 4); | |
case 0xFF: | |
return this.read(1 + 8); | |
default: | |
return this.read(1); | |
} | |
}; | |
BufferReader.prototype.readVarintBN = function () { | |
var first = this.readUInt8(); | |
switch (first) { | |
case 0xFD: | |
return new BN(this.readUInt16LE()); | |
case 0xFE: | |
return new BN(this.readUInt32LE()); | |
case 0xFF: | |
return this.readUInt64LEBN(); | |
default: | |
return new BN(first); | |
} | |
}; | |
BufferReader.prototype.reverse = function () { | |
var buf = new Buffer(this.buf.length); | |
for (var i = 0; i < buf.length; i++) { | |
buf[i] = this.buf[this.buf.length - 1 - i]; | |
} | |
this.buf = buf; | |
return this; | |
}; | |
BufferReader.prototype.readReverse = function (len) { | |
if (_.isUndefined(len)) { | |
len = this.buf.length; | |
} | |
var buf = this.buf.slice(this.pos, this.pos + len); | |
this.pos = this.pos + len; | |
return BufferUtil.reverse(buf); | |
}; | |
module.exports = BufferReader; | |
}).call(this,require("buffer").Buffer) | |
},{"../crypto/bn":32,"../util/buffer":68,"../util/preconditions":70,"buffer":148,"lodash":267}],41:[function(require,module,exports){ | |
(function (Buffer){ | |
'use strict'; | |
var bufferUtil = require('../util/buffer'); | |
var assert = require('assert'); | |
var BufferWriter = function BufferWriter(obj) { | |
if (!(this instanceof BufferWriter)) return new BufferWriter(obj); | |
if (obj) this.set(obj);else this.bufs = []; | |
}; | |
BufferWriter.prototype.set = function (obj) { | |
this.bufs = obj.bufs || this.bufs || []; | |
return this; | |
}; | |
BufferWriter.prototype.toBuffer = function () { | |
return this.concat(); | |
}; | |
BufferWriter.prototype.concat = function () { | |
return Buffer.concat(this.bufs); | |
}; | |
BufferWriter.prototype.write = function (buf) { | |
assert(bufferUtil.isBuffer(buf)); | |
this.bufs.push(buf); | |
return this; | |
}; | |
BufferWriter.prototype.writeReverse = function (buf) { | |
assert(bufferUtil.isBuffer(buf)); | |
this.bufs.push(bufferUtil.reverse(buf)); | |
return this; | |
}; | |
BufferWriter.prototype.writeUInt8 = function (n) { | |
var buf = new Buffer(1); | |
buf.writeUInt8(n, 0); | |
this.write(buf); | |
return this; | |
}; | |
BufferWriter.prototype.writeUInt16BE = function (n) { | |
var buf = new Buffer(2); | |
buf.writeUInt16BE(n, 0); | |
this.write(buf); | |
return this; | |
}; | |
BufferWriter.prototype.writeUInt16LE = function (n) { | |
var buf = new Buffer(2); | |
buf.writeUInt16LE(n, 0); | |
this.write(buf); | |
return this; | |
}; | |
BufferWriter.prototype.writeUInt32BE = function (n) { | |
var buf = new Buffer(4); | |
buf.writeUInt32BE(n, 0); | |
this.write(buf); | |
return this; | |
}; | |
BufferWriter.prototype.writeInt32LE = function (n) { | |
var buf = new Buffer(4); | |
buf.writeInt32LE(n, 0); | |
this.write(buf); | |
return this; | |
}; | |
BufferWriter.prototype.writeUInt32LE = function (n) { | |
var buf = new Buffer(4); | |
buf.writeUInt32LE(n, 0); | |
this.write(buf); | |
return this; | |
}; | |
BufferWriter.prototype.writeUInt64BEBN = function (bn) { | |
var buf = bn.toBuffer({ size: 8 }); | |
this.write(buf); | |
return this; | |
}; | |
BufferWriter.prototype.writeUInt64LEBN = function (bn) { | |
var buf = bn.toBuffer({ size: 8 }); | |
this.writeReverse(buf); | |
return this; | |
}; | |
BufferWriter.prototype.writeVarintNum = function (n) { | |
var buf = BufferWriter.varintBufNum(n); | |
this.write(buf); | |
return this; | |
}; | |
BufferWriter.prototype.writeVarintBN = function (bn) { | |
var buf = BufferWriter.varintBufBN(bn); | |
this.write(buf); | |
return this; | |
}; | |
BufferWriter.varintBufNum = function (n) { | |
var buf = undefined; | |
if (n < 253) { | |
buf = new Buffer(1); | |
buf.writeUInt8(n, 0); | |
} else if (n < 0x10000) { | |
buf = new Buffer(1 + 2); | |
buf.writeUInt8(253, 0); | |
buf.writeUInt16LE(n, 1); | |
} else if (n < 0x100000000) { | |
buf = new Buffer(1 + 4); | |
buf.writeUInt8(254, 0); | |
buf.writeUInt32LE(n, 1); | |
} else { | |
buf = new Buffer(1 + 8); | |
buf.writeUInt8(255, 0); | |
buf.writeInt32LE(n & -1, 1); | |
buf.writeUInt32LE(Math.floor(n / 0x100000000), 5); | |
} | |
return buf; | |
}; | |
BufferWriter.varintBufBN = function (bn) { | |
var buf = undefined; | |
var n = bn.toNumber(); | |
if (n < 253) { | |
buf = new Buffer(1); | |
buf.writeUInt8(n, 0); | |
} else if (n < 0x10000) { | |
buf = new Buffer(1 + 2); | |
buf.writeUInt8(253, 0); | |
buf.writeUInt16LE(n, 1); | |
} else if (n < 0x100000000) { | |
buf = new Buffer(1 + 4); | |
buf.writeUInt8(254, 0); | |
buf.writeUInt32LE(n, 1); | |
} else { | |
var bw = new BufferWriter(); | |
bw.writeUInt8(255); | |
bw.writeUInt64LEBN(bn); | |
var buf = bw.concat(); | |
} | |
return buf; | |
}; | |
module.exports = BufferWriter; | |
}).call(this,require("buffer").Buffer) | |
},{"../util/buffer":68,"assert":21,"buffer":148}],42:[function(require,module,exports){ | |
(function (Buffer){ | |
'use strict'; | |
var BufferWriter = require('./bufferwriter'); | |
var BufferReader = require('./bufferreader'); | |
var BN = require('../crypto/bn'); | |
var Varint = function Varint(buf) { | |
if (!(this instanceof Varint)) return new Varint(buf); | |
if (Buffer.isBuffer(buf)) { | |
this.buf = buf; | |
} else if (typeof buf === 'number') { | |
var num = buf; | |
this.fromNumber(num); | |
} else if (buf instanceof BN) { | |
var bn = buf; | |
this.fromBN(bn); | |
} else if (buf) { | |
var obj = buf; | |
this.set(obj); | |
} | |
}; | |
Varint.prototype.set = function (obj) { | |
this.buf = obj.buf || this.buf; | |
return this; | |
}; | |
Varint.prototype.fromString = function (str) { | |
this.set({ | |
buf: new Buffer(str, 'hex') | |
}); | |
return this; | |
}; | |
Varint.prototype.toString = function () { | |
return this.buf.toString('hex'); | |
}; | |
Varint.prototype.fromBuffer = function (buf) { | |
this.buf = buf; | |
return this; | |
}; | |
Varint.prototype.fromBufferReader = function (br) { | |
this.buf = br.readVarintBuf(); | |
return this; | |
}; | |
Varint.prototype.fromBN = function (bn) { | |
this.buf = BufferWriter().writeVarintBN(bn).concat(); | |
return this; | |
}; | |
Varint.prototype.fromNumber = function (num) { | |
this.buf = BufferWriter().writeVarintNum(num).concat(); | |
return this; | |
}; | |
Varint.prototype.toBuffer = function () { | |
return this.buf; | |
}; | |
Varint.prototype.toBN = function () { | |
return BufferReader(this.buf).readVarintBN(); | |
}; | |
Varint.prototype.toNumber = function () { | |
return BufferReader(this.buf).readVarintNum(); | |
}; | |
module.exports = Varint; | |
}).call(this,require("buffer").Buffer) | |
},{"../crypto/bn":32,"./bufferreader":40,"./bufferwriter":41,"buffer":148}],43:[function(require,module,exports){ | |
'use strict'; | |
var _ = require('lodash'); | |
function format(message, args) { | |
return message.replace('{0}', args[0]).replace('{1}', args[1]).replace('{2}', args[2]); | |
} | |
var traverseNode = function traverseNode(parent, errorDefinition) { | |
var NodeError = function NodeError() { | |
if (_.isString(errorDefinition.message)) { | |
this.message = format(errorDefinition.message, arguments); | |
} else if (_.isFunction(errorDefinition.message)) { | |
this.message = errorDefinition.message.apply(null, arguments); | |
} else { | |
throw new Error('Invalid error definition for ' + errorDefinition.name); | |
} | |
this.stack = this.message + '\n' + new Error().stack; | |
}; | |
NodeError.prototype = Object.create(parent.prototype); | |
NodeError.prototype.name = parent.prototype.name + errorDefinition.name; | |
parent[errorDefinition.name] = NodeError; | |
if (errorDefinition.errors) { | |
childDefinitions(NodeError, errorDefinition.errors); | |
} | |
return NodeError; | |
}; | |
/* jshint latedef: false */ | |
var childDefinitions = function childDefinitions(parent, _childDefinitions) { | |
_.each(_childDefinitions, function (childDefinition) { | |
traverseNode(parent, childDefinition); | |
}); | |
}; | |
/* jshint latedef: true */ | |
var traverseRoot = function traverseRoot(parent, errorsDefinition) { | |
childDefinitions(parent, errorsDefinition); | |
return parent; | |
}; | |
var bitcore = {}; | |
bitcore.Error = function () { | |
this.message = 'Internal error'; | |
this.stack = this.message + '\n' + new Error().stack; | |
}; | |
bitcore.Error.prototype = Object.create(Error.prototype); | |
bitcore.Error.prototype.name = 'bitcore.Error'; | |
var data = require('./spec'); | |
traverseRoot(bitcore.Error, data); | |
module.exports = bitcore.Error; | |
module.exports.extend = function (spec) { | |
return traverseNode(bitcore.Error, spec); | |
}; | |
},{"./spec":44,"lodash":267}],44:[function(require,module,exports){ | |
'use strict'; | |
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; | |
var docsURL = 'http://bitcore.io/'; | |
module.exports = [{ | |
name: 'InvalidB58Char', | |
message: 'Invalid Base58 character: {0} in {1}' | |
}, { | |
name: 'InvalidB58Checksum', | |
message: 'Invalid Base58 checksum for {0}' | |
}, { | |
name: 'InvalidNetwork', | |
message: 'Invalid version for network: got {0}' | |
}, { | |
name: 'InvalidState', | |
message: 'Invalid state: {0}' | |
}, { | |
name: 'NotImplemented', | |
message: 'Function {0} was not implemented yet' | |
}, { | |
name: 'InvalidNetworkArgument', | |
message: 'Invalid network: must be "livenet" or "testnet", got {0}' | |
}, { | |
name: 'InvalidArgument', | |
message: function message() { | |
return 'Invalid Argument' + (arguments[0] ? ': ' + arguments[0] : '') + (arguments[1] ? ' Documentation: ' + docsURL + arguments[1] : ''); | |
} | |
}, { | |
name: 'AbstractMethodInvoked', | |
message: 'Abstract Method Invocation: {0}' | |
}, { | |
name: 'InvalidArgumentType', | |
message: function message() { | |
return 'Invalid Argument for ' + arguments[2] + ', expected ' + arguments[1] + ' but got ' + _typeof(arguments[0]); | |
} | |
}, { | |
name: 'Unit', | |
message: 'Internal Error on Unit {0}', | |
errors: [{ | |
'name': 'UnknownCode', | |
'message': 'Unrecognized unit code: {0}' | |
}, { | |
'name': 'InvalidRate', | |
'message': 'Invalid exchange rate: {0}' | |
}] | |
}, { | |
name: 'MerkleBlock', | |
message: 'Internal Error on MerkleBlock {0}', | |
errors: [{ | |
'name': 'InvalidMerkleTree', | |
'message': 'This MerkleBlock contain an invalid Merkle Tree' | |
}] | |
}, { | |
name: 'Transaction', | |
message: 'Internal Error on Transaction {0}', | |
errors: [{ | |
name: 'Input', | |
message: 'Internal Error on Input {0}', | |
errors: [{ | |
name: 'MissingScript', | |
message: 'Need a script to create an input' | |
}, { | |
name: 'UnsupportedScript', | |
message: 'Unsupported input script type: {0}' | |
}, { | |
name: 'MissingPreviousOutput', | |
message: 'No previous output information.' | |
}] | |
}, { | |
name: 'NeedMoreInfo', | |
message: '{0}' | |
}, { | |
name: 'InvalidSorting', | |
message: 'The sorting function provided did not return the change output as one of the array elements' | |
}, { | |
name: 'InvalidOutputAmountSum', | |
message: '{0}' | |
}, { | |
name: 'MissingSignatures', | |
message: 'Some inputs have not been fully signed' | |
}, { | |
name: 'InvalidIndex', | |
message: 'Invalid index: {0} is not between 0, {1}' | |
}, { | |
name: 'UnableToVerifySignature', | |
message: 'Unable to verify signature: {0}' | |
}, { | |
name: 'DustOutputs', | |
message: 'Dust amount detected in one output' | |
}, { | |
name: 'InvalidSatoshis', | |
message: 'Output satoshis are invalid' | |
}, { | |
name: 'FeeError', | |
message: 'Internal Error on Fee {0}', | |
errors: [{ | |
name: 'TooSmall', | |
message: 'Fee is too small: {0}' | |
}, { | |
name: 'TooLarge', | |
message: 'Fee is too large: {0}' | |
}, { | |
name: 'Different', | |
message: 'Unspent value is different from specified fee: {0}' | |
}] | |
}, { | |
name: 'ChangeAddressMissing', | |
message: 'Change address is missing' | |
}, { | |
name: 'BlockHeightTooHigh', | |
message: 'Block Height can be at most 2^32 -1' | |
}, { | |
name: 'NLockTimeOutOfRange', | |
message: 'Block Height can only be between 0 and 499 999 999' | |
}, { | |
name: 'LockTimeTooEarly', | |
message: 'Lock Time can\'t be earlier than UNIX date 500 000 000' | |
}] | |
}, { | |
name: 'Script', | |
message: 'Internal Error on Script {0}', | |
errors: [{ | |
name: 'UnrecognizedAddress', | |
message: 'Expected argument {0} to be an address' | |
}, { | |
name: 'CantDeriveAddress', | |
message: 'Can\'t derive address associated with script {0}, needs to be p2pkh in, p2pkh out, p2sh in, or p2sh out.' | |
}, { | |
name: 'InvalidBuffer', | |
message: 'Invalid script buffer: can\'t parse valid script from given buffer {0}' | |
}] | |
}, { | |
name: 'HDPrivateKey', | |
message: 'Internal Error on HDPrivateKey {0}', | |
errors: [{ | |
name: 'InvalidDerivationArgument', | |
message: 'Invalid derivation argument {0}, expected string, or number and boolean' | |
}, { | |
name: 'InvalidEntropyArgument', | |
message: 'Invalid entropy: must be an hexa string or binary buffer, got {0}', | |
errors: [{ | |
name: 'TooMuchEntropy', | |
message: 'Invalid entropy: more than 512 bits is non standard, got "{0}"' | |
}, { | |
name: 'NotEnoughEntropy', | |
message: 'Invalid entropy: at least 128 bits needed, got "{0}"' | |
}] | |
}, { | |
name: 'InvalidLength', | |
message: 'Invalid length for xprivkey string in {0}' | |
}, { | |
name: 'InvalidPath', | |
message: 'Invalid derivation path: {0}' | |
}, { | |
name: 'UnrecognizedArgument', | |
message: 'Invalid argument: creating a HDPrivateKey requires a string, buffer, json or object, got "{0}"' | |
}] | |
}, { | |
name: 'HDPublicKey', | |
message: 'Internal Error on HDPublicKey {0}', | |
errors: [{ | |
name: 'ArgumentIsPrivateExtended', | |
message: 'Argument is an extended private key: {0}' | |
}, { | |
name: 'InvalidDerivationArgument', | |
message: 'Invalid derivation argument: got {0}' | |
}, { | |
name: 'InvalidLength', | |
message: 'Invalid length for xpubkey: got "{0}"' | |
}, { | |
name: 'InvalidPath', | |
message: 'Invalid derivation path, it should look like: "m/1/100", got "{0}"' | |
}, { | |
name: 'InvalidIndexCantDeriveHardened', | |
message: 'Invalid argument: creating a hardened path requires an HDPrivateKey' | |
}, { | |
name: 'MustSupplyArgument', | |
message: 'Must supply an argument to create a HDPublicKey' | |
}, { | |
name: 'UnrecognizedArgument', | |
message: 'Invalid argument for creation, must be string, json, buffer, or object' | |
}] | |
}]; | |
},{}],45:[function(require,module,exports){ | |
(function (Buffer){ | |
'use strict'; | |
var assert = require('assert'); | |
var buffer = require('buffer'); | |
var _ = require('lodash'); | |
var $ = require('./util/preconditions'); | |
var BN = require('./crypto/bn'); | |
var Base58 = require('./encoding/base58'); | |
var Base58Check = require('./encoding/base58check'); | |
var Hash = require('./crypto/hash'); | |
var Network = require('./networks'); | |
var Point = require('./crypto/point'); | |
var PrivateKey = require('./privatekey'); | |
var Random = require('./crypto/random'); | |
var errors = require('./errors'); | |
var hdErrors = errors.HDPrivateKey; | |
var BufferUtil = require('./util/buffer'); | |
var JSUtil = require('./util/js'); | |
var MINIMUM_ENTROPY_BITS = 128; | |
var BITS_TO_BYTES = 1 / 8; | |
var MAXIMUM_ENTROPY_BITS = 512; | |
/** | |
* Represents an instance of an hierarchically derived private key. | |
* | |
* More info on https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki | |
* | |
* @constructor | |
* @param {string|Buffer|Object} arg | |
*/ | |
function HDPrivateKey(arg) { | |
/* jshint maxcomplexity: 10 */ | |
if (arg instanceof HDPrivateKey) { | |
return arg; | |
} | |
if (!(this instanceof HDPrivateKey)) { | |
return new HDPrivateKey(arg); | |
} | |
if (!arg) { | |
return this._generateRandomly(); | |
} | |
if (Network.get(arg)) { | |
return this._generateRandomly(arg); | |
} else if (_.isString(arg) || BufferUtil.isBuffer(arg)) { | |
if (HDPrivateKey.isValidSerialized(arg)) { | |
this._buildFromSerialized(arg); | |
} else if (JSUtil.isValidJSON(arg)) { | |
this._buildFromJSON(arg); | |
} else if (BufferUtil.isBuffer(arg) && HDPrivateKey.isValidSerialized(arg.toString())) { | |
this._buildFromSerialized(arg.toString()); | |
} else { | |
throw HDPrivateKey.getSerializedError(arg); | |
} | |
} else if (_.isObject(arg)) { | |
this._buildFromObject(arg); | |
} else { | |
throw new hdErrors.UnrecognizedArgument(arg); | |
} | |
} | |
/** | |
* Verifies that a given path is valid. | |
* | |
* @param {string|number} arg | |
* @param {boolean?} hardened | |
* @return {boolean} | |
*/ | |
HDPrivateKey.isValidPath = function (arg, hardened) { | |
if (_.isString(arg)) { | |
var indexes = HDPrivateKey._getDerivationIndexes(arg); | |
return indexes !== null && _.every(indexes, HDPrivateKey.isValidPath); | |
} | |
if (_.isNumber(arg)) { | |
if (arg < HDPrivateKey.Hardened && hardened === true) { | |
arg += HDPrivateKey.Hardened; | |
} | |
return arg >= 0 && arg < HDPrivateKey.MaxIndex; | |
} | |
return false; | |
}; | |
/** | |
* Internal function that splits a string path into a derivation index array. | |
* It will return null if the string path is malformed. | |
* It does not validate if indexes are in bounds. | |
* | |
* @param {string} path | |
* @return {Array} | |
*/ | |
HDPrivateKey._getDerivationIndexes = function (path) { | |
var steps = path.split('/'); | |
// Special cases: | |
if (_.includes(HDPrivateKey.RootElementAlias, path)) { | |
return []; | |
} | |
if (!_.includes(HDPrivateKey.RootElementAlias, steps[0])) { | |
return null; | |
} | |
var indexes = steps.slice(1).map(function (step) { | |
var isHardened = step.slice(-1) === '\''; | |
if (isHardened) { | |
step = step.slice(0, -1); | |
} | |
if (!step || step[0] === '-') { | |
return NaN; | |
} | |
var index = +step; // cast to number | |
if (isHardened) { | |
index += HDPrivateKey.Hardened; | |
} | |
return index; | |
}); | |
return _.some(indexes, isNaN) ? null : indexes; | |
}; | |
/** | |
* WARNING: This method is deprecated. Use deriveChild or deriveNonCompliantChild instead. This is not BIP32 compliant | |
* | |
* | |
* Get a derived child based on a string or number. | |
* | |
* If the first argument is a string, it's parsed as the full path of | |
* derivation. Valid values for this argument include "m" (which returns the | |
* same private key), "m/0/1/40/2'/1000", where the ' quote means a hardened | |
* derivation. | |
* | |
* If the first argument is a number, the child with that index will be | |
* derived. If the second argument is truthy, the hardened version will be | |
* derived. See the example usage for clarification. | |
* | |
* @example | |
* ```javascript | |
* var parent = new HDPrivateKey('xprv...'); | |
* var child_0_1_2h = parent.derive(0).derive(1).derive(2, true); | |
* var copy_of_child_0_1_2h = parent.derive("m/0/1/2'"); | |
* assert(child_0_1_2h.xprivkey === copy_of_child_0_1_2h); | |
* ``` | |
* | |
* @param {string|number} arg | |
* @param {boolean?} hardened | |
*/ | |
HDPrivateKey.prototype.derive = function (arg, hardened) { | |
return this.deriveNonCompliantChild(arg, hardened); | |
}; | |
/** | |
* WARNING: This method will not be officially supported until v1.0.0. | |
* | |
* | |
* Get a derived child based on a string or number. | |
* | |
* If the first argument is a string, it's parsed as the full path of | |
* derivation. Valid values for this argument include "m" (which returns the | |
* same private key), "m/0/1/40/2'/1000", where the ' quote means a hardened | |
* derivation. | |
* | |
* If the first argument is a number, the child with that index will be | |
* derived. If the second argument is truthy, the hardened version will be | |
* derived. See the example usage for clarification. | |
* | |
* WARNING: The `nonCompliant` option should NOT be used, except for older implementation | |
* that used a derivation strategy that used a non-zero padded private key. | |
* | |
* @example | |
* ```javascript | |
* var parent = new HDPrivateKey('xprv...'); | |
* var child_0_1_2h = parent.deriveChild(0).deriveChild(1).deriveChild(2, true); | |
* var copy_of_child_0_1_2h = parent.deriveChild("m/0/1/2'"); | |
* assert(child_0_1_2h.xprivkey === copy_of_child_0_1_2h); | |
* ``` | |
* | |
* @param {string|number} arg | |
* @param {boolean?} hardened | |
*/ | |
HDPrivateKey.prototype.deriveChild = function (arg, hardened) { | |
if (_.isNumber(arg)) { | |
return this._deriveWithNumber(arg, hardened); | |
} else if (_.isString(arg)) { | |
return this._deriveFromString(arg); | |
} else { | |
throw new hdErrors.InvalidDerivationArgument(arg); | |
} | |
}; | |
/** | |
* WARNING: This method will not be officially supported until v1.0.0 | |
* | |
* | |
* WARNING: If this is a new implementation you should NOT use this method, you should be using | |
* `derive` instead. | |
* | |
* This method is explicitly for use and compatibility with an implementation that | |
* was not compliant with BIP32 regarding the derivation algorithm. The private key | |
* must be 32 bytes hashing, and this implementation will use the non-zero padded | |
* serialization of a private key, such that it's still possible to derive the privateKey | |
* to recover those funds. | |
* | |
* @param {string|number} arg | |
* @param {boolean?} hardened | |
*/ | |
HDPrivateKey.prototype.deriveNonCompliantChild = function (arg, hardened) { | |
if (_.isNumber(arg)) { | |
return this._deriveWithNumber(arg, hardened, true); | |
} else if (_.isString(arg)) { | |
return this._deriveFromString(arg, true); | |
} else { | |
throw new hdErrors.InvalidDerivationArgument(arg); | |
} | |
}; | |
HDPrivateKey.prototype._deriveWithNumber = function (index, hardened, nonCompliant) { | |
/* jshint maxstatements: 20 */ | |
/* jshint maxcomplexity: 10 */ | |
if (!HDPrivateKey.isValidPath(index, hardened)) { | |
throw new hdErrors.InvalidPath(index); | |
} | |
hardened = index >= HDPrivateKey.Hardened ? true : hardened; | |
if (index < HDPrivateKey.Hardened && hardened === true) { | |
index += HDPrivateKey.Hardened; | |
} | |
var indexBuffer = BufferUtil.integerAsBuffer(index); | |
var data; | |
if (hardened && nonCompliant) { | |
// The private key serialization in this case will not be exactly 32 bytes and can be | |
// any value less, and the value is not zero-padded. | |
var nonZeroPadded = this.privateKey.bn.toBuffer(); | |
data = BufferUtil.concat([new buffer.Buffer([0]), nonZeroPadded, indexBuffer]); | |
} else if (hardened) { | |
// This will use a 32 byte zero padded serialization of the private key | |
var privateKeyBuffer = this.privateKey.bn.toBuffer({ size: 32 }); | |
assert(privateKeyBuffer.length === 32, 'length of private key buffer is expected to be 32 bytes'); | |
data = BufferUtil.concat([new buffer.Buffer([0]), privateKeyBuffer, indexBuffer]); | |
} else { | |
data = BufferUtil.concat([this.publicKey.toBuffer(), indexBuffer]); | |
} | |
var hash = Hash.sha512hmac(data, this._buffers.chainCode); | |
var leftPart = BN.fromBuffer(hash.slice(0, 32), { | |
size: 32 | |
}); | |
var chainCode = hash.slice(32, 64); | |
var privateKey = leftPart.add(this.privateKey.toBigNumber()).umod(Point.getN()).toBuffer({ | |
size: 32 | |
}); | |
if (!PrivateKey.isValid(privateKey)) { | |
// Index at this point is already hardened, we can pass null as the hardened arg | |
return this._deriveWithNumber(index + 1, null, nonCompliant); | |
} | |
var derived = new HDPrivateKey({ | |
network: this.network, | |
depth: this.depth + 1, | |
parentFingerPrint: this.fingerPrint, | |
childIndex: index, | |
chainCode: chainCode, | |
privateKey: privateKey | |
}); | |
return derived; | |
}; | |
HDPrivateKey.prototype._deriveFromString = function (path, nonCompliant) { | |
if (!HDPrivateKey.isValidPath(path)) { | |
throw new hdErrors.InvalidPath(path); | |
} | |
var indexes = HDPrivateKey._getDerivationIndexes(path); | |
var derived = indexes.reduce(function (prev, index) { | |
return prev._deriveWithNumber(index, null, nonCompliant); | |
}, this); | |
return derived; | |
}; | |
/** | |
* Verifies that a given serialized private key in base58 with checksum format | |
* is valid. | |
* | |
* @param {string|Buffer} data - the serialized private key | |
* @param {string|Network=} network - optional, if present, checks that the | |
* network provided matches the network serialized. | |
* @return {boolean} | |
*/ | |
HDPrivateKey.isValidSerialized = function (data, network) { | |
return !HDPrivateKey.getSerializedError(data, network); | |
}; | |
/** | |
* Checks what's the error that causes the validation of a serialized private key | |
* in base58 with checksum to fail. | |
* | |
* @param {string|Buffer} data - the serialized private key | |
* @param {string|Network=} network - optional, if present, checks that the | |
* network provided matches the network serialized. | |
* @return {errors.InvalidArgument|null} | |
*/ | |
HDPrivateKey.getSerializedError = function (data, network) { | |
/* jshint maxcomplexity: 10 */ | |
if (!(_.isString(data) || BufferUtil.isBuffer(data))) { | |
return new hdErrors.UnrecognizedArgument('Expected string or buffer'); | |
} | |
if (!Base58.validCharacters(data)) { | |
return new errors.InvalidB58Char('(unknown)', data); | |
} | |
try { | |
data = Base58Check.decode(data); | |
} catch (e) { | |
return new errors.InvalidB58Checksum(data); | |
} | |
if (data.length !== HDPrivateKey.DataLength) { | |
return new hdErrors.InvalidLength(data); | |
} | |
if (!_.isUndefined(network)) { | |
var error = HDPrivateKey._validateNetwork(data, network); | |
if (error) { | |
return error; | |
} | |
} | |
return null; | |
}; | |
HDPrivateKey._validateNetwork = function (data, networkArg) { | |
var network = Network.get(networkArg); | |
if (!network) { | |
return new errors.InvalidNetworkArgument(networkArg); | |
} | |
var version = data.slice(0, 4); | |
if (BufferUtil.integerFromBuffer(version) !== network.xprivkey) { | |
return new errors.InvalidNetwork(version); | |
} | |
return null; | |
}; | |
HDPrivateKey.fromString = function (arg) { | |
$.checkArgument(_.isString(arg), 'No valid string was provided'); | |
return new HDPrivateKey(arg); | |
}; | |
HDPrivateKey.fromObject = function (arg) { | |
$.checkArgument(_.isObject(arg), 'No valid argument was provided'); | |
return new HDPrivateKey(arg); | |
}; | |
HDPrivateKey.prototype._buildFromJSON = function (arg) { | |
return this._buildFromObject(JSON.parse(arg)); | |
}; | |
HDPrivateKey.prototype._buildFromObject = function (arg) { | |
/* jshint maxcomplexity: 12 */ | |
// TODO: Type validation | |
var buffers = { | |
version: arg.network ? BufferUtil.integerAsBuffer(Network.get(arg.network).xprivkey) : arg.version, | |
depth: _.isNumber(arg.depth) ? BufferUtil.integerAsSingleByteBuffer(arg.depth) : arg.depth, | |
parentFingerPrint: _.isNumber(arg.parentFingerPrint) ? BufferUtil.integerAsBuffer(arg.parentFingerPrint) : arg.parentFingerPrint, | |
childIndex: _.isNumber(arg.childIndex) ? BufferUtil.integerAsBuffer(arg.childIndex) : arg.childIndex, | |
chainCode: _.isString(arg.chainCode) ? BufferUtil.hexToBuffer(arg.chainCode) : arg.chainCode, | |
privateKey: _.isString(arg.privateKey) && JSUtil.isHexa(arg.privateKey) ? BufferUtil.hexToBuffer(arg.privateKey) : arg.privateKey, | |
checksum: arg.checksum ? arg.checksum.length ? arg.checksum : BufferUtil.integerAsBuffer(arg.checksum) : undefined | |
}; | |
return this._buildFromBuffers(buffers); | |
}; | |
HDPrivateKey.prototype._buildFromSerialized = function (arg) { | |
var decoded = Base58Check.decode(arg); | |
var buffers = { | |
version: decoded.slice(HDPrivateKey.VersionStart, HDPrivateKey.VersionEnd), | |
depth: decoded.slice(HDPrivateKey.DepthStart, HDPrivateKey.DepthEnd), | |
parentFingerPrint: decoded.slice(HDPrivateKey.ParentFingerPrintStart, HDPrivateKey.ParentFingerPrintEnd), | |
childIndex: decoded.slice(HDPrivateKey.ChildIndexStart, HDPrivateKey.ChildIndexEnd), | |
chainCode: decoded.slice(HDPrivateKey.ChainCodeStart, HDPrivateKey.ChainCodeEnd), | |
privateKey: decoded.slice(HDPrivateKey.PrivateKeyStart, HDPrivateKey.PrivateKeyEnd), | |
checksum: decoded.slice(HDPrivateKey.ChecksumStart, HDPrivateKey.ChecksumEnd), | |
xprivkey: arg | |
}; | |
return this._buildFromBuffers(buffers); | |
}; | |
HDPrivateKey.prototype._generateRandomly = function (network) { | |
return HDPrivateKey.fromSeed(Random.getRandomBuffer(64), network); | |
}; | |
/** | |
* Generate a private key from a seed, as described in BIP32 | |
* | |
* @param {string|Buffer} hexa | |
* @param {*} network | |
* @return HDPrivateKey | |
*/ | |
HDPrivateKey.fromSeed = function (hexa, network) { | |
/* jshint maxcomplexity: 8 */ | |
if (JSUtil.isHexaString(hexa)) { | |
hexa = BufferUtil.hexToBuffer(hexa); | |
} | |
if (!Buffer.isBuffer(hexa)) { | |
throw new hdErrors.InvalidEntropyArgument(hexa); | |
} | |
if (hexa.length < MINIMUM_ENTROPY_BITS * BITS_TO_BYTES) { | |
throw new hdErrors.InvalidEntropyArgument.NotEnoughEntropy(hexa); | |
} | |
if (hexa.length > MAXIMUM_ENTROPY_BITS * BITS_TO_BYTES) { | |
throw new hdErrors.InvalidEntropyArgument.TooMuchEntropy(hexa); | |
} | |
var hash = Hash.sha512hmac(hexa, new buffer.Buffer('Bitcoin seed')); | |
return new HDPrivateKey({ | |
network: Network.get(network) || Network.defaultNetwork, | |
depth: 0, | |
parentFingerPrint: 0, | |
childIndex: 0, | |
privateKey: hash.slice(0, 32), | |
chainCode: hash.slice(32, 64) | |
}); | |
}; | |
HDPrivateKey.prototype._calcHDPublicKey = function () { | |
if (!this._hdPublicKey) { | |
var HDPublicKey = require('./hdpublickey'); | |
this._hdPublicKey = new HDPublicKey(this); | |
} | |
}; | |
/** | |
* Receives a object with buffers in all the properties and populates the | |
* internal structure | |
* | |
* @param {Object} arg | |
* @param {buffer.Buffer} arg.version | |
* @param {buffer.Buffer} arg.depth | |
* @param {buffer.Buffer} arg.parentFingerPrint | |
* @param {buffer.Buffer} arg.childIndex | |
* @param {buffer.Buffer} arg.chainCode | |
* @param {buffer.Buffer} arg.privateKey | |
* @param {buffer.Buffer} arg.checksum | |
* @param {string=} arg.xprivkey - if set, don't recalculate the base58 | |
* representation | |
* @return {HDPrivateKey} this | |
*/ | |
HDPrivateKey.prototype._buildFromBuffers = function (arg) { | |
/* jshint maxcomplexity: 8 */ | |
/* jshint maxstatements: 20 */ | |
HDPrivateKey._validateBufferArguments(arg); | |
JSUtil.defineImmutable(this, { | |
_buffers: arg | |
}); | |
var sequence = [arg.version, arg.depth, arg.parentFingerPrint, arg.childIndex, arg.chainCode, BufferUtil.emptyBuffer(1), arg.privateKey]; | |
var concat = buffer.Buffer.concat(sequence); | |
if (!arg.checksum || !arg.checksum.length) { | |
arg.checksum = Base58Check.checksum(concat); | |
} else { | |
if (arg.checksum.toString() !== Base58Check.checksum(concat).toString()) { | |
throw new errors.InvalidB58Checksum(concat); | |
} | |
} | |
var network = Network.get(BufferUtil.integerFromBuffer(arg.version)); | |
var xprivkey; | |
xprivkey = Base58Check.encode(buffer.Buffer.concat(sequence)); | |
arg.xprivkey = new Buffer(xprivkey); | |
var privateKey = new PrivateKey(BN.fromBuffer(arg.privateKey), network); | |
var publicKey = privateKey.toPublicKey(); | |
var size = HDPrivateKey.ParentFingerPrintSize; | |
var fingerPrint = Hash.sha256ripemd160(publicKey.toBuffer()).slice(0, size); | |
JSUtil.defineImmutable(this, { | |
xprivkey: xprivkey, | |
network: network, | |
depth: BufferUtil.integerFromSingleByteBuffer(arg.depth), | |
privateKey: privateKey, | |
publicKey: publicKey, | |
fingerPrint: fingerPrint | |
}); | |
this._hdPublicKey = null; | |
Object.defineProperty(this, 'hdPublicKey', { | |
configurable: false, | |
enumerable: true, | |
get: function get() { | |
this._calcHDPublicKey(); | |
return this._hdPublicKey; | |
} | |
}); | |
Object.defineProperty(this, 'xpubkey', { | |
configurable: false, | |
enumerable: true, | |
get: function get() { | |
this._calcHDPublicKey(); | |
return this._hdPublicKey.xpubkey; | |
} | |
}); | |
return this; | |
}; | |
HDPrivateKey._validateBufferArguments = function (arg) { | |
var checkBuffer = function checkBuffer(name, size) { | |
var buff = arg[name]; | |
assert(BufferUtil.isBuffer(buff), name + ' argument is not a buffer'); | |
assert(buff.length === size, name + ' has not the expected size: found ' + buff.length + ', expected ' + size); | |
}; | |
checkBuffer('version', HDPrivateKey.VersionSize); | |
checkBuffer('depth', HDPrivateKey.DepthSize); | |
checkBuffer('parentFingerPrint', HDPrivateKey.ParentFingerPrintSize); | |
checkBuffer('childIndex', HDPrivateKey.ChildIndexSize); | |
checkBuffer('chainCode', HDPrivateKey.ChainCodeSize); | |
checkBuffer('privateKey', HDPrivateKey.PrivateKeySize); | |
if (arg.checksum && arg.checksum.length) { | |
checkBuffer('checksum', HDPrivateKey.CheckSumSize); | |
} | |
}; | |
/** | |
* Returns the string representation of this private key (a string starting | |
* with "xprv..." | |
* | |
* @return string | |
*/ | |
HDPrivateKey.prototype.toString = function () { | |
return this.xprivkey; | |
}; | |
/** | |
* Returns the console representation of this extended private key. | |
* @return string | |
*/ | |
HDPrivateKey.prototype.inspect = function () { | |
return '<HDPrivateKey: ' + this.xprivkey + '>'; | |
}; | |
/** | |
* Returns a plain object with a representation of this private key. | |
* | |
* Fields include:<ul> | |
* <li> network: either 'livenet' or 'testnet' | |
* <li> depth: a number ranging from 0 to 255 | |
* <li> fingerPrint: a number ranging from 0 to 2^32-1, taken from the hash of the | |
* <li> associated public key | |
* <li> parentFingerPrint: a number ranging from 0 to 2^32-1, taken from the hash | |
* <li> of this parent's associated public key or zero. | |
* <li> childIndex: the index from which this child was derived (or zero) | |
* <li> chainCode: an hexa string representing a number used in the derivation | |
* <li> privateKey: the private key associated, in hexa representation | |
* <li> xprivkey: the representation of this extended private key in checksum | |
* <li> base58 format | |
* <li> checksum: the base58 checksum of xprivkey | |
* </ul> | |
* @return {Object} | |
*/ | |
HDPrivateKey.prototype.toObject = HDPrivateKey.prototype.toJSON = function toObject() { | |
return { | |
network: Network.get(BufferUtil.integerFromBuffer(this._buffers.version), 'xprivkey').name, | |
depth: BufferUtil.integerFromSingleByteBuffer(this._buffers.depth), | |
fingerPrint: BufferUtil.integerFromBuffer(this.fingerPrint), | |
parentFingerPrint: BufferUtil.integerFromBuffer(this._buffers.parentFingerPrint), | |
childIndex: BufferUtil.integerFromBuffer(this._buffers.childIndex), | |
chainCode: BufferUtil.bufferToHex(this._buffers.chainCode), | |
privateKey: this.privateKey.toBuffer().toString('hex'), | |
checksum: BufferUtil.integerFromBuffer(this._buffers.checksum), | |
xprivkey: this.xprivkey | |
}; | |
}; | |
/** | |
* Build a HDPrivateKey from a buffer | |
* | |
* @param {Buffer} arg | |
* @return {HDPrivateKey} | |
*/ | |
HDPrivateKey.fromBuffer = function (arg) { | |
return new HDPrivateKey(arg.toString()); | |
}; | |
/** | |
* Returns a buffer representation of the HDPrivateKey | |
* | |
* @return {string} | |
*/ | |
HDPrivateKey.prototype.toBuffer = function () { | |
return BufferUtil.copy(this._buffers.xprivkey); | |
}; | |
HDPrivateKey.DefaultDepth = 0; | |
HDPrivateKey.DefaultFingerprint = 0; | |
HDPrivateKey.DefaultChildIndex = 0; | |
HDPrivateKey.Hardened = 0x80000000; | |
HDPrivateKey.MaxIndex = 2 * HDPrivateKey.Hardened; | |
HDPrivateKey.RootElementAlias = ['m', 'M', 'm\'', 'M\'']; | |
HDPrivateKey.VersionSize = 4; | |
HDPrivateKey.DepthSize = 1; | |
HDPrivateKey.ParentFingerPrintSize = 4; | |
HDPrivateKey.ChildIndexSize = 4; | |
HDPrivateKey.ChainCodeSize = 32; | |
HDPrivateKey.PrivateKeySize = 32; | |
HDPrivateKey.CheckSumSize = 4; | |
HDPrivateKey.DataLength = 78; | |
HDPrivateKey.SerializedByteSize = 82; | |
HDPrivateKey.VersionStart = 0; | |
HDPrivateKey.VersionEnd = HDPrivateKey.VersionStart + HDPrivateKey.VersionSize; | |
HDPrivateKey.DepthStart = HDPrivateKey.VersionEnd; | |
HDPrivateKey.DepthEnd = HDPrivateKey.DepthStart + HDPrivateKey.DepthSize; | |
HDPrivateKey.ParentFingerPrintStart = HDPrivateKey.DepthEnd; | |
HDPrivateKey.ParentFingerPrintEnd = HDPrivateKey.ParentFingerPrintStart + HDPrivateKey.ParentFingerPrintSize; | |
HDPrivateKey.ChildIndexStart = HDPrivateKey.ParentFingerPrintEnd; | |
HDPrivateKey.ChildIndexEnd = HDPrivateKey.ChildIndexStart + HDPrivateKey.ChildIndexSize; | |
HDPrivateKey.ChainCodeStart = HDPrivateKey.ChildIndexEnd; | |
HDPrivateKey.ChainCodeEnd = HDPrivateKey.ChainCodeStart + HDPrivateKey.ChainCodeSize; | |
HDPrivateKey.PrivateKeyStart = HDPrivateKey.ChainCodeEnd + 1; | |
HDPrivateKey.PrivateKeyEnd = HDPrivateKey.PrivateKeyStart + HDPrivateKey.PrivateKeySize; | |
HDPrivateKey.ChecksumStart = HDPrivateKey.PrivateKeyEnd; | |
HDPrivateKey.ChecksumEnd = HDPrivateKey.ChecksumStart + HDPrivateKey.CheckSumSize; | |
assert(HDPrivateKey.ChecksumEnd === HDPrivateKey.SerializedByteSize); | |
module.exports = HDPrivateKey; | |
}).call(this,require("buffer").Buffer) | |
},{"./crypto/bn":32,"./crypto/hash":34,"./crypto/point":35,"./crypto/random":36,"./encoding/base58":38,"./encoding/base58check":39,"./errors":43,"./hdpublickey":46,"./networks":47,"./privatekey":49,"./util/buffer":68,"./util/js":69,"./util/preconditions":70,"assert":21,"buffer":148,"lodash":267}],46:[function(require,module,exports){ | |
(function (Buffer){ | |
'use strict'; | |
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; | |
var _ = require('lodash'); | |
var $ = require('./util/preconditions'); | |
var BN = require('./crypto/bn'); | |
var Base58 = require('./encoding/base58'); | |
var Base58Check = require('./encoding/base58check'); | |
var Hash = require('./crypto/hash'); | |
var HDPrivateKey = require('./hdprivatekey'); | |
var Network = require('./networks'); | |
var Point = require('./crypto/point'); | |
var PublicKey = require('./publickey'); | |
var bitcoreErrors = require('./errors'); | |
var errors = bitcoreErrors; | |
var hdErrors = bitcoreErrors.HDPublicKey; | |
var assert = require('assert'); | |
var JSUtil = require('./util/js'); | |
var BufferUtil = require('./util/buffer'); | |
/** | |
* The representation of an hierarchically derived public key. | |
* | |
* See https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki | |
* | |
* @constructor | |
* @param {Object|string|Buffer} arg | |
*/ | |
function HDPublicKey(arg) { | |
/* jshint maxcomplexity: 12 */ | |
/* jshint maxstatements: 20 */ | |
if (arg instanceof HDPublicKey) { | |
return arg; | |
} | |
if (!(this instanceof HDPublicKey)) { | |
return new HDPublicKey(arg); | |
} | |
if (arg) { | |
if (_.isString(arg) || BufferUtil.isBuffer(arg)) { | |
var error = HDPublicKey.getSerializedError(arg); | |
if (!error) { | |
return this._buildFromSerialized(arg); | |
} else if (BufferUtil.isBuffer(arg) && !HDPublicKey.getSerializedError(arg.toString())) { | |
return this._buildFromSerialized(arg.toString()); | |
} else { | |
if (error instanceof hdErrors.ArgumentIsPrivateExtended) { | |
return new HDPrivateKey(arg).hdPublicKey; | |
} | |
throw error; | |
} | |
} else { | |
if (_.isObject(arg)) { | |
if (arg instanceof HDPrivateKey) { | |
return this._buildFromPrivate(arg); | |
} else { | |
return this._buildFromObject(arg); | |
} | |
} else { | |
throw new hdErrors.UnrecognizedArgument(arg); | |
} | |
} | |
} else { | |
throw new hdErrors.MustSupplyArgument(); | |
} | |
} | |
/** | |
* Verifies that a given path is valid. | |
* | |
* @param {string|number} arg | |
* @return {boolean} | |
*/ | |
HDPublicKey.isValidPath = function (arg) { | |
if (_.isString(arg)) { | |
var indexes = HDPrivateKey._getDerivationIndexes(arg); | |
return indexes !== null && _.every(indexes, HDPublicKey.isValidPath); | |
} | |
if (_.isNumber(arg)) { | |
return arg >= 0 && arg < HDPublicKey.Hardened; | |
} | |
return false; | |
}; | |
/** | |
* WARNING: This method is deprecated. Use deriveChild instead. | |
* | |
* | |
* Get a derivated child based on a string or number. | |
* | |
* If the first argument is a string, it's parsed as the full path of | |
* derivation. Valid values for this argument include "m" (which returns the | |
* same public key), "m/0/1/40/2/1000". | |
* | |
* Note that hardened keys can't be derived from a public extended key. | |
* | |
* If the first argument is a number, the child with that index will be | |
* derived. See the example usage for clarification. | |
* | |
* @example | |
* ```javascript | |
* var parent = new HDPublicKey('xpub...'); | |
* var child_0_1_2 = parent.derive(0).derive(1).derive(2); | |
* var copy_of_child_0_1_2 = parent.derive("m/0/1/2"); | |
* assert(child_0_1_2.xprivkey === copy_of_child_0_1_2); | |
* ``` | |
* | |
* @param {string|number} arg | |
*/ | |
HDPublicKey.prototype.derive = function (arg, hardened) { | |
return this.deriveChild(arg, hardened); | |
}; | |
/** | |
* WARNING: This method will not be officially supported until v1.0.0. | |
* | |
* | |
* Get a derivated child based on a string or number. | |
* | |
* If the first argument is a string, it's parsed as the full path of | |
* derivation. Valid values for this argument include "m" (which returns the | |
* same public key), "m/0/1/40/2/1000". | |
* | |
* Note that hardened keys can't be derived from a public extended key. | |
* | |
* If the first argument is a number, the child with that index will be | |
* derived. See the example usage for clarification. | |
* | |
* @example | |
* ```javascript | |
* var parent = new HDPublicKey('xpub...'); | |
* var child_0_1_2 = parent.deriveChild(0).deriveChild(1).deriveChild(2); | |
* var copy_of_child_0_1_2 = parent.deriveChild("m/0/1/2"); | |
* assert(child_0_1_2.xprivkey === copy_of_child_0_1_2); | |
* ``` | |
* | |
* @param {string|number} arg | |
*/ | |
HDPublicKey.prototype.deriveChild = function (arg, hardened) { | |
if (_.isNumber(arg)) { | |
return this._deriveWithNumber(arg, hardened); | |
} else if (_.isString(arg)) { | |
return this._deriveFromString(arg); | |
} else { | |
throw new hdErrors.InvalidDerivationArgument(arg); | |
} | |
}; | |
HDPublicKey.prototype._deriveWithNumber = function (index, hardened) { | |
if (index >= HDPublicKey.Hardened || hardened) { | |
throw new hdErrors.InvalidIndexCantDeriveHardened(); | |
} | |
if (index < 0) { | |
throw new hdErrors.InvalidPath(index); | |
} | |
var indexBuffer = BufferUtil.integerAsBuffer(index); | |
var data = BufferUtil.concat([this.publicKey.toBuffer(), indexBuffer]); | |
var hash = Hash.sha512hmac(data, this._buffers.chainCode); | |
var leftPart = BN.fromBuffer(hash.slice(0, 32), { size: 32 }); | |
var chainCode = hash.slice(32, 64); | |
var publicKey; | |
try { | |
publicKey = PublicKey.fromPoint(Point.getG().mul(leftPart).add(this.publicKey.point)); | |
} catch (e) { | |
return this._deriveWithNumber(index + 1); | |
} | |
var derived = new HDPublicKey({ | |
network: this.network, | |
depth: this.depth + 1, | |
parentFingerPrint: this.fingerPrint, | |
childIndex: index, | |
chainCode: chainCode, | |
publicKey: publicKey | |
}); | |
return derived; | |
}; | |
HDPublicKey.prototype._deriveFromString = function (path) { | |
/* jshint maxcomplexity: 8 */ | |
if (_.includes(path, "'")) { | |
throw new hdErrors.InvalidIndexCantDeriveHardened(); | |
} else if (!HDPublicKey.isValidPath(path)) { | |
throw new hdErrors.InvalidPath(path); | |
} | |
var indexes = HDPrivateKey._getDerivationIndexes(path); | |
var derived = indexes.reduce(function (prev, index) { | |
return prev._deriveWithNumber(index); | |
}, this); | |
return derived; | |
}; | |
/** | |
* Verifies that a given serialized public key in base58 with checksum format | |
* is valid. | |
* | |
* @param {string|Buffer} data - the serialized public key | |
* @param {string|Network=} network - optional, if present, checks that the | |
* network provided matches the network serialized. | |
* @return {boolean} | |
*/ | |
HDPublicKey.isValidSerialized = function (data, network) { | |
return _.isNull(HDPublicKey.getSerializedError(data, network)); | |
}; | |
/** | |
* Checks what's the error that causes the validation of a serialized public key | |
* in base58 with checksum to fail. | |
* | |
* @param {string|Buffer} data - the serialized public key | |
* @param {string|Network=} network - optional, if present, checks that the | |
* network provided matches the network serialized. | |
* @return {errors|null} | |
*/ | |
HDPublicKey.getSerializedError = function (data, network) { | |
/* jshint maxcomplexity: 10 */ | |
/* jshint maxstatements: 20 */ | |
if (!(_.isString(data) || BufferUtil.isBuffer(data))) { | |
return new hdErrors.UnrecognizedArgument('expected buffer or string'); | |
} | |
if (!Base58.validCharacters(data)) { | |
return new errors.InvalidB58Char('(unknown)', data); | |
} | |
try { | |
data = Base58Check.decode(data); | |
} catch (e) { | |
return new errors.InvalidB58Checksum(data); | |
} | |
if (data.length !== HDPublicKey.DataSize) { | |
return new hdErrors.InvalidLength(data); | |
} | |
if (!_.isUndefined(network)) { | |
var error = HDPublicKey._validateNetwork(data, network); | |
if (error) { | |
return error; | |
} | |
} | |
var version = BufferUtil.integerFromBuffer(data.slice(0, 4)); | |
if (version === Network.livenet.xprivkey || version === Network.testnet.xprivkey) { | |
return new hdErrors.ArgumentIsPrivateExtended(); | |
} | |
return null; | |
}; | |
HDPublicKey._validateNetwork = function (data, networkArg) { | |
var network = Network.get(networkArg); | |
if (!network) { | |
return new errors.InvalidNetworkArgument(networkArg); | |
} | |
var version = data.slice(HDPublicKey.VersionStart, HDPublicKey.VersionEnd); | |
if (BufferUtil.integerFromBuffer(version) !== network.xpubkey) { | |
return new errors.InvalidNetwork(version); | |
} | |
return null; | |
}; | |
HDPublicKey.prototype._buildFromPrivate = function (arg) { | |
var args = _.clone(arg._buffers); | |
var point = Point.getG().mul(BN.fromBuffer(args.privateKey)); | |
args.publicKey = Point.pointToCompressed(point); | |
args.version = BufferUtil.integerAsBuffer(Network.get(BufferUtil.integerFromBuffer(args.version)).xpubkey); | |
args.privateKey = undefined; | |
args.checksum = undefined; | |
args.xprivkey = undefined; | |
return this._buildFromBuffers(args); | |
}; | |
HDPublicKey.prototype._buildFromObject = function (arg) { | |
/* jshint maxcomplexity: 10 */ | |
// TODO: Type validation | |
var buffers = { | |
version: arg.network ? BufferUtil.integerAsBuffer(Network.get(arg.network).xpubkey) : arg.version, | |
depth: _.isNumber(arg.depth) ? BufferUtil.integerAsSingleByteBuffer(arg.depth) : arg.depth, | |
parentFingerPrint: _.isNumber(arg.parentFingerPrint) ? BufferUtil.integerAsBuffer(arg.parentFingerPrint) : arg.parentFingerPrint, | |
childIndex: _.isNumber(arg.childIndex) ? BufferUtil.integerAsBuffer(arg.childIndex) : arg.childIndex, | |
chainCode: _.isString(arg.chainCode) ? BufferUtil.hexToBuffer(arg.chainCode) : arg.chainCode, | |
publicKey: _.isString(arg.publicKey) ? BufferUtil.hexToBuffer(arg.publicKey) : BufferUtil.isBuffer(arg.publicKey) ? arg.publicKey : arg.publicKey.toBuffer(), | |
checksum: _.isNumber(arg.checksum) ? BufferUtil.integerAsBuffer(arg.checksum) : arg.checksum | |
}; | |
return this._buildFromBuffers(buffers); | |
}; | |
HDPublicKey.prototype._buildFromSerialized = function (arg) { | |
var decoded = Base58Check.decode(arg); | |
var buffers = { | |
version: decoded.slice(HDPublicKey.VersionStart, HDPublicKey.VersionEnd), | |
depth: decoded.slice(HDPublicKey.DepthStart, HDPublicKey.DepthEnd), | |
parentFingerPrint: decoded.slice(HDPublicKey.ParentFingerPrintStart, HDPublicKey.ParentFingerPrintEnd), | |
childIndex: decoded.slice(HDPublicKey.ChildIndexStart, HDPublicKey.ChildIndexEnd), | |
chainCode: decoded.slice(HDPublicKey.ChainCodeStart, HDPublicKey.ChainCodeEnd), | |
publicKey: decoded.slice(HDPublicKey.PublicKeyStart, HDPublicKey.PublicKeyEnd), | |
checksum: decoded.slice(HDPublicKey.ChecksumStart, HDPublicKey.ChecksumEnd), | |
xpubkey: arg | |
}; | |
return this._buildFromBuffers(buffers); | |
}; | |
/** | |
* Receives a object with buffers in all the properties and populates the | |
* internal structure | |
* | |
* @param {Object} arg | |
* @param {buffer.Buffer} arg.version | |
* @param {buffer.Buffer} arg.depth | |
* @param {buffer.Buffer} arg.parentFingerPrint | |
* @param {buffer.Buffer} arg.childIndex | |
* @param {buffer.Buffer} arg.chainCode | |
* @param {buffer.Buffer} arg.publicKey | |
* @param {buffer.Buffer} arg.checksum | |
* @param {string=} arg.xpubkey - if set, don't recalculate the base58 | |
* representation | |
* @return {HDPublicKey} this | |
*/ | |
HDPublicKey.prototype._buildFromBuffers = function (arg) { | |
/* jshint maxcomplexity: 8 */ | |
/* jshint maxstatements: 20 */ | |
HDPublicKey._validateBufferArguments(arg); | |
JSUtil.defineImmutable(this, { | |
_buffers: arg | |
}); | |
var sequence = [arg.version, arg.depth, arg.parentFingerPrint, arg.childIndex, arg.chainCode, arg.publicKey]; | |
var concat = BufferUtil.concat(sequence); | |
var checksum = Base58Check.checksum(concat); | |
if (!arg.checksum || !arg.checksum.length) { | |
arg.checksum = checksum; | |
} else { | |
if (arg.checksum.toString('hex') !== checksum.toString('hex')) { | |
throw new errors.InvalidB58Checksum(concat, checksum); | |
} | |
} | |
var network = Network.get(BufferUtil.integerFromBuffer(arg.version)); | |
var xpubkey; | |
xpubkey = Base58Check.encode(BufferUtil.concat(sequence)); | |
arg.xpubkey = new Buffer(xpubkey); | |
var publicKey = new PublicKey(arg.publicKey, { network: network }); | |
var size = HDPublicKey.ParentFingerPrintSize; | |
var fingerPrint = Hash.sha256ripemd160(publicKey.toBuffer()).slice(0, size); | |
JSUtil.defineImmutable(this, { | |
xpubkey: xpubkey, | |
network: network, | |
depth: BufferUtil.integerFromSingleByteBuffer(arg.depth), | |
publicKey: publicKey, | |
fingerPrint: fingerPrint | |
}); | |
return this; | |
}; | |
HDPublicKey._validateBufferArguments = function (arg) { | |
var checkBuffer = function checkBuffer(name, size) { | |
var buff = arg[name]; | |
assert(BufferUtil.isBuffer(buff), name + ' argument is not a buffer, it\'s ' + (typeof buff === 'undefined' ? 'undefined' : _typeof(buff))); | |
assert(buff.length === size, name + ' has not the expected size: found ' + buff.length + ', expected ' + size); | |
}; | |
checkBuffer('version', HDPublicKey.VersionSize); | |
checkBuffer('depth', HDPublicKey.DepthSize); | |
checkBuffer('parentFingerPrint', HDPublicKey.ParentFingerPrintSize); | |
checkBuffer('childIndex', HDPublicKey.ChildIndexSize); | |
checkBuffer('chainCode', HDPublicKey.ChainCodeSize); | |
checkBuffer('publicKey', HDPublicKey.PublicKeySize); | |
if (arg.checksum && arg.checksum.length) { | |
checkBuffer('checksum', HDPublicKey.CheckSumSize); | |
} | |
}; | |
HDPublicKey.fromString = function (arg) { | |
$.checkArgument(_.isString(arg), 'No valid string was provided'); | |
return new HDPublicKey(arg); | |
}; | |
HDPublicKey.fromObject = function (arg) { | |
$.checkArgument(_.isObject(arg), 'No valid argument was provided'); | |
return new HDPublicKey(arg); | |
}; | |
/** | |
* Returns the base58 checked representation of the public key | |
* @return {string} a string starting with "xpub..." in livenet | |
*/ | |
HDPublicKey.prototype.toString = function () { | |
return this.xpubkey; | |
}; | |
/** | |
* Returns the console representation of this extended public key. | |
* @return string | |
*/ | |
HDPublicKey.prototype.inspect = function () { | |
return '<HDPublicKey: ' + this.xpubkey + '>'; | |
}; | |
/** | |
* Returns a plain JavaScript object with information to reconstruct a key. | |
* | |
* Fields are: <ul> | |
* <li> network: 'livenet' or 'testnet' | |
* <li> depth: a number from 0 to 255, the depth to the master extended key | |
* <li> fingerPrint: a number of 32 bits taken from the hash of the public key | |
* <li> fingerPrint: a number of 32 bits taken from the hash of this key's | |
* <li> parent's public key | |
* <li> childIndex: index with which this key was derived | |
* <li> chainCode: string in hexa encoding used for derivation | |
* <li> publicKey: string, hexa encoded, in compressed key format | |
* <li> checksum: BufferUtil.integerFromBuffer(this._buffers.checksum), | |
* <li> xpubkey: the string with the base58 representation of this extended key | |
* <li> checksum: the base58 checksum of xpubkey | |
* </ul> | |
*/ | |
HDPublicKey.prototype.toObject = HDPublicKey.prototype.toJSON = function toObject() { | |
return { | |
network: Network.get(BufferUtil.integerFromBuffer(this._buffers.version)).name, | |
depth: BufferUtil.integerFromSingleByteBuffer(this._buffers.depth), | |
fingerPrint: BufferUtil.integerFromBuffer(this.fingerPrint), | |
parentFingerPrint: BufferUtil.integerFromBuffer(this._buffers.parentFingerPrint), | |
childIndex: BufferUtil.integerFromBuffer(this._buffers.childIndex), | |
chainCode: BufferUtil.bufferToHex(this._buffers.chainCode), | |
publicKey: this.publicKey.toString(), | |
checksum: BufferUtil.integerFromBuffer(this._buffers.checksum), | |
xpubkey: this.xpubkey | |
}; | |
}; | |
/** | |
* Create a HDPublicKey from a buffer argument | |
* | |
* @param {Buffer} arg | |
* @return {HDPublicKey} | |
*/ | |
HDPublicKey.fromBuffer = function (arg) { | |
return new HDPublicKey(arg); | |
}; | |
/** | |
* Return a buffer representation of the xpubkey | |
* | |
* @return {Buffer} | |
*/ | |
HDPublicKey.prototype.toBuffer = function () { | |
return BufferUtil.copy(this._buffers.xpubkey); | |
}; | |
HDPublicKey.Hardened = 0x80000000; | |
HDPublicKey.RootElementAlias = ['m', 'M']; | |
HDPublicKey.VersionSize = 4; | |
HDPublicKey.DepthSize = 1; | |
HDPublicKey.ParentFingerPrintSize = 4; | |
HDPublicKey.ChildIndexSize = 4; | |
HDPublicKey.ChainCodeSize = 32; | |
HDPublicKey.PublicKeySize = 33; | |
HDPublicKey.CheckSumSize = 4; | |
HDPublicKey.DataSize = 78; | |
HDPublicKey.SerializedByteSize = 82; | |
HDPublicKey.VersionStart = 0; | |
HDPublicKey.VersionEnd = HDPublicKey.VersionStart + HDPublicKey.VersionSize; | |
HDPublicKey.DepthStart = HDPublicKey.VersionEnd; | |
HDPublicKey.DepthEnd = HDPublicKey.DepthStart + HDPublicKey.DepthSize; | |
HDPublicKey.ParentFingerPrintStart = HDPublicKey.DepthEnd; | |
HDPublicKey.ParentFingerPrintEnd = HDPublicKey.ParentFingerPrintStart + HDPublicKey.ParentFingerPrintSize; | |
HDPublicKey.ChildIndexStart = HDPublicKey.ParentFingerPrintEnd; | |
HDPublicKey.ChildIndexEnd = HDPublicKey.ChildIndexStart + HDPublicKey.ChildIndexSize; | |
HDPublicKey.ChainCodeStart = HDPublicKey.ChildIndexEnd; | |
HDPublicKey.ChainCodeEnd = HDPublicKey.ChainCodeStart + HDPublicKey.ChainCodeSize; | |
HDPublicKey.PublicKeyStart = HDPublicKey.ChainCodeEnd; | |
HDPublicKey.PublicKeyEnd = HDPublicKey.PublicKeyStart + HDPublicKey.PublicKeySize; | |
HDPublicKey.ChecksumStart = HDPublicKey.PublicKeyEnd; | |
HDPublicKey.ChecksumEnd = HDPublicKey.ChecksumStart + HDPublicKey.CheckSumSize; | |
assert(HDPublicKey.PublicKeyEnd === HDPublicKey.DataSize); | |
assert(HDPublicKey.ChecksumEnd === HDPublicKey.SerializedByteSize); | |
module.exports = HDPublicKey; | |
}).call(this,require("buffer").Buffer) | |
},{"./crypto/bn":32,"./crypto/hash":34,"./crypto/point":35,"./encoding/base58":38,"./encoding/base58check":39,"./errors":43,"./hdprivatekey":45,"./networks":47,"./publickey":50,"./util/buffer":68,"./util/js":69,"./util/preconditions":70,"assert":21,"buffer":148,"lodash":267}],47:[function(require,module,exports){ | |
'use strict'; | |
var _ = require('lodash'); | |
var BufferUtil = require('./util/buffer'); | |
var JSUtil = require('./util/js'); | |
var networks = []; | |
var networkMaps = {}; | |
/** | |
* A network is merely a map containing values that correspond to version | |
* numbers for each bitcoin network. Currently only supporting "livenet" | |
* (a.k.a. "mainnet") and "testnet". | |
* @constructor | |
*/ | |
function Network() {} | |
Network.prototype.toString = function toString() { | |
return this.name; | |
}; | |
/** | |
* @function | |
* @member Networks#get | |
* Retrieves the network associated with a magic number or string. | |
* @param {string|number|Network} arg | |
* @param {string|Array} keys - if set, only check if the magic number associated with this name matches | |
* @return Network | |
*/ | |
function get(arg, keys) { | |
if (~networks.indexOf(arg)) { | |
return arg; | |
} | |
if (keys) { | |
if (!_.isArray(keys)) { | |
keys = [keys]; | |
} | |
var containsArg = function containsArg(key) { | |
return networks[index][key] === arg; | |
}; | |
for (var index in networks) { | |
if (_.some(keys, containsArg)) { | |
return networks[index]; | |
} | |
} | |
return undefined; | |
} | |
return networkMaps[arg]; | |
} | |
/** | |
* @function | |
* @member Networks#add | |
* Will add a custom Network | |
* @param {Object} data | |
* @param {string} data.name - The name of the network | |
* @param {string} data.alias - The aliased name of the network | |
* @param {Number} data.pubkeyhash - The publickey hash prefix | |
* @param {Number} data.privatekey - The privatekey prefix | |
* @param {Number} data.scripthash - The scripthash prefix | |
* @param {Number} data.xpubkey - The extended public key magic | |
* @param {Number} data.xprivkey - The extended private key magic | |
* @param {Number} data.networkMagic - The network magic number | |
* @param {Number} data.port - The network port | |
* @param {Array} data.dnsSeeds - An array of dns seeds | |
* @return Network | |
*/ | |
function addNetwork(data) { | |
var network = new Network(); | |
JSUtil.defineImmutable(network, { | |
name: data.name, | |
alias: data.alias, | |
pubkeyhash: data.pubkeyhash, | |
privatekey: data.privatekey, | |
scripthash: data.scripthash, | |
xpubkey: data.xpubkey, | |
xprivkey: data.xprivkey | |
}); | |
if (data.networkMagic) { | |
JSUtil.defineImmutable(network, { | |
networkMagic: BufferUtil.integerAsBuffer(data.networkMagic) | |
}); | |
} | |
if (data.port) { | |
JSUtil.defineImmutable(network, { | |
port: data.port | |
}); | |
} | |
if (data.dnsSeeds) { | |
JSUtil.defineImmutable(network, { | |
dnsSeeds: data.dnsSeeds | |
}); | |
} | |
_.each(network, function (value) { | |
if (!_.isUndefined(value) && !_.isObject(value)) { | |
networkMaps[value] = network; | |
} | |
}); | |
networks.push(network); | |
return network; | |
} | |
/** | |
* @function | |
* @member Networks#remove | |
* Will remove a custom network | |
* @param {Network} network | |
*/ | |
function removeNetwork(network) { | |
for (var i = 0; i < networks.length; i++) { | |
if (networks[i] === network) { | |
networks.splice(i, 1); | |
} | |
} | |
for (var key in networkMaps) { | |
if (networkMaps[key] === network) { | |
delete networkMaps[key]; | |
} | |
} | |
} | |
addNetwork({ | |
name: 'livenet', | |
alias: 'mainnet', | |
pubkeyhash: 0x00, | |
privatekey: 0x80, | |
scripthash: 0x05, | |
xpubkey: 0x0488b21e, | |
xprivkey: 0x0488ade4, | |
networkMagic: 0xf9beb4d9, | |
port: 8333, | |
dnsSeeds: ['seed.bitcoin.sipa.be', 'dnsseed.bluematt.me', 'dnsseed.bitcoin.dashjr.org', 'seed.bitcoinstats.com', 'seed.bitnodes.io', 'bitseed.xf2.org'] | |
}); | |
/** | |
* @instance | |
* @member Networks#livenet | |
*/ | |
var livenet = get('livenet'); | |
addNetwork({ | |
name: 'testnet', | |
alias: 'regtest', | |
pubkeyhash: 0x6f, | |
privatekey: 0xef, | |
scripthash: 0xc4, | |
xpubkey: 0x043587cf, | |
xprivkey: 0x04358394 | |
}); | |
/** | |
* @instance | |
* @member Networks#testnet | |
*/ | |
var testnet = get('testnet'); | |
// Add configurable values for testnet/regtest | |
var TESTNET = { | |
PORT: 18333, | |
NETWORK_MAGIC: BufferUtil.integerAsBuffer(0x0b110907), | |
DNS_SEEDS: ['testnet-seed.bitcoin.petertodd.org', 'testnet-seed.bluematt.me', 'testnet-seed.alexykot.me', 'testnet-seed.bitcoin.schildbach.de'] | |
}; | |
for (var key in TESTNET) { | |
if (!_.isObject(TESTNET[key])) { | |
networkMaps[TESTNET[key]] = testnet; | |
} | |
} | |
var REGTEST = { | |
PORT: 18444, | |
NETWORK_MAGIC: BufferUtil.integerAsBuffer(0xfabfb5da), | |
DNS_SEEDS: [] | |
}; | |
for (var key in REGTEST) { | |
if (!_.isObject(REGTEST[key])) { | |
networkMaps[REGTEST[key]] = testnet; | |
} | |
} | |
Object.defineProperty(testnet, 'port', { | |
enumerable: true, | |
configurable: false, | |
get: function get() { | |
if (this.regtestEnabled) { | |
return REGTEST.PORT; | |
} else { | |
return TESTNET.PORT; | |
} | |
} | |
}); | |
Object.defineProperty(testnet, 'networkMagic', { | |
enumerable: true, | |
configurable: false, | |
get: function get() { | |
if (this.regtestEnabled) { | |
return REGTEST.NETWORK_MAGIC; | |
} else { | |
return TESTNET.NETWORK_MAGIC; | |
} | |
} | |
}); | |
Object.defineProperty(testnet, 'dnsSeeds', { | |
enumerable: true, | |
configurable: false, | |
get: function get() { | |
if (this.regtestEnabled) { | |
return REGTEST.DNS_SEEDS; | |
} else { | |
return TESTNET.DNS_SEEDS; | |
} | |
} | |
}); | |
/** | |
* @function | |
* @member Networks#enableRegtest | |
* Will enable regtest features for testnet | |
*/ | |
function enableRegtest() { | |
testnet.regtestEnabled = true; | |
} | |
/** | |
* @function | |
* @member Networks#disableRegtest | |
* Will disable regtest features for testnet | |
*/ | |
function disableRegtest() { | |
testnet.regtestEnabled = false; | |
} | |
/** | |
* @namespace Networks | |
*/ | |
module.exports = { | |
add: addNetwork, | |
remove: removeNetwork, | |
defaultNetwork: livenet, | |
livenet: livenet, | |
mainnet: livenet, | |
testnet: testnet, | |
get: get, | |
enableRegtest: enableRegtest, | |
disableRegtest: disableRegtest | |
}; | |
},{"./util/buffer":68,"./util/js":69,"lodash":267}],48:[function(require,module,exports){ | |
(function (Buffer){ | |
'use strict'; | |
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; | |
var _ = require('lodash'); | |
var $ = require('./util/preconditions'); | |
var BufferUtil = require('./util/buffer'); | |
var JSUtil = require('./util/js'); | |
function Opcode(num) { | |
if (!(this instanceof Opcode)) { | |
return new Opcode(num); | |
} | |
var value; | |
if (_.isNumber(num)) { | |
value = num; | |
} else if (_.isString(num)) { | |
value = Opcode.map[num]; | |
} else { | |
throw new TypeError('Unrecognized num type: "' + (typeof num === 'undefined' ? 'undefined' : _typeof(num)) + '" for Opcode'); | |
} | |
JSUtil.defineImmutable(this, { | |
num: value | |
}); | |
return this; | |
} | |
Opcode.fromBuffer = function (buf) { | |
$.checkArgument(BufferUtil.isBuffer(buf)); | |
return new Opcode(Number('0x' + buf.toString('hex'))); | |
}; | |
Opcode.fromNumber = function (num) { | |
$.checkArgument(_.isNumber(num)); | |
return new Opcode(num); | |
}; | |
Opcode.fromString = function (str) { | |
$.checkArgument(_.isString(str)); | |
var value = Opcode.map[str]; | |
if (typeof value === 'undefined') { | |
throw new TypeError('Invalid opcodestr'); | |
} | |
return new Opcode(value); | |
}; | |
Opcode.prototype.toHex = function () { | |
return this.num.toString(16); | |
}; | |
Opcode.prototype.toBuffer = function () { | |
return new Buffer(this.toHex(), 'hex'); | |
}; | |
Opcode.prototype.toNumber = function () { | |
return this.num; | |
}; | |
Opcode.prototype.toString = function () { | |
var str = Opcode.reverseMap[this.num]; | |
if (typeof str === 'undefined') { | |
throw new Error('Opcode does not have a string representation'); | |
} | |
return str; | |
}; | |
Opcode.smallInt = function (n) { | |
$.checkArgument(_.isNumber(n), 'Invalid Argument: n should be number'); | |
$.checkArgument(n >= 0 && n <= 16, 'Invalid Argument: n must be between 0 and 16'); | |
if (n === 0) { | |
return Opcode('OP_0'); | |
} | |
return new Opcode(Opcode.map.OP_1 + n - 1); | |
}; | |
Opcode.map = { | |
// push value | |
OP_FALSE: 0, | |
OP_0: 0, | |
OP_PUSHDATA1: 76, | |
OP_PUSHDATA2: 77, | |
OP_PUSHDATA4: 78, | |
OP_1NEGATE: 79, | |
OP_RESERVED: 80, | |
OP_TRUE: 81, | |
OP_1: 81, | |
OP_2: 82, | |
OP_3: 83, | |
OP_4: 84, | |
OP_5: 85, | |
OP_6: 86, | |
OP_7: 87, | |
OP_8: 88, | |
OP_9: 89, | |
OP_10: 90, | |
OP_11: 91, | |
OP_12: 92, | |
OP_13: 93, | |
OP_14: 94, | |
OP_15: 95, | |
OP_16: 96, | |
// control | |
OP_NOP: 97, | |
OP_VER: 98, | |
OP_IF: 99, | |
OP_NOTIF: 100, | |
OP_VERIF: 101, | |
OP_VERNOTIF: 102, | |
OP_ELSE: 103, | |
OP_ENDIF: 104, | |
OP_VERIFY: 105, | |
OP_RETURN: 106, | |
// stack ops | |
OP_TOALTSTACK: 107, | |
OP_FROMALTSTACK: 108, | |
OP_2DROP: 109, | |
OP_2DUP: 110, | |
OP_3DUP: 111, | |
OP_2OVER: 112, | |
OP_2ROT: 113, | |
OP_2SWAP: 114, | |
OP_IFDUP: 115, | |
OP_DEPTH: 116, | |
OP_DROP: 117, | |
OP_DUP: 118, | |
OP_NIP: 119, | |
OP_OVER: 120, | |
OP_PICK: 121, | |
OP_ROLL: 122, | |
OP_ROT: 123, | |
OP_SWAP: 124, | |
OP_TUCK: 125, | |
// splice ops | |
OP_CAT: 126, | |
OP_SUBSTR: 127, | |
OP_LEFT: 128, | |
OP_RIGHT: 129, | |
OP_SIZE: 130, | |
// bit logic | |
OP_INVERT: 131, | |
OP_AND: 132, | |
OP_OR: 133, | |
OP_XOR: 134, | |
OP_EQUAL: 135, | |
OP_EQUALVERIFY: 136, | |
OP_RESERVED1: 137, | |
OP_RESERVED2: 138, | |
// numeric | |
OP_1ADD: 139, | |
OP_1SUB: 140, | |
OP_2MUL: 141, | |
OP_2DIV: 142, | |
OP_NEGATE: 143, | |
OP_ABS: 144, | |
OP_NOT: 145, | |
OP_0NOTEQUAL: 146, | |
OP_ADD: 147, | |
OP_SUB: 148, | |
OP_MUL: 149, | |
OP_DIV: 150, | |
OP_MOD: 151, | |
OP_LSHIFT: 152, | |
OP_RSHIFT: 153, | |
OP_BOOLAND: 154, | |
OP_BOOLOR: 155, | |
OP_NUMEQUAL: 156, | |
OP_NUMEQUALVERIFY: 157, | |
OP_NUMNOTEQUAL: 158, | |
OP_LESSTHAN: 159, | |
OP_GREATERTHAN: 160, | |
OP_LESSTHANOREQUAL: 161, | |
OP_GREATERTHANOREQUAL: 162, | |
OP_MIN: 163, | |
OP_MAX: 164, | |
OP_WITHIN: 165, | |
// crypto | |
OP_RIPEMD160: 166, | |
OP_SHA1: 167, | |
OP_SHA256: 168, | |
OP_HASH160: 169, | |
OP_HASH256: 170, | |
OP_CODESEPARATOR: 171, | |
OP_CHECKSIG: 172, | |
OP_CHECKSIGVERIFY: 173, | |
OP_CHECKMULTISIG: 174, | |
OP_CHECKMULTISIGVERIFY: 175, | |
OP_CHECKLOCKTIMEVERIFY: 177, | |
// expansion | |
OP_NOP1: 176, | |
OP_NOP2: 177, | |
OP_NOP3: 178, | |
OP_NOP4: 179, | |
OP_NOP5: 180, | |
OP_NOP6: 181, | |
OP_NOP7: 182, | |
OP_NOP8: 183, | |
OP_NOP9: 184, | |
OP_NOP10: 185, | |
// template matching params | |
OP_PUBKEYHASH: 253, | |
OP_PUBKEY: 254, | |
OP_INVALIDOPCODE: 255 | |
}; | |
Opcode.reverseMap = []; | |
for (var k in Opcode.map) { | |
Opcode.reverseMap[Opcode.map[k]] = k; | |
} | |
// Easier access to opcodes | |
_.extend(Opcode, Opcode.map); | |
/** | |
* @returns true if opcode is one of OP_0, OP_1, ..., OP_16 | |
*/ | |
Opcode.isSmallIntOp = function (opcode) { | |
if (opcode instanceof Opcode) { | |
opcode = opcode.toNumber(); | |
} | |
return opcode === Opcode.map.OP_0 || opcode >= Opcode.map.OP_1 && opcode <= Opcode.map.OP_16; | |
}; | |
/** | |
* Will return a string formatted for the console | |
* | |
* @returns {string} Script opcode | |
*/ | |
Opcode.prototype.inspect = function () { | |
return '<Opcode: ' + this.toString() + ', hex: ' + this.toHex() + ', decimal: ' + this.num + '>'; | |
}; | |
module.exports = Opcode; | |
}).call(this,require("buffer").Buffer) | |
},{"./util/buffer":68,"./util/js":69,"./util/preconditions":70,"buffer":148,"lodash":267}],49:[function(require,module,exports){ | |
(function (Buffer){ | |
'use strict'; | |
var _ = require('lodash'); | |
var Address = require('./address'); | |
var Base58Check = require('./encoding/base58check'); | |
var BN = require('./crypto/bn'); | |
var JSUtil = require('./util/js'); | |
var Networks = require('./networks'); | |
var Point = require('./crypto/point'); | |
var PublicKey = require('./publickey'); | |
var Random = require('./crypto/random'); | |
var $ = require('./util/preconditions'); | |
/** | |
* Instantiate a PrivateKey from a BN, Buffer and WIF. | |
* | |
* @example | |
* ```javascript | |
* // generate a new random key | |
* var key = PrivateKey(); | |
* | |
* // get the associated address | |
* var address = key.toAddress(); | |
* | |
* // encode into wallet export format | |
* var exported = key.toWIF(); | |
* | |
* // instantiate from the exported (and saved) private key | |
* var imported = PrivateKey.fromWIF(exported); | |
* ``` | |
* | |
* @param {string} data - The encoded data in various formats | |
* @param {Network|string=} network - a {@link Network} object, or a string with the network name | |
* @returns {PrivateKey} A new valid instance of an PrivateKey | |
* @constructor | |
*/ | |
function PrivateKey(data, network) { | |
/* jshint maxstatements: 20 */ | |
/* jshint maxcomplexity: 8 */ | |
if (!(this instanceof PrivateKey)) { | |
return new PrivateKey(data, network); | |
} | |
if (data instanceof PrivateKey) { | |
return data; | |
} | |
var info = this._classifyArguments(data, network); | |
// validation | |
if (!info.bn || info.bn.cmp(new BN(0)) === 0) { | |
throw new TypeError('Number can not be equal to zero, undefined, null or false'); | |
} | |
if (!info.bn.lt(Point.getN())) { | |
throw new TypeError('Number must be less than N'); | |
} | |
if (typeof info.network === 'undefined') { | |
throw new TypeError('Must specify the network ("livenet" or "testnet")'); | |
} | |
JSUtil.defineImmutable(this, { | |
bn: info.bn, | |
compressed: info.compressed, | |
network: info.network | |
}); | |
Object.defineProperty(this, 'publicKey', { | |
configurable: false, | |
enumerable: true, | |
get: this.toPublicKey.bind(this) | |
}); | |
return this; | |
}; | |
/** | |
* Internal helper to instantiate PrivateKey internal `info` object from | |
* different kinds of arguments passed to the constructor. | |
* | |
* @param {*} data | |
* @param {Network|string=} network - a {@link Network} object, or a string with the network name | |
* @return {Object} | |
*/ | |
PrivateKey.prototype._classifyArguments = function (data, network) { | |
/* jshint maxcomplexity: 10 */ | |
var info = { | |
compressed: true, | |
network: network ? Networks.get(network) : Networks.defaultNetwork | |
}; | |
// detect type of data | |
if (_.isUndefined(data) || _.isNull(data)) { | |
info.bn = PrivateKey._getRandomBN(); | |
} else if (data instanceof BN) { | |
info.bn = data; | |
} else if (data instanceof Buffer || data instanceof Uint8Array) { | |
info = PrivateKey._transformBuffer(data, network); | |
} else if (data.bn && data.network) { | |
info = PrivateKey._transformObject(data); | |
} else if (!network && Networks.get(data)) { | |
info.bn = PrivateKey._getRandomBN(); | |
info.network = Networks.get(data); | |
} else if (typeof data === 'string') { | |
if (JSUtil.isHexa(data)) { | |
info.bn = new BN(new Buffer(data, 'hex')); | |
} else { | |
info = PrivateKey._transformWIF(data, network); | |
} | |
} else { | |
throw new TypeError('First argument is an unrecognized data type.'); | |
} | |
return info; | |
}; | |
/** | |
* Internal function to get a random Big Number (BN) | |
* | |
* @returns {BN} A new randomly generated BN | |
* @private | |
*/ | |
PrivateKey._getRandomBN = function () { | |
var condition; | |
var bn; | |
do { | |
var privbuf = Random.getRandomBuffer(32); | |
bn = BN.fromBuffer(privbuf); | |
condition = bn.lt(Point.getN()); | |
} while (!condition); | |
return bn; | |
}; | |
/** | |
* Internal function to transform a WIF Buffer into a private key | |
* | |
* @param {Buffer} buf - An WIF string | |
* @param {Network|string=} network - a {@link Network} object, or a string with the network name | |
* @returns {Object} An object with keys: bn, network and compressed | |
* @private | |
*/ | |
PrivateKey._transformBuffer = function (buf, network) { | |
var info = {}; | |
if (buf.length === 32) { | |
return PrivateKey._transformBNBuffer(buf, network); | |
} | |
info.network = Networks.get(buf[0], 'privatekey'); | |
if (!info.network) { | |
throw new Error('Invalid network'); | |
} | |
if (network && info.network !== Networks.get(network)) { | |
throw new TypeError('Private key network mismatch'); | |
} | |
if (buf.length === 1 + 32 + 1 && buf[1 + 32 + 1 - 1] === 1) { | |
info.compressed = true; | |
} else if (buf.length === 1 + 32) { | |
info.compressed = false; | |
} else { | |
throw new Error('Length of buffer must be 33 (uncompressed) or 34 (compressed)'); | |
} | |
info.bn = BN.fromBuffer(buf.slice(1, 32 + 1)); | |
return info; | |
}; | |
/** | |
* Internal function to transform a BN buffer into a private key | |
* | |
* @param {Buffer} buf | |
* @param {Network|string=} network - a {@link Network} object, or a string with the network name | |
* @returns {object} an Object with keys: bn, network, and compressed | |
* @private | |
*/ | |
PrivateKey._transformBNBuffer = function (buf, network) { | |
var info = {}; | |
info.network = Networks.get(network) || Networks.defaultNetwork; | |
info.bn = BN.fromBuffer(buf); | |
info.compressed = false; | |
return info; | |
}; | |
/** | |
* Internal function to transform a WIF string into a private key | |
* | |
* @param {string} buf - An WIF string | |
* @returns {Object} An object with keys: bn, network and compressed | |
* @private | |
*/ | |
PrivateKey._transformWIF = function (str, network) { | |
return PrivateKey._transformBuffer(Base58Check.decode(str), network); | |
}; | |
/** | |
* Instantiate a PrivateKey from a Buffer with the DER or WIF representation | |
* | |
* @param {Buffer} arg | |
* @param {Network} network | |
* @return {PrivateKey} | |
*/ | |
PrivateKey.fromBuffer = function (arg, network) { | |
return new PrivateKey(arg, network); | |
}; | |
/** | |
* Internal function to transform a JSON string on plain object into a private key | |
* return this. | |
* | |
* @param {string} json - A JSON string or plain object | |
* @returns {Object} An object with keys: bn, network and compressed | |
* @private | |
*/ | |
PrivateKey._transformObject = function (json) { | |
var bn = new BN(json.bn, 'hex'); | |
var network = Networks.get(json.network); | |
return { | |
bn: bn, | |
network: network, | |
compressed: json.compressed | |
}; | |
}; | |
/** | |
* Instantiate a PrivateKey from a WIF string | |
* | |
* @param {string} str - The WIF encoded private key string | |
* @returns {PrivateKey} A new valid instance of PrivateKey | |
*/ | |
PrivateKey.fromString = PrivateKey.fromWIF = function (str) { | |
$.checkArgument(_.isString(str), 'First argument is expected to be a string.'); | |
return new PrivateKey(str); | |
}; | |
/** | |
* Instantiate a PrivateKey from a plain JavaScript object | |
* | |
* @param {Object} obj - The output from privateKey.toObject() | |
*/ | |
PrivateKey.fromObject = function (obj) { | |
$.checkArgument(_.isObject(obj), 'First argument is expected to be an object.'); | |
return new PrivateKey(obj); | |
}; | |
/** | |
* Instantiate a PrivateKey from random bytes | |
* | |
* @param {string=} network - Either "livenet" or "testnet" | |
* @returns {PrivateKey} A new valid instance of PrivateKey | |
*/ | |
PrivateKey.fromRandom = function (network) { | |
var bn = PrivateKey._getRandomBN(); | |
return new PrivateKey(bn, network); | |
}; | |
/** | |
* Check if there would be any errors when initializing a PrivateKey | |
* | |
* @param {string} data - The encoded data in various formats | |
* @param {string=} network - Either "livenet" or "testnet" | |
* @returns {null|Error} An error if exists | |
*/ | |
PrivateKey.getValidationError = function (data, network) { | |
var error; | |
try { | |
/* jshint nonew: false */ | |
new PrivateKey(data, network); | |
} catch (e) { | |
error = e; | |
} | |
return error; | |
}; | |
/** | |
* Check if the parameters are valid | |
* | |
* @param {string} data - The encoded data in various formats | |
* @param {string=} network - Either "livenet" or "testnet" | |
* @returns {Boolean} If the private key is would be valid | |
*/ | |
PrivateKey.isValid = function (data, network) { | |
if (!data) { | |
return false; | |
} | |
return !PrivateKey.getValidationError(data, network); | |
}; | |
/** | |
* Will output the PrivateKey encoded as hex string | |
* | |
* @returns {string} | |
*/ | |
PrivateKey.prototype.toString = function () { | |
return this.toBuffer().toString('hex'); | |
}; | |
/** | |
* Will output the PrivateKey to a WIF string | |
* | |
* @returns {string} A WIP representation of the private key | |
*/ | |
PrivateKey.prototype.toWIF = function () { | |
var network = this.network; | |
var compressed = this.compressed; | |
var buf; | |
if (compressed) { | |
buf = Buffer.concat([new Buffer([network.privatekey]), this.bn.toBuffer({ size: 32 }), new Buffer([0x01])]); | |
} else { | |
buf = Buffer.concat([new Buffer([network.privatekey]), this.bn.toBuffer({ size: 32 })]); | |
} | |
return Base58Check.encode(buf); | |
}; | |
/** | |
* Will return the private key as a BN instance | |
* | |
* @returns {BN} A BN instance of the private key | |
*/ | |
PrivateKey.prototype.toBigNumber = function () { | |
return this.bn; | |
}; | |
/** | |
* Will return the private key as a BN buffer | |
* | |
* @returns {Buffer} A buffer of the private key | |
*/ | |
PrivateKey.prototype.toBuffer = function () { | |
// TODO: use `return this.bn.toBuffer({ size: 32 })` in v1.0.0 | |
return this.bn.toBuffer(); | |
}; | |
/** | |
* WARNING: This method will not be officially supported until v1.0.0. | |
* | |
* | |
* Will return the private key as a BN buffer without leading zero padding | |
* | |
* @returns {Buffer} A buffer of the private key | |
*/ | |
PrivateKey.prototype.toBufferNoPadding = function () { | |
return this.bn.toBuffer(); | |
}; | |
/** | |
* Will return the corresponding public key | |
* | |
* @returns {PublicKey} A public key generated from the private key | |
*/ | |
PrivateKey.prototype.toPublicKey = function () { | |
if (!this._pubkey) { | |
this._pubkey = PublicKey.fromPrivateKey(this); | |
} | |
return this._pubkey; | |
}; | |
/** | |
* Will return an address for the private key | |
* @param {Network=} network - optional parameter specifying | |
* the desired network for the address | |
* | |
* @returns {Address} An address generated from the private key | |
*/ | |
PrivateKey.prototype.toAddress = function (network) { | |
var pubkey = this.toPublicKey(); | |
return Address.fromPublicKey(pubkey, network || this.network); | |
}; | |
/** | |
* @returns {Object} A plain object representation | |
*/ | |
PrivateKey.prototype.toObject = PrivateKey.prototype.toJSON = function toObject() { | |
return { | |
bn: this.bn.toString('hex'), | |
compressed: this.compressed, | |
network: this.network.toString() | |
}; | |
}; | |
/** | |
* Will return a string formatted for the console | |
* | |
* @returns {string} Private key | |
*/ | |
PrivateKey.prototype.inspect = function () { | |
var uncompressed = !this.compressed ? ', uncompressed' : ''; | |
return '<PrivateKey: ' + this.toString() + ', network: ' + this.network + uncompressed + '>'; | |
}; | |
module.exports = PrivateKey; | |
}).call(this,require("buffer").Buffer) | |
},{"./address":27,"./crypto/bn":32,"./crypto/point":35,"./crypto/random":36,"./encoding/base58check":39,"./networks":47,"./publickey":50,"./util/js":69,"./util/preconditions":70,"buffer":148,"lodash":267}],50:[function(require,module,exports){ | |
(function (Buffer){ | |
'use strict'; | |
var BN = require('./crypto/bn'); | |
var Point = require('./crypto/point'); | |
var Hash = require('./crypto/hash'); | |
var JSUtil = require('./util/js'); | |
var Network = require('./networks'); | |
var _ = require('lodash'); | |
var $ = require('./util/preconditions'); | |
/** | |
* Instantiate a PublicKey from a {@link PrivateKey}, {@link Point}, `string`, or `Buffer`. | |
* | |
* There are two internal properties, `network` and `compressed`, that deal with importing | |
* a PublicKey from a PrivateKey in WIF format. More details described on {@link PrivateKey} | |
* | |
* @example | |
* ```javascript | |
* // instantiate from a private key | |
* var key = PublicKey(privateKey, true); | |
* | |
* // export to as a DER hex encoded string | |
* var exported = key.toString(); | |
* | |
* // import the public key | |
* var imported = PublicKey.fromString(exported); | |
* ``` | |
* | |
* @param {string} data - The encoded data in various formats | |
* @param {Object} extra - additional options | |
* @param {Network=} extra.network - Which network should the address for this public key be for | |
* @param {String=} extra.compressed - If the public key is compressed | |
* @returns {PublicKey} A new valid instance of an PublicKey | |
* @constructor | |
*/ | |
function PublicKey(data, extra) { | |
if (!(this instanceof PublicKey)) { | |
return new PublicKey(data, extra); | |
} | |
$.checkArgument(data, 'First argument is required, please include public key data.'); | |
if (data instanceof PublicKey) { | |
// Return copy, but as it's an immutable object, return same argument | |
return data; | |
} | |
extra = extra || {}; | |
var info = this._classifyArgs(data, extra); | |
// validation | |
info.point.validate(); | |
JSUtil.defineImmutable(this, { | |
point: info.point, | |
compressed: info.compressed, | |
network: info.network || Network.defaultNetwork | |
}); | |
return this; | |
}; | |
/** | |
* Internal function to differentiate between arguments passed to the constructor | |
* @param {*} data | |
* @param {Object} extra | |
*/ | |
PublicKey.prototype._classifyArgs = function (data, extra) { | |
/* jshint maxcomplexity: 10 */ | |
var info = { | |
compressed: _.isUndefined(extra.compressed) || extra.compressed | |
}; | |
// detect type of data | |
if (data instanceof Point) { | |
info.point = data; | |
} else if (data.x && data.y) { | |
info = PublicKey._transformObject(data); | |
} else if (typeof data === 'string') { | |
info = PublicKey._transformDER(new Buffer(data, 'hex')); | |
} else if (PublicKey._isBuffer(data)) { | |
info = PublicKey._transformDER(data); | |
} else if (PublicKey._isPrivateKey(data)) { | |
info = PublicKey._transformPrivateKey(data); | |
} else { | |
throw new TypeError('First argument is an unrecognized data format.'); | |
} | |
if (!info.network) { | |
info.network = _.isUndefined(extra.network) ? undefined : Network.get(extra.network); | |
} | |
return info; | |
}; | |
/** | |
* Internal function to detect if an object is a {@link PrivateKey} | |
* | |
* @param {*} param - object to test | |
* @returns {boolean} | |
* @private | |
*/ | |
PublicKey._isPrivateKey = function (param) { | |
var PrivateKey = require('./privatekey'); | |
return param instanceof PrivateKey; | |
}; | |
/** | |
* Internal function to detect if an object is a Buffer | |
* | |
* @param {*} param - object to test | |
* @returns {boolean} | |
* @private | |
*/ | |
PublicKey._isBuffer = function (param) { | |
return param instanceof Buffer || param instanceof Uint8Array; | |
}; | |
/** | |
* Internal function to transform a private key into a public key point | |
* | |
* @param {PrivateKey} privkey - An instance of PrivateKey | |
* @returns {Object} An object with keys: point and compressed | |
* @private | |
*/ | |
PublicKey._transformPrivateKey = function (privkey) { | |
$.checkArgument(PublicKey._isPrivateKey(privkey), 'Must be an instance of PrivateKey'); | |
var info = {}; | |
info.point = Point.getG().mul(privkey.bn); | |
info.compressed = privkey.compressed; | |
info.network = privkey.network; | |
return info; | |
}; | |
/** | |
* Internal function to transform DER into a public key point | |
* | |
* @param {Buffer} buf - An hex encoded buffer | |
* @param {bool=} strict - if set to false, will loosen some conditions | |
* @returns {Object} An object with keys: point and compressed | |
* @private | |
*/ | |
PublicKey._transformDER = function (buf, strict) { | |
/* jshint maxstatements: 30 */ | |
/* jshint maxcomplexity: 12 */ | |
$.checkArgument(PublicKey._isBuffer(buf), 'Must be a hex buffer of DER encoded public key'); | |
var info = {}; | |
strict = _.isUndefined(strict) ? true : strict; | |
var x; | |
var y; | |
var xbuf; | |
var ybuf; | |
if (buf[0] === 0x04 || !strict && (buf[0] === 0x06 || buf[0] === 0x07)) { | |
xbuf = buf.slice(1, 33); | |
ybuf = buf.slice(33, 65); | |
if (xbuf.length !== 32 || ybuf.length !== 32 || buf.length !== 65) { | |
throw new TypeError('Length of x and y must be 32 bytes'); | |
} | |
x = new BN(xbuf); | |
y = new BN(ybuf); | |
info.point = new Point(x, y); | |
info.compressed = false; | |
} else if (buf[0] === 0x03) { | |
xbuf = buf.slice(1); | |
x = new BN(xbuf); | |
info = PublicKey._transformX(true, x); | |
info.compressed = true; | |
} else if (buf[0] === 0x02) { | |
xbuf = buf.slice(1); | |
x = new BN(xbuf); | |
info = PublicKey._transformX(false, x); | |
info.compressed = true; | |
} else { | |
throw new TypeError('Invalid DER format public key'); | |
} | |
return info; | |
}; | |
/** | |
* Internal function to transform X into a public key point | |
* | |
* @param {Boolean} odd - If the point is above or below the x axis | |
* @param {Point} x - The x point | |
* @returns {Object} An object with keys: point and compressed | |
* @private | |
*/ | |
PublicKey._transformX = function (odd, x) { | |
$.checkArgument(typeof odd === 'boolean', 'Must specify whether y is odd or not (true or false)'); | |
var info = {}; | |
info.point = Point.fromX(odd, x); | |
return info; | |
}; | |
/** | |
* Internal function to transform a JSON into a public key point | |
* | |
* @param {String|Object} json - a JSON string or plain object | |
* @returns {Object} An object with keys: point and compressed | |
* @private | |
*/ | |
PublicKey._transformObject = function (json) { | |
var x = new BN(json.x, 'hex'); | |
var y = new BN(json.y, 'hex'); | |
var point = new Point(x, y); | |
return new PublicKey(point, { | |
compressed: json.compressed | |
}); | |
}; | |
/** | |
* Instantiate a PublicKey from a PrivateKey | |
* | |
* @param {PrivateKey} privkey - An instance of PrivateKey | |
* @returns {PublicKey} A new valid instance of PublicKey | |
*/ | |
PublicKey.fromPrivateKey = function (privkey) { | |
$.checkArgument(PublicKey._isPrivateKey(privkey), 'Must be an instance of PrivateKey'); | |
var info = PublicKey._transformPrivateKey(privkey); | |
return new PublicKey(info.point, { | |
compressed: info.compressed, | |
network: info.network | |
}); | |
}; | |
/** | |
* Instantiate a PublicKey from a Buffer | |
* @param {Buffer} buf - A DER hex buffer | |
* @param {bool=} strict - if set to false, will loosen some conditions | |
* @returns {PublicKey} A new valid instance of PublicKey | |
*/ | |
PublicKey.fromDER = PublicKey.fromBuffer = function (buf, strict) { | |
$.checkArgument(PublicKey._isBuffer(buf), 'Must be a hex buffer of DER encoded public key'); | |
var info = PublicKey._transformDER(buf, strict); | |
return new PublicKey(info.point, { | |
compressed: info.compressed | |
}); | |
}; | |
/** | |
* Instantiate a PublicKey from a Point | |
* | |
* @param {Point} point - A Point instance | |
* @param {boolean=} compressed - whether to store this public key as compressed format | |
* @returns {PublicKey} A new valid instance of PublicKey | |
*/ | |
PublicKey.fromPoint = function (point, compressed) { | |
$.checkArgument(point instanceof Point, 'First argument must be an instance of Point.'); | |
return new PublicKey(point, { | |
compressed: compressed | |
}); | |
}; | |
/** | |
* Instantiate a PublicKey from a DER hex encoded string | |
* | |
* @param {string} str - A DER hex string | |
* @param {String=} encoding - The type of string encoding | |
* @returns {PublicKey} A new valid instance of PublicKey | |
*/ | |
PublicKey.fromString = function (str, encoding) { | |
var buf = new Buffer(str, encoding || 'hex'); | |
var info = PublicKey._transformDER(buf); | |
return new PublicKey(info.point, { | |
compressed: info.compressed | |
}); | |
}; | |
/** | |
* Instantiate a PublicKey from an X Point | |
* | |
* @param {Boolean} odd - If the point is above or below the x axis | |
* @param {Point} x - The x point | |
* @returns {PublicKey} A new valid instance of PublicKey | |
*/ | |
PublicKey.fromX = function (odd, x) { | |
var info = PublicKey._transformX(odd, x); | |
return new PublicKey(info.point, { | |
compressed: info.compressed | |
}); | |
}; | |
/** | |
* Check if there would be any errors when initializing a PublicKey | |
* | |
* @param {string} data - The encoded data in various formats | |
* @returns {null|Error} An error if exists | |
*/ | |
PublicKey.getValidationError = function (data) { | |
var error; | |
try { | |
/* jshint nonew: false */ | |
new PublicKey(data); | |
} catch (e) { | |
error = e; | |
} | |
return error; | |
}; | |
/** | |
* Check if the parameters are valid | |
* | |
* @param {string} data - The encoded data in various formats | |
* @returns {Boolean} If the public key would be valid | |
*/ | |
PublicKey.isValid = function (data) { | |
return !PublicKey.getValidationError(data); | |
}; | |
/** | |
* @returns {Object} A plain object of the PublicKey | |
*/ | |
PublicKey.prototype.toObject = PublicKey.prototype.toJSON = function toObject() { | |
return { | |
x: this.point.getX().toString('hex', 2), | |
y: this.point.getY().toString('hex', 2), | |
compressed: this.compressed | |
}; | |
}; | |
/** | |
* Will output the PublicKey to a DER Buffer | |
* | |
* @returns {Buffer} A DER hex encoded buffer | |
*/ | |
PublicKey.prototype.toBuffer = PublicKey.prototype.toDER = function () { | |
var x = this.point.getX(); | |
var y = this.point.getY(); | |
var xbuf = x.toBuffer({ | |
size: 32 | |
}); | |
var ybuf = y.toBuffer({ | |
size: 32 | |
}); | |
var prefix; | |
if (!this.compressed) { | |
prefix = new Buffer([0x04]); | |
return Buffer.concat([prefix, xbuf, ybuf]); | |
} else { | |
var odd = ybuf[ybuf.length - 1] % 2; | |
if (odd) { | |
prefix = new Buffer([0x03]); | |
} else { | |
prefix = new Buffer([0x02]); | |
} | |
return Buffer.concat([prefix, xbuf]); | |
} | |
}; | |
/** | |
* Will return a sha256 + ripemd160 hash of the serialized public key | |
* @see https://github.com/bitcoin/bitcoin/blob/master/src/pubkey.h#L141 | |
* @returns {Buffer} | |
*/ | |
PublicKey.prototype._getID = function _getID() { | |
return Hash.sha256ripemd160(this.toBuffer()); | |
}; | |
/** | |
* Will return an address for the public key | |
* | |
* @param {String|Network=} network - Which network should the address be for | |
* @returns {Address} An address generated from the public key | |
*/ | |
PublicKey.prototype.toAddress = function (network) { | |
var Address = require('./address'); | |
return Address.fromPublicKey(this, network || this.network); | |
}; | |
/** | |
* Will output the PublicKey to a DER encoded hex string | |
* | |
* @returns {string} A DER hex encoded string | |
*/ | |
PublicKey.prototype.toString = function () { | |
return this.toDER().toString('hex'); | |
}; | |
/** | |
* Will return a string formatted for the console | |
* | |
* @returns {string} Public key | |
*/ | |
PublicKey.prototype.inspect = function () { | |
return '<PublicKey: ' + this.toString() + (this.compressed ? '' : ', uncompressed') + '>'; | |
}; | |
module.exports = PublicKey; | |
}).call(this,require("buffer").Buffer) | |
},{"./address":27,"./crypto/bn":32,"./crypto/hash":34,"./crypto/point":35,"./networks":47,"./privatekey":49,"./util/js":69,"./util/preconditions":70,"buffer":148,"lodash":267}],51:[function(require,module,exports){ | |
'use strict'; | |
module.exports = require('./script'); | |
module.exports.Interpreter = require('./interpreter'); | |
},{"./interpreter":52,"./script":53}],52:[function(require,module,exports){ | |
(function (Buffer){ | |
'use strict'; | |
var _ = require('lodash'); | |
var Script = require('./script'); | |
var Opcode = require('../opcode'); | |
var BN = require('../crypto/bn'); | |
var Hash = require('../crypto/hash'); | |
var Signature = require('../crypto/signature'); | |
var PublicKey = require('../publickey'); | |
/** | |
* Bitcoin transactions contain scripts. Each input has a script called the | |
* scriptSig, and each output has a script called the scriptPubkey. To validate | |
* an input, the input's script is concatenated with the referenced output script, | |
* and the result is executed. If at the end of execution the stack contains a | |
* "true" value, then the transaction is valid. | |
* | |
* The primary way to use this class is via the verify function. | |
* e.g., Interpreter().verify( ... ); | |
*/ | |
var Interpreter = function Interpreter(obj) { | |
if (!(this instanceof Interpreter)) { | |
return new Interpreter(obj); | |
} | |
if (obj) { | |
this.initialize(); | |
this.set(obj); | |
} else { | |
this.initialize(); | |
} | |
}; | |
/** | |
* Verifies a Script by executing it and returns true if it is valid. | |
* This function needs to be provided with the scriptSig and the scriptPubkey | |
* separately. | |
* @param {Script} scriptSig - the script's first part (corresponding to the tx input) | |
* @param {Script} scriptPubkey - the script's last part (corresponding to the tx output) | |
* @param {Transaction=} tx - the Transaction containing the scriptSig in one input (used | |
* to check signature validity for some opcodes like OP_CHECKSIG) | |
* @param {number} nin - index of the transaction input containing the scriptSig verified. | |
* @param {number} flags - evaluation flags. See Interpreter.SCRIPT_* constants | |
* | |
* Translated from bitcoind's VerifyScript | |
*/ | |
Interpreter.prototype.verify = function (scriptSig, scriptPubkey, tx, nin, flags) { | |
var Transaction = require('../transaction'); | |
if (_.isUndefined(tx)) { | |
tx = new Transaction(); | |
} | |
if (_.isUndefined(nin)) { | |
nin = 0; | |
} | |
if (_.isUndefined(flags)) { | |
flags = 0; | |
} | |
this.set({ | |
script: scriptSig, | |
tx: tx, | |
nin: nin, | |
flags: flags | |
}); | |
var stackCopy; | |
if ((flags & Interpreter.SCRIPT_VERIFY_SIGPUSHONLY) !== 0 && !scriptSig.isPushOnly()) { | |
this.errstr = 'SCRIPT_ERR_SIG_PUSHONLY'; | |
return false; | |
} | |
// evaluate scriptSig | |
if (!this.evaluate()) { | |
return false; | |
} | |
if (flags & Interpreter.SCRIPT_VERIFY_P2SH) { | |
stackCopy = this.stack.slice(); | |
} | |
var stack = this.stack; | |
this.initialize(); | |
this.set({ | |
script: scriptPubkey, | |
stack: stack, | |
tx: tx, | |
nin: nin, | |
flags: flags | |
}); | |
// evaluate scriptPubkey | |
if (!this.evaluate()) { | |
return false; | |
} | |
if (this.stack.length === 0) { | |
this.errstr = 'SCRIPT_ERR_EVAL_FALSE_NO_RESULT'; | |
return false; | |
} | |
var buf = this.stack[this.stack.length - 1]; | |
if (!Interpreter.castToBool(buf)) { | |
this.errstr = 'SCRIPT_ERR_EVAL_FALSE_IN_STACK'; | |
return false; | |
} | |
// Additional validation for spend-to-script-hash transactions: | |
if (flags & Interpreter.SCRIPT_VERIFY_P2SH && scriptPubkey.isScriptHashOut()) { | |
// scriptSig must be literals-only or validation fails | |
if (!scriptSig.isPushOnly()) { | |
this.errstr = 'SCRIPT_ERR_SIG_PUSHONLY'; | |
return false; | |
} | |
// stackCopy cannot be empty here, because if it was the | |
// P2SH HASH <> EQUAL scriptPubKey would be evaluated with | |
// an empty stack and the EvalScript above would return false. | |
if (stackCopy.length === 0) { | |
throw new Error('internal error - stack copy empty'); | |
} | |
var redeemScriptSerialized = stackCopy[stackCopy.length - 1]; | |
var redeemScript = Script.fromBuffer(redeemScriptSerialized); | |
stackCopy.pop(); | |
this.initialize(); | |
this.set({ | |
script: redeemScript, | |
stack: stackCopy, | |
tx: tx, | |
nin: nin, | |
flags: flags | |
}); | |
// evaluate redeemScript | |
if (!this.evaluate()) { | |
return false; | |
} | |
if (stackCopy.length === 0) { | |
this.errstr = 'SCRIPT_ERR_EVAL_FALSE_NO_P2SH_STACK'; | |
return false; | |
} | |
if (!Interpreter.castToBool(stackCopy[stackCopy.length - 1])) { | |
this.errstr = 'SCRIPT_ERR_EVAL_FALSE_IN_P2SH_STACK'; | |
return false; | |
} else { | |
return true; | |
} | |
} | |
return true; | |
}; | |
module.exports = Interpreter; | |
Interpreter.prototype.initialize = function (obj) { | |
this.stack = []; | |
this.altstack = []; | |
this.pc = 0; | |
this.pbegincodehash = 0; | |
this.nOpCount = 0; | |
this.vfExec = []; | |
this.errstr = ''; | |
this.flags = 0; | |
}; | |
Interpreter.prototype.set = function (obj) { | |
this.script = obj.script || this.script; | |
this.tx = obj.tx || this.tx; | |
this.nin = typeof obj.nin !== 'undefined' ? obj.nin : this.nin; | |
this.stack = obj.stack || this.stack; | |
this.altstack = obj.altack || this.altstack; | |
this.pc = typeof obj.pc !== 'undefined' ? obj.pc : this.pc; | |
this.pbegincodehash = typeof obj.pbegincodehash !== 'undefined' ? obj.pbegincodehash : this.pbegincodehash; | |
this.nOpCount = typeof obj.nOpCount !== 'undefined' ? obj.nOpCount : this.nOpCount; | |
this.vfExec = obj.vfExec || this.vfExec; | |
this.errstr = obj.errstr || this.errstr; | |
this.flags = typeof obj.flags !== 'undefined' ? obj.flags : this.flags; | |
}; | |
Interpreter.true = new Buffer([1]); | |
Interpreter.false = new Buffer([]); | |
Interpreter.MAX_SCRIPT_ELEMENT_SIZE = 520; | |
Interpreter.LOCKTIME_THRESHOLD = 500000000; | |
Interpreter.LOCKTIME_THRESHOLD_BN = new BN(Interpreter.LOCKTIME_THRESHOLD); | |
// flags taken from bitcoind | |
// bitcoind commit: b5d1b1092998bc95313856d535c632ea5a8f9104 | |
Interpreter.SCRIPT_VERIFY_NONE = 0; | |
// Evaluate P2SH subscripts (softfork safe, BIP16). | |
Interpreter.SCRIPT_VERIFY_P2SH = 1 << 0; | |
// Passing a non-strict-DER signature or one with undefined hashtype to a checksig operation causes script failure. | |
// Passing a pubkey that is not (0x04 + 64 bytes) or (0x02 or 0x03 + 32 bytes) to checksig causes that pubkey to be | |
// skipped (not softfork safe: this flag can widen the validity of OP_CHECKSIG OP_NOT). | |
Interpreter.SCRIPT_VERIFY_STRICTENC = 1 << 1; | |
// Passing a non-strict-DER signature to a checksig operation causes script failure (softfork safe, BIP62 rule 1) | |
Interpreter.SCRIPT_VERIFY_DERSIG = 1 << 2; | |
// Passing a non-strict-DER signature or one with S > order/2 to a checksig operation causes script failure | |
// (softfork safe, BIP62 rule 5). | |
Interpreter.SCRIPT_VERIFY_LOW_S = 1 << 3; | |
// verify dummy stack item consumed by CHECKMULTISIG is of zero-length (softfork safe, BIP62 rule 7). | |
Interpreter.SCRIPT_VERIFY_NULLDUMMY = 1 << 4; | |
// Using a non-push operator in the scriptSig causes script failure (softfork safe, BIP62 rule 2). | |
Interpreter.SCRIPT_VERIFY_SIGPUSHONLY = 1 << 5; | |
// Require minimal encodings for all push operations (OP_0... OP_16, OP_1NEGATE where possible, direct | |
// pushes up to 75 bytes, OP_PUSHDATA up to 255 bytes, OP_PUSHDATA2 for anything larger). Evaluating | |
// any other push causes the script to fail (BIP62 rule 3). | |
// In addition, whenever a stack element is interpreted as a number, it must be of minimal length (BIP62 rule 4). | |
// (softfork safe) | |
Interpreter.SCRIPT_VERIFY_MINIMALDATA = 1 << 6; | |
// Discourage use of NOPs reserved for upgrades (NOP1-10) | |
// | |
// Provided so that nodes can avoid accepting or mining transactions | |
// containing executed NOP's whose meaning may change after a soft-fork, | |
// thus rendering the script invalid; with this flag set executing | |
// discouraged NOPs fails the script. This verification flag will never be | |
// a mandatory flag applied to scripts in a block. NOPs that are not | |
// executed, e.g. within an unexecuted IF ENDIF block, are *not* rejected. | |
Interpreter.SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS = 1 << 7; | |
// CLTV See BIP65 for details. | |
Interpreter.SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY = 1 << 9; | |
Interpreter.castToBool = function (buf) { | |
for (var i = 0; i < buf.length; i++) { | |
if (buf[i] !== 0) { | |
// can be negative zero | |
if (i === buf.length - 1 && buf[i] === 0x80) { | |
return false; | |
} | |
return true; | |
} | |
} | |
return false; | |
}; | |
/** | |
* Translated from bitcoind's CheckSignatureEncoding | |
*/ | |
Interpreter.prototype.checkSignatureEncoding = function (buf) { | |
var sig; | |
if ((this.flags & (Interpreter.SCRIPT_VERIFY_DERSIG | Interpreter.SCRIPT_VERIFY_LOW_S | Interpreter.SCRIPT_VERIFY_STRICTENC)) !== 0 && !Signature.isTxDER(buf)) { | |
this.errstr = 'SCRIPT_ERR_SIG_DER_INVALID_FORMAT'; | |
return false; | |
} else if ((this.flags & Interpreter.SCRIPT_VERIFY_LOW_S) !== 0) { | |
sig = Signature.fromTxFormat(buf); | |
if (!sig.hasLowS()) { | |
this.errstr = 'SCRIPT_ERR_SIG_DER_HIGH_S'; | |
return false; | |
} | |
} else if ((this.flags & Interpreter.SCRIPT_VERIFY_STRICTENC) !== 0) { | |
sig = Signature.fromTxFormat(buf); | |
if (!sig.hasDefinedHashtype()) { | |
this.errstr = 'SCRIPT_ERR_SIG_HASHTYPE'; | |
return false; | |
} | |
} | |
return true; | |
}; | |
/** | |
* Translated from bitcoind's CheckPubKeyEncoding | |
*/ | |
Interpreter.prototype.checkPubkeyEncoding = function (buf) { | |
if ((this.flags & Interpreter.SCRIPT_VERIFY_STRICTENC) !== 0 && !PublicKey.isValid(buf)) { | |
this.errstr = 'SCRIPT_ERR_PUBKEYTYPE'; | |
return false; | |
} | |
return true; | |
}; | |
/** | |
* Based on bitcoind's EvalScript function, with the inner loop moved to | |
* Interpreter.prototype.step() | |
* bitcoind commit: b5d1b1092998bc95313856d535c632ea5a8f9104 | |
*/ | |
Interpreter.prototype.evaluate = function () { | |
if (this.script.toBuffer().length > 10000) { | |
this.errstr = 'SCRIPT_ERR_SCRIPT_SIZE'; | |
return false; | |
} | |
try { | |
while (this.pc < this.script.chunks.length) { | |
var fSuccess = this.step(); | |
if (!fSuccess) { | |
return false; | |
} | |
} | |
// Size limits | |
if (this.stack.length + this.altstack.length > 1000) { | |
this.errstr = 'SCRIPT_ERR_STACK_SIZE'; | |
return false; | |
} | |
} catch (e) { | |
this.errstr = 'SCRIPT_ERR_UNKNOWN_ERROR: ' + e; | |
return false; | |
} | |
if (this.vfExec.length > 0) { | |
this.errstr = 'SCRIPT_ERR_UNBALANCED_CONDITIONAL'; | |
return false; | |
} | |
return true; | |
}; | |
/** | |
* Checks a locktime parameter with the transaction's locktime. | |
* There are two times of nLockTime: lock-by-blockheight and lock-by-blocktime, | |
* distinguished by whether nLockTime < LOCKTIME_THRESHOLD = 500000000 | |
* | |
* See the corresponding code on bitcoin core: | |
* https://github.com/bitcoin/bitcoin/blob/ffd75adce01a78b3461b3ff05bcc2b530a9ce994/src/script/interpreter.cpp#L1129 | |
* | |
* @param {BN} nLockTime the locktime read from the script | |
* @return {boolean} true if the transaction's locktime is less than or equal to | |
* the transaction's locktime | |
*/ | |
Interpreter.prototype.checkLockTime = function (nLockTime) { | |
// We want to compare apples to apples, so fail the script | |
// unless the type of nLockTime being tested is the same as | |
// the nLockTime in the transaction. | |
if (!(this.tx.nLockTime < Interpreter.LOCKTIME_THRESHOLD && nLockTime.lt(Interpreter.LOCKTIME_THRESHOLD_BN) || this.tx.nLockTime >= Interpreter.LOCKTIME_THRESHOLD && nLockTime.gte(Interpreter.LOCKTIME_THRESHOLD_BN))) { | |
return false; | |
} | |
// Now that we know we're comparing apples-to-apples, the | |
// comparison is a simple numeric one. | |
if (nLockTime.gt(new BN(this.tx.nLockTime))) { | |
return false; | |
} | |
// Finally the nLockTime feature can be disabled and thus | |
// CHECKLOCKTIMEVERIFY bypassed if every txin has been | |
// finalized by setting nSequence to maxint. The | |
// transaction would be allowed into the blockchain, making | |
// the opcode ineffective. | |
// | |
// Testing if this vin is not final is sufficient to | |
// prevent this condition. Alternatively we could test all | |
// inputs, but testing just this input minimizes the data | |
// required to prove correct CHECKLOCKTIMEVERIFY execution. | |
if (!this.tx.inputs[this.nin].isFinal()) { | |
return false; | |
} | |
return true; | |
}; | |
/** | |
* Based on the inner loop of bitcoind's EvalScript function | |
* bitcoind commit: b5d1b1092998bc95313856d535c632ea5a8f9104 | |
*/ | |
Interpreter.prototype.step = function () { | |
var fRequireMinimal = (this.flags & Interpreter.SCRIPT_VERIFY_MINIMALDATA) !== 0; | |
//bool fExec = !count(vfExec.begin(), vfExec.end(), false); | |
var fExec = this.vfExec.indexOf(false) === -1; | |
var buf, buf1, buf2, spliced, n, x1, x2, bn, bn1, bn2, bufSig, bufPubkey, subscript; | |
var sig, pubkey; | |
var fValue, fSuccess; | |
// Read instruction | |
var chunk = this.script.chunks[this.pc]; | |
this.pc++; | |
var opcodenum = chunk.opcodenum; | |
if (_.isUndefined(opcodenum)) { | |
this.errstr = 'SCRIPT_ERR_UNDEFINED_OPCODE'; | |
return false; | |
} | |
if (chunk.buf && chunk.buf.length > Interpreter.MAX_SCRIPT_ELEMENT_SIZE) { | |
this.errstr = 'SCRIPT_ERR_PUSH_SIZE'; | |
return false; | |
} | |
// Note how Opcode.OP_RESERVED does not count towards the opcode limit. | |
if (opcodenum > Opcode.OP_16 && ++this.nOpCount > 201) { | |
this.errstr = 'SCRIPT_ERR_OP_COUNT'; | |
return false; | |
} | |
if (opcodenum === Opcode.OP_CAT || opcodenum === Opcode.OP_SUBSTR || opcodenum === Opcode.OP_LEFT || opcodenum === Opcode.OP_RIGHT || opcodenum === Opcode.OP_INVERT || opcodenum === Opcode.OP_AND || opcodenum === Opcode.OP_OR || opcodenum === Opcode.OP_XOR || opcodenum === Opcode.OP_2MUL || opcodenum === Opcode.OP_2DIV || opcodenum === Opcode.OP_MUL || opcodenum === Opcode.OP_DIV || opcodenum === Opcode.OP_MOD || opcodenum === Opcode.OP_LSHIFT || opcodenum === Opcode.OP_RSHIFT) { | |
this.errstr = 'SCRIPT_ERR_DISABLED_OPCODE'; | |
return false; | |
} | |
if (fExec && 0 <= opcodenum && opcodenum <= Opcode.OP_PUSHDATA4) { | |
if (fRequireMinimal && !this.script.checkMinimalPush(this.pc - 1)) { | |
this.errstr = 'SCRIPT_ERR_MINIMALDATA'; | |
return false; | |
} | |
if (!chunk.buf) { | |
this.stack.push(Interpreter.false); | |
} else if (chunk.len !== chunk.buf.length) { | |
throw new Error('Length of push value not equal to length of data'); | |
} else { | |
this.stack.push(chunk.buf); | |
} | |
} else if (fExec || Opcode.OP_IF <= opcodenum && opcodenum <= Opcode.OP_ENDIF) { | |
switch (opcodenum) { | |
// Push value | |
case Opcode.OP_1NEGATE: | |
case Opcode.OP_1: | |
case Opcode.OP_2: | |
case Opcode.OP_3: | |
case Opcode.OP_4: | |
case Opcode.OP_5: | |
case Opcode.OP_6: | |
case Opcode.OP_7: | |
case Opcode.OP_8: | |
case Opcode.OP_9: | |
case Opcode.OP_10: | |
case Opcode.OP_11: | |
case Opcode.OP_12: | |
case Opcode.OP_13: | |
case Opcode.OP_14: | |
case Opcode.OP_15: | |
case Opcode.OP_16: | |
{ | |
// ( -- value) | |
// ScriptNum bn((int)opcode - (int)(Opcode.OP_1 - 1)); | |
n = opcodenum - (Opcode.OP_1 - 1); | |
buf = new BN(n).toScriptNumBuffer(); | |
this.stack.push(buf); | |
// The result of these opcodes should always be the minimal way to push the data | |
// they push, so no need for a CheckMinimalPush here. | |
} | |
break; | |
// | |
// Control | |
// | |
case Opcode.OP_NOP: | |
break; | |
case Opcode.OP_NOP2: | |
case Opcode.OP_CHECKLOCKTIMEVERIFY: | |
if (!(this.flags & Interpreter.SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY)) { | |
// not enabled; treat as a NOP2 | |
if (this.flags & Interpreter.SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS) { | |
this.errstr = 'SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS'; | |
return false; | |
} | |
break; | |
} | |
if (this.stack.length < 1) { | |
this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'; | |
return false; | |
} | |
// Note that elsewhere numeric opcodes are limited to | |
// operands in the range -2**31+1 to 2**31-1, however it is | |
// legal for opcodes to produce results exceeding that | |
// range. This limitation is implemented by CScriptNum's | |
// default 4-byte limit. | |
// | |
// If we kept to that limit we'd have a year 2038 problem, | |
// even though the nLockTime field in transactions | |
// themselves is uint32 which only becomes meaningless | |
// after the year 2106. | |
// | |
// Thus as a special case we tell CScriptNum to accept up | |
// to 5-byte bignums, which are good until 2**39-1, well | |
// beyond the 2**32-1 limit of the nLockTime field itself. | |
var nLockTime = BN.fromScriptNumBuffer(this.stack[this.stack.length - 1], fRequireMinimal, 5); | |
// In the rare event that the argument may be < 0 due to | |
// some arithmetic being done first, you can always use | |
// 0 MAX CHECKLOCKTIMEVERIFY. | |
if (nLockTime.lt(new BN(0))) { | |
this.errstr = 'SCRIPT_ERR_NEGATIVE_LOCKTIME'; | |
return false; | |
} | |
// Actually compare the specified lock time with the transaction. | |
if (!this.checkLockTime(nLockTime)) { | |
this.errstr = 'SCRIPT_ERR_UNSATISFIED_LOCKTIME'; | |
return false; | |
} | |
break; | |
case Opcode.OP_NOP1: | |
case Opcode.OP_NOP3: | |
case Opcode.OP_NOP4: | |
case Opcode.OP_NOP5: | |
case Opcode.OP_NOP6: | |
case Opcode.OP_NOP7: | |
case Opcode.OP_NOP8: | |
case Opcode.OP_NOP9: | |
case Opcode.OP_NOP10: | |
{ | |
if (this.flags & Interpreter.SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS) { | |
this.errstr = 'SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS'; | |
return false; | |
} | |
} | |
break; | |
case Opcode.OP_IF: | |
case Opcode.OP_NOTIF: | |
{ | |
// <expression> if [statements] [else [statements]] endif | |
// bool fValue = false; | |
fValue = false; | |
if (fExec) { | |
if (this.stack.length < 1) { | |
this.errstr = 'SCRIPT_ERR_UNBALANCED_CONDITIONAL'; | |
return false; | |
} | |
buf = this.stack.pop(); | |
fValue = Interpreter.castToBool(buf); | |
if (opcodenum === Opcode.OP_NOTIF) { | |
fValue = !fValue; | |
} | |
} | |
this.vfExec.push(fValue); | |
} | |
break; | |
case Opcode.OP_ELSE: | |
{ | |
if (this.vfExec.length === 0) { | |
this.errstr = 'SCRIPT_ERR_UNBALANCED_CONDITIONAL'; | |
return false; | |
} | |
this.vfExec[this.vfExec.length - 1] = !this.vfExec[this.vfExec.length - 1]; | |
} | |
break; | |
case Opcode.OP_ENDIF: | |
{ | |
if (this.vfExec.length === 0) { | |
this.errstr = 'SCRIPT_ERR_UNBALANCED_CONDITIONAL'; | |
return false; | |
} | |
this.vfExec.pop(); | |
} | |
break; | |
case Opcode.OP_VERIFY: | |
{ | |
// (true -- ) or | |
// (false -- false) and return | |
if (this.stack.length < 1) { | |
this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'; | |
return false; | |
} | |
buf = this.stack[this.stack.length - 1]; | |
fValue = Interpreter.castToBool(buf); | |
if (fValue) { | |
this.stack.pop(); | |
} else { | |
this.errstr = 'SCRIPT_ERR_VERIFY'; | |
return false; | |
} | |
} | |
break; | |
case Opcode.OP_RETURN: | |
{ | |
this.errstr = 'SCRIPT_ERR_OP_RETURN'; | |
return false; | |
} | |
break; | |
// | |
// Stack ops | |
// | |
case Opcode.OP_TOALTSTACK: | |
{ | |
if (this.stack.length < 1) { | |
this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'; | |
return false; | |
} | |
this.altstack.push(this.stack.pop()); | |
} | |
break; | |
case Opcode.OP_FROMALTSTACK: | |
{ | |
if (this.altstack.length < 1) { | |
this.errstr = 'SCRIPT_ERR_INVALID_ALTSTACK_OPERATION'; | |
return false; | |
} | |
this.stack.push(this.altstack.pop()); | |
} | |
break; | |
case Opcode.OP_2DROP: | |
{ | |
// (x1 x2 -- ) | |
if (this.stack.length < 2) { | |
this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'; | |
return false; | |
} | |
this.stack.pop(); | |
this.stack.pop(); | |
} | |
break; | |
case Opcode.OP_2DUP: | |
{ | |
// (x1 x2 -- x1 x2 x1 x2) | |
if (this.stack.length < 2) { | |
this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'; | |
return false; | |
} | |
buf1 = this.stack[this.stack.length - 2]; | |
buf2 = this.stack[this.stack.length - 1]; | |
this.stack.push(buf1); | |
this.stack.push(buf2); | |
} | |
break; | |
case Opcode.OP_3DUP: | |
{ | |
// (x1 x2 x3 -- x1 x2 x3 x1 x2 x3) | |
if (this.stack.length < 3) { | |
this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'; | |
return false; | |
} | |
buf1 = this.stack[this.stack.length - 3]; | |
buf2 = this.stack[this.stack.length - 2]; | |
var buf3 = this.stack[this.stack.length - 1]; | |
this.stack.push(buf1); | |
this.stack.push(buf2); | |
this.stack.push(buf3); | |
} | |
break; | |
case Opcode.OP_2OVER: | |
{ | |
// (x1 x2 x3 x4 -- x1 x2 x3 x4 x1 x2) | |
if (this.stack.length < 4) { | |
this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'; | |
return false; | |
} | |
buf1 = this.stack[this.stack.length - 4]; | |
buf2 = this.stack[this.stack.length - 3]; | |
this.stack.push(buf1); | |
this.stack.push(buf2); | |
} | |
break; | |
case Opcode.OP_2ROT: | |
{ | |
// (x1 x2 x3 x4 x5 x6 -- x3 x4 x5 x6 x1 x2) | |
if (this.stack.length < 6) { | |
this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'; | |
return false; | |
} | |
spliced = this.stack.splice(this.stack.length - 6, 2); | |
this.stack.push(spliced[0]); | |
this.stack.push(spliced[1]); | |
} | |
break; | |
case Opcode.OP_2SWAP: | |
{ | |
// (x1 x2 x3 x4 -- x3 x4 x1 x2) | |
if (this.stack.length < 4) { | |
this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'; | |
return false; | |
} | |
spliced = this.stack.splice(this.stack.length - 4, 2); | |
this.stack.push(spliced[0]); | |
this.stack.push(spliced[1]); | |
} | |
break; | |
case Opcode.OP_IFDUP: | |
{ | |
// (x - 0 | x x) | |
if (this.stack.length < 1) { | |
this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'; | |
return false; | |
} | |
buf = this.stack[this.stack.length - 1]; | |
fValue = Interpreter.castToBool(buf); | |
if (fValue) { | |
this.stack.push(buf); | |
} | |
} | |
break; | |
case Opcode.OP_DEPTH: | |
{ | |
// -- stacksize | |
buf = new BN(this.stack.length).toScriptNumBuffer(); | |
this.stack.push(buf); | |
} | |
break; | |
case Opcode.OP_DROP: | |
{ | |
// (x -- ) | |
if (this.stack.length < 1) { | |
this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'; | |
return false; | |
} | |
this.stack.pop(); | |
} | |
break; | |
case Opcode.OP_DUP: | |
{ | |
// (x -- x x) | |
if (this.stack.length < 1) { | |
this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'; | |
return false; | |
} | |
this.stack.push(this.stack[this.stack.length - 1]); | |
} | |
break; | |
case Opcode.OP_NIP: | |
{ | |
// (x1 x2 -- x2) | |
if (this.stack.length < 2) { | |
this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'; | |
return false; | |
} | |
this.stack.splice(this.stack.length - 2, 1); | |
} | |
break; | |
case Opcode.OP_OVER: | |
{ | |
// (x1 x2 -- x1 x2 x1) | |
if (this.stack.length < 2) { | |
this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'; | |
return false; | |
} | |
this.stack.push(this.stack[this.stack.length - 2]); | |
} | |
break; | |
case Opcode.OP_PICK: | |
case Opcode.OP_ROLL: | |
{ | |
// (xn ... x2 x1 x0 n - xn ... x2 x1 x0 xn) | |
// (xn ... x2 x1 x0 n - ... x2 x1 x0 xn) | |
if (this.stack.length < 2) { | |
this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'; | |
return false; | |
} | |
buf = this.stack[this.stack.length - 1]; | |
bn = BN.fromScriptNumBuffer(buf, fRequireMinimal); | |
n = bn.toNumber(); | |
this.stack.pop(); | |
if (n < 0 || n >= this.stack.length) { | |
this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'; | |
return false; | |
} | |
buf = this.stack[this.stack.length - n - 1]; | |
if (opcodenum === Opcode.OP_ROLL) { | |
this.stack.splice(this.stack.length - n - 1, 1); | |
} | |
this.stack.push(buf); | |
} | |
break; | |
case Opcode.OP_ROT: | |
{ | |
// (x1 x2 x3 -- x2 x3 x1) | |
// x2 x1 x3 after first swap | |
// x2 x3 x1 after second swap | |
if (this.stack.length < 3) { | |
this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'; | |
return false; | |
} | |
x1 = this.stack[this.stack.length - 3]; | |
x2 = this.stack[this.stack.length - 2]; | |
var x3 = this.stack[this.stack.length - 1]; | |
this.stack[this.stack.length - 3] = x2; | |
this.stack[this.stack.length - 2] = x3; | |
this.stack[this.stack.length - 1] = x1; | |
} | |
break; | |
case Opcode.OP_SWAP: | |
{ | |
// (x1 x2 -- x2 x1) | |
if (this.stack.length < 2) { | |
this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'; | |
return false; | |
} | |
x1 = this.stack[this.stack.length - 2]; | |
x2 = this.stack[this.stack.length - 1]; | |
this.stack[this.stack.length - 2] = x2; | |
this.stack[this.stack.length - 1] = x1; | |
} | |
break; | |
case Opcode.OP_TUCK: | |
{ | |
// (x1 x2 -- x2 x1 x2) | |
if (this.stack.length < 2) { | |
this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'; | |
return false; | |
} | |
this.stack.splice(this.stack.length - 2, 0, this.stack[this.stack.length - 1]); | |
} | |
break; | |
case Opcode.OP_SIZE: | |
{ | |
// (in -- in size) | |
if (this.stack.length < 1) { | |
this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'; | |
return false; | |
} | |
bn = new BN(this.stack[this.stack.length - 1].length); | |
this.stack.push(bn.toScriptNumBuffer()); | |
} | |
break; | |
// | |
// Bitwise logic | |
// | |
case Opcode.OP_EQUAL: | |
case Opcode.OP_EQUALVERIFY: | |
//case Opcode.OP_NOTEQUAL: // use Opcode.OP_NUMNOTEQUAL | |
{ | |
// (x1 x2 - bool) | |
if (this.stack.length < 2) { | |
this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'; | |
return false; | |
} | |
buf1 = this.stack[this.stack.length - 2]; | |
buf2 = this.stack[this.stack.length - 1]; | |
var fEqual = buf1.toString('hex') === buf2.toString('hex'); | |
this.stack.pop(); | |
this.stack.pop(); | |
this.stack.push(fEqual ? Interpreter.true : Interpreter.false); | |
if (opcodenum === Opcode.OP_EQUALVERIFY) { | |
if (fEqual) { | |
this.stack.pop(); | |
} else { | |
this.errstr = 'SCRIPT_ERR_EQUALVERIFY'; | |
return false; | |
} | |
} | |
} | |
break; | |
// | |
// Numeric | |
// | |
case Opcode.OP_1ADD: | |
case Opcode.OP_1SUB: | |
case Opcode.OP_NEGATE: | |
case Opcode.OP_ABS: | |
case Opcode.OP_NOT: | |
case Opcode.OP_0NOTEQUAL: | |
{ | |
// (in -- out) | |
if (this.stack.length < 1) { | |
this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'; | |
return false; | |
} | |
buf = this.stack[this.stack.length - 1]; | |
bn = BN.fromScriptNumBuffer(buf, fRequireMinimal); | |
switch (opcodenum) { | |
case Opcode.OP_1ADD: | |
bn = bn.add(BN.One); | |
break; | |
case Opcode.OP_1SUB: | |
bn = bn.sub(BN.One); | |
break; | |
case Opcode.OP_NEGATE: | |
bn = bn.neg(); | |
break; | |
case Opcode.OP_ABS: | |
if (bn.cmp(BN.Zero) < 0) { | |
bn = bn.neg(); | |
} | |
break; | |
case Opcode.OP_NOT: | |
bn = new BN((bn.cmp(BN.Zero) === 0) + 0); | |
break; | |
case Opcode.OP_0NOTEQUAL: | |
bn = new BN((bn.cmp(BN.Zero) !== 0) + 0); | |
break; | |
//default: assert(!'invalid opcode'); break; // TODO: does this ever occur? | |
} | |
this.stack.pop(); | |
this.stack.push(bn.toScriptNumBuffer()); | |
} | |
break; | |
case Opcode.OP_ADD: | |
case Opcode.OP_SUB: | |
case Opcode.OP_BOOLAND: | |
case Opcode.OP_BOOLOR: | |
case Opcode.OP_NUMEQUAL: | |
case Opcode.OP_NUMEQUALVERIFY: | |
case Opcode.OP_NUMNOTEQUAL: | |
case Opcode.OP_LESSTHAN: | |
case Opcode.OP_GREATERTHAN: | |
case Opcode.OP_LESSTHANOREQUAL: | |
case Opcode.OP_GREATERTHANOREQUAL: | |
case Opcode.OP_MIN: | |
case Opcode.OP_MAX: | |
{ | |
// (x1 x2 -- out) | |
if (this.stack.length < 2) { | |
this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'; | |
return false; | |
} | |
bn1 = BN.fromScriptNumBuffer(this.stack[this.stack.length - 2], fRequireMinimal); | |
bn2 = BN.fromScriptNumBuffer(this.stack[this.stack.length - 1], fRequireMinimal); | |
bn = new BN(0); | |
switch (opcodenum) { | |
case Opcode.OP_ADD: | |
bn = bn1.add(bn2); | |
break; | |
case Opcode.OP_SUB: | |
bn = bn1.sub(bn2); | |
break; | |
// case Opcode.OP_BOOLAND: bn = (bn1 != bnZero && bn2 != bnZero); break; | |
case Opcode.OP_BOOLAND: | |
bn = new BN((bn1.cmp(BN.Zero) !== 0 && bn2.cmp(BN.Zero) !== 0) + 0); | |
break; | |
// case Opcode.OP_BOOLOR: bn = (bn1 != bnZero || bn2 != bnZero); break; | |
case Opcode.OP_BOOLOR: | |
bn = new BN((bn1.cmp(BN.Zero) !== 0 || bn2.cmp(BN.Zero) !== 0) + 0); | |
break; | |
// case Opcode.OP_NUMEQUAL: bn = (bn1 == bn2); break; | |
case Opcode.OP_NUMEQUAL: | |
bn = new BN((bn1.cmp(bn2) === 0) + 0); | |
break; | |
// case Opcode.OP_NUMEQUALVERIFY: bn = (bn1 == bn2); break; | |
case Opcode.OP_NUMEQUALVERIFY: | |
bn = new BN((bn1.cmp(bn2) === 0) + 0); | |
break; | |
// case Opcode.OP_NUMNOTEQUAL: bn = (bn1 != bn2); break; | |
case Opcode.OP_NUMNOTEQUAL: | |
bn = new BN((bn1.cmp(bn2) !== 0) + 0); | |
break; | |
// case Opcode.OP_LESSTHAN: bn = (bn1 < bn2); break; | |
case Opcode.OP_LESSTHAN: | |
bn = new BN((bn1.cmp(bn2) < 0) + 0); | |
break; | |
// case Opcode.OP_GREATERTHAN: bn = (bn1 > bn2); break; | |
case Opcode.OP_GREATERTHAN: | |
bn = new BN((bn1.cmp(bn2) > 0) + 0); | |
break; | |
// case Opcode.OP_LESSTHANOREQUAL: bn = (bn1 <= bn2); break; | |
case Opcode.OP_LESSTHANOREQUAL: | |
bn = new BN((bn1.cmp(bn2) <= 0) + 0); | |
break; | |
// case Opcode.OP_GREATERTHANOREQUAL: bn = (bn1 >= bn2); break; | |
case Opcode.OP_GREATERTHANOREQUAL: | |
bn = new BN((bn1.cmp(bn2) >= 0) + 0); | |
break; | |
case Opcode.OP_MIN: | |
bn = bn1.cmp(bn2) < 0 ? bn1 : bn2; | |
break; | |
case Opcode.OP_MAX: | |
bn = bn1.cmp(bn2) > 0 ? bn1 : bn2; | |
break; | |
// default: assert(!'invalid opcode'); break; //TODO: does this ever occur? | |
} | |
this.stack.pop(); | |
this.stack.pop(); | |
this.stack.push(bn.toScriptNumBuffer()); | |
if (opcodenum === Opcode.OP_NUMEQUALVERIFY) { | |
// if (CastToBool(stacktop(-1))) | |
if (Interpreter.castToBool(this.stack[this.stack.length - 1])) { | |
this.stack.pop(); | |
} else { | |
this.errstr = 'SCRIPT_ERR_NUMEQUALVERIFY'; | |
return false; | |
} | |
} | |
} | |
break; | |
case Opcode.OP_WITHIN: | |
{ | |
// (x min max -- out) | |
if (this.stack.length < 3) { | |
this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'; | |
return false; | |
} | |
bn1 = BN.fromScriptNumBuffer(this.stack[this.stack.length - 3], fRequireMinimal); | |
bn2 = BN.fromScriptNumBuffer(this.stack[this.stack.length - 2], fRequireMinimal); | |
var bn3 = BN.fromScriptNumBuffer(this.stack[this.stack.length - 1], fRequireMinimal); | |
//bool fValue = (bn2 <= bn1 && bn1 < bn3); | |
fValue = bn2.cmp(bn1) <= 0 && bn1.cmp(bn3) < 0; | |
this.stack.pop(); | |
this.stack.pop(); | |
this.stack.pop(); | |
this.stack.push(fValue ? Interpreter.true : Interpreter.false); | |
} | |
break; | |
// | |
// Crypto | |
// | |
case Opcode.OP_RIPEMD160: | |
case Opcode.OP_SHA1: | |
case Opcode.OP_SHA256: | |
case Opcode.OP_HASH160: | |
case Opcode.OP_HASH256: | |
{ | |
// (in -- hash) | |
if (this.stack.length < 1) { | |
this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'; | |
return false; | |
} | |
buf = this.stack[this.stack.length - 1]; | |
//valtype vchHash((opcode == Opcode.OP_RIPEMD160 || | |
// opcode == Opcode.OP_SHA1 || opcode == Opcode.OP_HASH160) ? 20 : 32); | |
var bufHash; | |
if (opcodenum === Opcode.OP_RIPEMD160) { | |
bufHash = Hash.ripemd160(buf); | |
} else if (opcodenum === Opcode.OP_SHA1) { | |
bufHash = Hash.sha1(buf); | |
} else if (opcodenum === Opcode.OP_SHA256) { | |
bufHash = Hash.sha256(buf); | |
} else if (opcodenum === Opcode.OP_HASH160) { | |
bufHash = Hash.sha256ripemd160(buf); | |
} else if (opcodenum === Opcode.OP_HASH256) { | |
bufHash = Hash.sha256sha256(buf); | |
} | |
this.stack.pop(); | |
this.stack.push(bufHash); | |
} | |
break; | |
case Opcode.OP_CODESEPARATOR: | |
{ | |
// Hash starts after the code separator | |
this.pbegincodehash = this.pc; | |
} | |
break; | |
case Opcode.OP_CHECKSIG: | |
case Opcode.OP_CHECKSIGVERIFY: | |
{ | |
// (sig pubkey -- bool) | |
if (this.stack.length < 2) { | |
this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'; | |
return false; | |
} | |
bufSig = this.stack[this.stack.length - 2]; | |
bufPubkey = this.stack[this.stack.length - 1]; | |
// Subset of script starting at the most recent codeseparator | |
// CScript scriptCode(pbegincodehash, pend); | |
subscript = new Script().set({ | |
chunks: this.script.chunks.slice(this.pbegincodehash) | |
}); | |
// Drop the signature, since there's no way for a signature to sign itself | |
var tmpScript = new Script().add(bufSig); | |
subscript.findAndDelete(tmpScript); | |
if (!this.checkSignatureEncoding(bufSig) || !this.checkPubkeyEncoding(bufPubkey)) { | |
return false; | |
} | |
try { | |
sig = Signature.fromTxFormat(bufSig); | |
pubkey = PublicKey.fromBuffer(bufPubkey, false); | |
fSuccess = this.tx.verifySignature(sig, pubkey, this.nin, subscript); | |
} catch (e) { | |
//invalid sig or pubkey | |
fSuccess = false; | |
} | |
this.stack.pop(); | |
this.stack.pop(); | |
// stack.push_back(fSuccess ? vchTrue : vchFalse); | |
this.stack.push(fSuccess ? Interpreter.true : Interpreter.false); | |
if (opcodenum === Opcode.OP_CHECKSIGVERIFY) { | |
if (fSuccess) { | |
this.stack.pop(); | |
} else { | |
this.errstr = 'SCRIPT_ERR_CHECKSIGVERIFY'; | |
return false; | |
} | |
} | |
} | |
break; | |
case Opcode.OP_CHECKMULTISIG: | |
case Opcode.OP_CHECKMULTISIGVERIFY: | |
{ | |
// ([sig ...] num_of_signatures [pubkey ...] num_of_pubkeys -- bool) | |
var i = 1; | |
if (this.stack.length < i) { | |
this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'; | |
return false; | |
} | |
var nKeysCount = BN.fromScriptNumBuffer(this.stack[this.stack.length - i], fRequireMinimal).toNumber(); | |
if (nKeysCount < 0 || nKeysCount > 20) { | |
this.errstr = 'SCRIPT_ERR_PUBKEY_COUNT'; | |
return false; | |
} | |
this.nOpCount += nKeysCount; | |
if (this.nOpCount > 201) { | |
this.errstr = 'SCRIPT_ERR_OP_COUNT'; | |
return false; | |
} | |
// int ikey = ++i; | |
var ikey = ++i; | |
i += nKeysCount; | |
if (this.stack.length < i) { | |
this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'; | |
return false; | |
} | |
var nSigsCount = BN.fromScriptNumBuffer(this.stack[this.stack.length - i], fRequireMinimal).toNumber(); | |
if (nSigsCount < 0 || nSigsCount > nKeysCount) { | |
this.errstr = 'SCRIPT_ERR_SIG_COUNT'; | |
return false; | |
} | |
// int isig = ++i; | |
var isig = ++i; | |
i += nSigsCount; | |
if (this.stack.length < i) { | |
this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'; | |
return false; | |
} | |
// Subset of script starting at the most recent codeseparator | |
subscript = new Script().set({ | |
chunks: this.script.chunks.slice(this.pbegincodehash) | |
}); | |
// Drop the signatures, since there's no way for a signature to sign itself | |
for (var k = 0; k < nSigsCount; k++) { | |
bufSig = this.stack[this.stack.length - isig - k]; | |
subscript.findAndDelete(new Script().add(bufSig)); | |
} | |
fSuccess = true; | |
while (fSuccess && nSigsCount > 0) { | |
// valtype& vchSig = stacktop(-isig); | |
bufSig = this.stack[this.stack.length - isig]; | |
// valtype& vchPubKey = stacktop(-ikey); | |
bufPubkey = this.stack[this.stack.length - ikey]; | |
if (!this.checkSignatureEncoding(bufSig) || !this.checkPubkeyEncoding(bufPubkey)) { | |
return false; | |
} | |
var fOk; | |
try { | |
sig = Signature.fromTxFormat(bufSig); | |
pubkey = PublicKey.fromBuffer(bufPubkey, false); | |
fOk = this.tx.verifySignature(sig, pubkey, this.nin, subscript); | |
} catch (e) { | |
//invalid sig or pubkey | |
fOk = false; | |
} | |
if (fOk) { | |
isig++; | |
nSigsCount--; | |
} | |
ikey++; | |
nKeysCount--; | |
// If there are more signatures left than keys left, | |
// then too many signatures have failed | |
if (nSigsCount > nKeysCount) { | |
fSuccess = false; | |
} | |
} | |
// Clean up stack of actual arguments | |
while (i-- > 1) { | |
this.stack.pop(); | |
} | |
// A bug causes CHECKMULTISIG to consume one extra argument | |
// whose contents were not checked in any way. | |
// | |
// Unfortunately this is a potential source of mutability, | |
// so optionally verify it is exactly equal to zero prior | |
// to removing it from the stack. | |
if (this.stack.length < 1) { | |
this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION'; | |
return false; | |
} | |
if (this.flags & Interpreter.SCRIPT_VERIFY_NULLDUMMY && this.stack[this.stack.length - 1].length) { | |
this.errstr = 'SCRIPT_ERR_SIG_NULLDUMMY'; | |
return false; | |
} | |
this.stack.pop(); | |
this.stack.push(fSuccess ? Interpreter.true : Interpreter.false); | |
if (opcodenum === Opcode.OP_CHECKMULTISIGVERIFY) { | |
if (fSuccess) { | |
this.stack.pop(); | |
} else { | |
this.errstr = 'SCRIPT_ERR_CHECKMULTISIGVERIFY'; | |
return false; | |
} | |
} | |
} | |
break; | |
default: | |
this.errstr = 'SCRIPT_ERR_BAD_OPCODE'; | |
return false; | |
} | |
} | |
return true; | |
}; | |
}).call(this,require("buffer").Buffer) | |
},{"../crypto/bn":32,"../crypto/hash":34,"../crypto/signature":37,"../opcode":48,"../publickey":50,"../transaction":54,"./script":53,"buffer":148,"lodash":267}],53:[function(require,module,exports){ | |
(function (Buffer){ | |
'use strict'; | |
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; | |
var Address = require('../address'); | |
var BufferReader = require('../encoding/bufferreader'); | |
var BufferWriter = require('../encoding/bufferwriter'); | |
var Hash = require('../crypto/hash'); | |
var Opcode = require('../opcode'); | |
var PublicKey = require('../publickey'); | |
var Signature = require('../crypto/signature'); | |
var Networks = require('../networks'); | |
var $ = require('../util/preconditions'); | |
var _ = require('lodash'); | |
var errors = require('../errors'); | |
var buffer = require('buffer'); | |
var BufferUtil = require('../util/buffer'); | |
var JSUtil = require('../util/js'); | |
/** | |
* A bitcoin transaction script. Each transaction's inputs and outputs | |
* has a script that is evaluated to validate it's spending. | |
* | |
* See https://en.bitcoin.it/wiki/Script | |
* | |
* @constructor | |
* @param {Object|string|Buffer=} from optional data to populate script | |
*/ | |
var Script = function Script(from) { | |
if (!(this instanceof Script)) { | |
return new Script(from); | |
} | |
this.chunks = []; | |
if (BufferUtil.isBuffer(from)) { | |
return Script.fromBuffer(from); | |
} else if (from instanceof Address) { | |
return Script.fromAddress(from); | |
} else if (from instanceof Script) { | |
return Script.fromBuffer(from.toBuffer()); | |
} else if (_.isString(from)) { | |
return Script.fromString(from); | |
} else if (_.isObject(from) && _.isArray(from.chunks)) { | |
this.set(from); | |
} | |
}; | |
Script.prototype.set = function (obj) { | |
$.checkArgument(_.isObject(obj)); | |
$.checkArgument(_.isArray(obj.chunks)); | |
this.chunks = obj.chunks; | |
return this; | |
}; | |
Script.fromBuffer = function (buffer) { | |
var script = new Script(); | |
script.chunks = []; | |
var br = new BufferReader(buffer); | |
while (!br.finished()) { | |
try { | |
var opcodenum = br.readUInt8(); | |
var len, buf; | |
if (opcodenum > 0 && opcodenum < Opcode.OP_PUSHDATA1) { | |
len = opcodenum; | |
script.chunks.push({ | |
buf: br.read(len), | |
len: len, | |
opcodenum: opcodenum | |
}); | |
} else if (opcodenum === Opcode.OP_PUSHDATA1) { | |
len = br.readUInt8(); | |
buf = br.read(len); | |
script.chunks.push({ | |
buf: buf, | |
len: len, | |
opcodenum: opcodenum | |
}); | |
} else if (opcodenum === Opcode.OP_PUSHDATA2) { | |
len = br.readUInt16LE(); | |
buf = br.read(len); | |
script.chunks.push({ | |
buf: buf, | |
len: len, | |
opcodenum: opcodenum | |
}); | |
} else if (opcodenum === Opcode.OP_PUSHDATA4) { | |
len = br.readUInt32LE(); | |
buf = br.read(len); | |
script.chunks.push({ | |
buf: buf, | |
len: len, | |
opcodenum: opcodenum | |
}); | |
} else { | |
script.chunks.push({ | |
opcodenum: opcodenum | |
}); | |
} | |
} catch (e) { | |
if (e instanceof RangeError) { | |
throw new errors.Script.InvalidBuffer(buffer.toString('hex')); | |
} | |
throw e; | |
} | |
} | |
return script; | |
}; | |
Script.prototype.toBuffer = function () { | |
var bw = new BufferWriter(); | |
for (var i = 0; i < this.chunks.length; i++) { | |
var chunk = this.chunks[i]; | |
var opcodenum = chunk.opcodenum; | |
bw.writeUInt8(chunk.opcodenum); | |
if (chunk.buf) { | |
if (opcodenum < Opcode.OP_PUSHDATA1) { | |
bw.write(chunk.buf); | |
} else if (opcodenum === Opcode.OP_PUSHDATA1) { | |
bw.writeUInt8(chunk.len); | |
bw.write(chunk.buf); | |
} else if (opcodenum === Opcode.OP_PUSHDATA2) { | |
bw.writeUInt16LE(chunk.len); | |
bw.write(chunk.buf); | |
} else if (opcodenum === Opcode.OP_PUSHDATA4) { | |
bw.writeUInt32LE(chunk.len); | |
bw.write(chunk.buf); | |
} | |
} | |
} | |
return bw.concat(); | |
}; | |
Script.fromASM = function (str) { | |
var script = new Script(); | |
script.chunks = []; | |
var tokens = str.split(' '); | |
var i = 0; | |
while (i < tokens.length) { | |
var token = tokens[i]; | |
var opcode = Opcode(token); | |
var opcodenum = opcode.toNumber(); | |
if (_.isUndefined(opcodenum)) { | |
var buf = new Buffer(tokens[i], 'hex'); | |
script.chunks.push({ | |
buf: buf, | |
len: buf.length, | |
opcodenum: buf.length | |
}); | |
i = i + 1; | |
} else if (opcodenum === Opcode.OP_PUSHDATA1 || opcodenum === Opcode.OP_PUSHDATA2 || opcodenum === Opcode.OP_PUSHDATA4) { | |
script.chunks.push({ | |
buf: new Buffer(tokens[i + 2], 'hex'), | |
len: parseInt(tokens[i + 1]), | |
opcodenum: opcodenum | |
}); | |
i = i + 3; | |
} else { | |
script.chunks.push({ | |
opcodenum: opcodenum | |
}); | |
i = i + 1; | |
} | |
} | |
return script; | |
}; | |
Script.fromHex = function (str) { | |
return new Script(new buffer.Buffer(str, 'hex')); | |
}; | |
Script.fromString = function (str) { | |
if (JSUtil.isHexa(str) || str.length === 0) { | |
return new Script(new buffer.Buffer(str, 'hex')); | |
} | |
var script = new Script(); | |
script.chunks = []; | |
var tokens = str.split(' '); | |
var i = 0; | |
while (i < tokens.length) { | |
var token = tokens[i]; | |
var opcode = Opcode(token); | |
var opcodenum = opcode.toNumber(); | |
if (_.isUndefined(opcodenum)) { | |
opcodenum = parseInt(token); | |
if (opcodenum > 0 && opcodenum < Opcode.OP_PUSHDATA1) { | |
script.chunks.push({ | |
buf: new Buffer(tokens[i + 1].slice(2), 'hex'), | |
len: opcodenum, | |
opcodenum: opcodenum | |
}); | |
i = i + 2; | |
} else { | |
throw new Error('Invalid script: ' + JSON.stringify(str)); | |
} | |
} else if (opcodenum === Opcode.OP_PUSHDATA1 || opcodenum === Opcode.OP_PUSHDATA2 || opcodenum === Opcode.OP_PUSHDATA4) { | |
if (tokens[i + 2].slice(0, 2) !== '0x') { | |
throw new Error('Pushdata data must start with 0x'); | |
} | |
script.chunks.push({ | |
buf: new Buffer(tokens[i + 2].slice(2), 'hex'), | |
len: parseInt(tokens[i + 1]), | |
opcodenum: opcodenum | |
}); | |
i = i + 3; | |
} else { | |
script.chunks.push({ | |
opcodenum: opcodenum | |
}); | |
i = i + 1; | |
} | |
} | |
return script; | |
}; | |
Script.prototype._chunkToString = function (chunk, type) { | |
var opcodenum = chunk.opcodenum; | |
var asm = type === 'asm'; | |
var str = ''; | |
if (!chunk.buf) { | |
// no data chunk | |
if (typeof Opcode.reverseMap[opcodenum] !== 'undefined') { | |
if (asm) { | |
// A few cases where the opcode name differs from reverseMap | |
// aside from 1 to 16 data pushes. | |
if (opcodenum === 0) { | |
// OP_0 -> 0 | |
str = str + ' 0'; | |
} else if (opcodenum === 79) { | |
// OP_1NEGATE -> 1 | |
str = str + ' -1'; | |
} else { | |
str = str + ' ' + Opcode(opcodenum).toString(); | |
} | |
} else { | |
str = str + ' ' + Opcode(opcodenum).toString(); | |
} | |
} else { | |
var numstr = opcodenum.toString(16); | |
if (numstr.length % 2 !== 0) { | |
numstr = '0' + numstr; | |
} | |
if (asm) { | |
str = str + ' ' + numstr; | |
} else { | |
str = str + ' ' + '0x' + numstr; | |
} | |
} | |
} else { | |
// data chunk | |
if (!asm && opcodenum === Opcode.OP_PUSHDATA1 || opcodenum === Opcode.OP_PUSHDATA2 || opcodenum === Opcode.OP_PUSHDATA4) { | |
str = str + ' ' + Opcode(opcodenum).toString(); | |
} | |
if (chunk.len > 0) { | |
if (asm) { | |
str = str + ' ' + chunk.buf.toString('hex'); | |
} else { | |
str = str + ' ' + chunk.len + ' ' + '0x' + chunk.buf.toString('hex'); | |
} | |
} | |
} | |
return str; | |
}; | |
Script.prototype.toASM = function () { | |
var str = ''; | |
for (var i = 0; i < this.chunks.length; i++) { | |
var chunk = this.chunks[i]; | |
str += this._chunkToString(chunk, 'asm'); | |
} | |
return str.substr(1); | |
}; | |
Script.prototype.toString = function () { | |
var str = ''; | |
for (var i = 0; i < this.chunks.length; i++) { | |
var chunk = this.chunks[i]; | |
str += this._chunkToString(chunk); | |
} | |
return str.substr(1); | |
}; | |
Script.prototype.toHex = function () { | |
return this.toBuffer().toString('hex'); | |
}; | |
Script.prototype.inspect = function () { | |
return '<Script: ' + this.toString() + '>'; | |
}; | |
// script classification methods | |
/** | |
* @returns {boolean} if this is a pay to pubkey hash output script | |
*/ | |
Script.prototype.isPublicKeyHashOut = function () { | |
return !!(this.chunks.length === 5 && this.chunks[0].opcodenum === Opcode.OP_DUP && this.chunks[1].opcodenum === Opcode.OP_HASH160 && this.chunks[2].buf && this.chunks[2].buf.length === 20 && this.chunks[3].opcodenum === Opcode.OP_EQUALVERIFY && this.chunks[4].opcodenum === Opcode.OP_CHECKSIG); | |
}; | |
/** | |
* @returns {boolean} if this is a pay to public key hash input script | |
*/ | |
Script.prototype.isPublicKeyHashIn = function () { | |
if (this.chunks.length === 2) { | |
var signatureBuf = this.chunks[0].buf; | |
var pubkeyBuf = this.chunks[1].buf; | |
if (signatureBuf && signatureBuf.length && signatureBuf[0] === 0x30 && pubkeyBuf && pubkeyBuf.length) { | |
var version = pubkeyBuf[0]; | |
if ((version === 0x04 || version === 0x06 || version === 0x07) && pubkeyBuf.length === 65) { | |
return true; | |
} else if ((version === 0x03 || version === 0x02) && pubkeyBuf.length === 33) { | |
return true; | |
} | |
} | |
} | |
return false; | |
}; | |
Script.prototype.getPublicKey = function () { | |
$.checkState(this.isPublicKeyOut(), 'Can\'t retrieve PublicKey from a non-PK output'); | |
return this.chunks[0].buf; | |
}; | |
Script.prototype.getPublicKeyHash = function () { | |
$.checkState(this.isPublicKeyHashOut(), 'Can\'t retrieve PublicKeyHash from a non-PKH output'); | |
return this.chunks[2].buf; | |
}; | |
/** | |
* @returns {boolean} if this is a public key output script | |
*/ | |
Script.prototype.isPublicKeyOut = function () { | |
if (this.chunks.length === 2 && this.chunks[0].buf && this.chunks[0].buf.length && this.chunks[1].opcodenum === Opcode.OP_CHECKSIG) { | |
var pubkeyBuf = this.chunks[0].buf; | |
var version = pubkeyBuf[0]; | |
var isVersion = false; | |
if ((version === 0x04 || version === 0x06 || version === 0x07) && pubkeyBuf.length === 65) { | |
isVersion = true; | |
} else if ((version === 0x03 || version === 0x02) && pubkeyBuf.length === 33) { | |
isVersion = true; | |
} | |
if (isVersion) { | |
return PublicKey.isValid(pubkeyBuf); | |
} | |
} | |
return false; | |
}; | |
/** | |
* @returns {boolean} if this is a pay to public key input script | |
*/ | |
Script.prototype.isPublicKeyIn = function () { | |
if (this.chunks.length === 1) { | |
var signatureBuf = this.chunks[0].buf; | |
if (signatureBuf && signatureBuf.length && signatureBuf[0] === 0x30) { | |
return true; | |
} | |
} | |
return false; | |
}; | |
/** | |
* @returns {boolean} if this is a p2sh output script | |
*/ | |
Script.prototype.isScriptHashOut = function () { | |
var buf = this.toBuffer(); | |
return buf.length === 23 && buf[0] === Opcode.OP_HASH160 && buf[1] === 0x14 && buf[buf.length - 1] === Opcode.OP_EQUAL; | |
}; | |
/** | |
* @returns {boolean} if this is a p2sh input script | |
* Note that these are frequently indistinguishable from pubkeyhashin | |
*/ | |
Script.prototype.isScriptHashIn = function () { | |
if (this.chunks.length <= 1) { | |
return false; | |
} | |
var redeemChunk = this.chunks[this.chunks.length - 1]; | |
var redeemBuf = redeemChunk.buf; | |
if (!redeemBuf) { | |
return false; | |
} | |
var redeemScript; | |
try { | |
redeemScript = Script.fromBuffer(redeemBuf); | |
} catch (e) { | |
if (e instanceof errors.Script.InvalidBuffer) { | |
return false; | |
} | |
throw e; | |
} | |
var type = redeemScript.classify(); | |
return type !== Script.types.UNKNOWN; | |
}; | |
/** | |
* @returns {boolean} if this is a mutlsig output script | |
*/ | |
Script.prototype.isMultisigOut = function () { | |
return this.chunks.length > 3 && Opcode.isSmallIntOp(this.chunks[0].opcodenum) && this.chunks.slice(1, this.chunks.length - 2).every(function (obj) { | |
return obj.buf && BufferUtil.isBuffer(obj.buf); | |
}) && Opcode.isSmallIntOp(this.chunks[this.chunks.length - 2].opcodenum) && this.chunks[this.chunks.length - 1].opcodenum === Opcode.OP_CHECKMULTISIG; | |
}; | |
/** | |
* @returns {boolean} if this is a multisig input script | |
*/ | |
Script.prototype.isMultisigIn = function () { | |
return this.chunks.length >= 2 && this.chunks[0].opcodenum === 0 && this.chunks.slice(1, this.chunks.length).every(function (obj) { | |
return obj.buf && BufferUtil.isBuffer(obj.buf) && Signature.isTxDER(obj.buf); | |
}); | |
}; | |
/** | |
* @returns {boolean} true if this is a valid standard OP_RETURN output | |
*/ | |
Script.prototype.isDataOut = function () { | |
return this.chunks.length >= 1 && this.chunks[0].opcodenum === Opcode.OP_RETURN && (this.chunks.length === 1 || this.chunks.length === 2 && this.chunks[1].buf && this.chunks[1].buf.length <= Script.OP_RETURN_STANDARD_SIZE && this.chunks[1].length === this.chunks.len); | |
}; | |
/** | |
* Retrieve the associated data for this script. | |
* In the case of a pay to public key hash or P2SH, return the hash. | |
* In the case of a standard OP_RETURN, return the data | |
* @returns {Buffer} | |
*/ | |
Script.prototype.getData = function () { | |
if (this.isDataOut() || this.isScriptHashOut()) { | |
if (_.isUndefined(this.chunks[1])) { | |
return new Buffer(0); | |
} else { | |
return new Buffer(this.chunks[1].buf); | |
} | |
} | |
if (this.isPublicKeyHashOut()) { | |
return new Buffer(this.chunks[2].buf); | |
} | |
throw new Error('Unrecognized script type to get data from'); | |
}; | |
/** | |
* @returns {boolean} if the script is only composed of data pushing | |
* opcodes or small int opcodes (OP_0, OP_1, ..., OP_16) | |
*/ | |
Script.prototype.isPushOnly = function () { | |
return _.every(this.chunks, function (chunk) { | |
return chunk.opcodenum <= Opcode.OP_16; | |
}); | |
}; | |
Script.types = {}; | |
Script.types.UNKNOWN = 'Unknown'; | |
Script.types.PUBKEY_OUT = 'Pay to public key'; | |
Script.types.PUBKEY_IN = 'Spend from public key'; | |
Script.types.PUBKEYHASH_OUT = 'Pay to public key hash'; | |
Script.types.PUBKEYHASH_IN = 'Spend from public key hash'; | |
Script.types.SCRIPTHASH_OUT = 'Pay to script hash'; | |
Script.types.SCRIPTHASH_IN = 'Spend from script hash'; | |
Script.types.MULTISIG_OUT = 'Pay to multisig'; | |
Script.types.MULTISIG_IN = 'Spend from multisig'; | |
Script.types.DATA_OUT = 'Data push'; | |
Script.OP_RETURN_STANDARD_SIZE = 80; | |
/** | |
* @returns {object} The Script type if it is a known form, | |
* or Script.UNKNOWN if it isn't | |
*/ | |
Script.prototype.classify = function () { | |
if (this._isInput) { | |
return this.classifyInput(); | |
} else if (this._isOutput) { | |
return this.classifyOutput(); | |
} else { | |
var outputType = this.classifyOutput(); | |
return outputType != Script.types.UNKNOWN ? outputType : this.classifyInput(); | |
} | |
}; | |
Script.outputIdentifiers = {}; | |
Script.outputIdentifiers.PUBKEY_OUT = Script.prototype.isPublicKeyOut; | |
Script.outputIdentifiers.PUBKEYHASH_OUT = Script.prototype.isPublicKeyHashOut; | |
Script.outputIdentifiers.MULTISIG_OUT = Script.prototype.isMultisigOut; | |
Script.outputIdentifiers.SCRIPTHASH_OUT = Script.prototype.isScriptHashOut; | |
Script.outputIdentifiers.DATA_OUT = Script.prototype.isDataOut; | |
/** | |
* @returns {object} The Script type if it is a known form, | |
* or Script.UNKNOWN if it isn't | |
*/ | |
Script.prototype.classifyOutput = function () { | |
for (var type in Script.outputIdentifiers) { | |
if (Script.outputIdentifiers[type].bind(this)()) { | |
return Script.types[type]; | |
} | |
} | |
return Script.types.UNKNOWN; | |
}; | |
Script.inputIdentifiers = {}; | |
Script.inputIdentifiers.PUBKEY_IN = Script.prototype.isPublicKeyIn; | |
Script.inputIdentifiers.PUBKEYHASH_IN = Script.prototype.isPublicKeyHashIn; | |
Script.inputIdentifiers.MULTISIG_IN = Script.prototype.isMultisigIn; | |
Script.inputIdentifiers.SCRIPTHASH_IN = Script.prototype.isScriptHashIn; | |
/** | |
* @returns {object} The Script type if it is a known form, | |
* or Script.UNKNOWN if it isn't | |
*/ | |
Script.prototype.classifyInput = function () { | |
for (var type in Script.inputIdentifiers) { | |
if (Script.inputIdentifiers[type].bind(this)()) { | |
return Script.types[type]; | |
} | |
} | |
return Script.types.UNKNOWN; | |
}; | |
/** | |
* @returns {boolean} if script is one of the known types | |
*/ | |
Script.prototype.isStandard = function () { | |
// TODO: Add BIP62 compliance | |
return this.classify() !== Script.types.UNKNOWN; | |
}; | |
// Script construction methods | |
/** | |
* Adds a script element at the start of the script. | |
* @param {*} obj a string, number, Opcode, Buffer, or object to add | |
* @returns {Script} this script instance | |
*/ | |
Script.prototype.prepend = function (obj) { | |
this._addByType(obj, true); | |
return this; | |
}; | |
/** | |
* Compares a script with another script | |
*/ | |
Script.prototype.equals = function (script) { | |
$.checkState(script instanceof Script, 'Must provide another script'); | |
if (this.chunks.length !== script.chunks.length) { | |
return false; | |
} | |
var i; | |
for (i = 0; i < this.chunks.length; i++) { | |
if (BufferUtil.isBuffer(this.chunks[i].buf) && !BufferUtil.isBuffer(script.chunks[i].buf)) { | |
return false; | |
} | |
if (BufferUtil.isBuffer(this.chunks[i].buf) && !BufferUtil.equals(this.chunks[i].buf, script.chunks[i].buf)) { | |
return false; | |
} else if (this.chunks[i].opcodenum !== script.chunks[i].opcodenum) { | |
return false; | |
} | |
} | |
return true; | |
}; | |
/** | |
* Adds a script element to the end of the script. | |
* | |
* @param {*} obj a string, number, Opcode, Buffer, or object to add | |
* @returns {Script} this script instance | |
* | |
*/ | |
Script.prototype.add = function (obj) { | |
this._addByType(obj, false); | |
return this; | |
}; | |
Script.prototype._addByType = function (obj, prepend) { | |
if (typeof obj === 'string') { | |
this._addOpcode(obj, prepend); | |
} else if (typeof obj === 'number') { | |
this._addOpcode(obj, prepend); | |
} else if (obj instanceof Opcode) { | |
this._addOpcode(obj, prepend); | |
} else if (BufferUtil.isBuffer(obj)) { | |
this._addBuffer(obj, prepend); | |
} else if (obj instanceof Script) { | |
this.chunks = this.chunks.concat(obj.chunks); | |
} else if ((typeof obj === 'undefined' ? 'undefined' : _typeof(obj)) === 'object') { | |
this._insertAtPosition(obj, prepend); | |
} else { | |
throw new Error('Invalid script chunk'); | |
} | |
}; | |
Script.prototype._insertAtPosition = function (op, prepend) { | |
if (prepend) { | |
this.chunks.unshift(op); | |
} else { | |
this.chunks.push(op); | |
} | |
}; | |
Script.prototype._addOpcode = function (opcode, prepend) { | |
var op; | |
if (typeof opcode === 'number') { | |
op = opcode; | |
} else if (opcode instanceof Opcode) { | |
op = opcode.toNumber(); | |
} else { | |
op = Opcode(opcode).toNumber(); | |
} | |
this._insertAtPosition({ | |
opcodenum: op | |
}, prepend); | |
return this; | |
}; | |
Script.prototype._addBuffer = function (buf, prepend) { | |
var opcodenum; | |
var len = buf.length; | |
if (len >= 0 && len < Opcode.OP_PUSHDATA1) { | |
opcodenum = len; | |
} else if (len < Math.pow(2, 8)) { | |
opcodenum = Opcode.OP_PUSHDATA1; | |
} else if (len < Math.pow(2, 16)) { | |
opcodenum = Opcode.OP_PUSHDATA2; | |
} else if (len < Math.pow(2, 32)) { | |
opcodenum = Opcode.OP_PUSHDATA4; | |
} else { | |
throw new Error('You can\'t push that much data'); | |
} | |
this._insertAtPosition({ | |
buf: buf, | |
len: len, | |
opcodenum: opcodenum | |
}, prepend); | |
return this; | |
}; | |
Script.prototype.removeCodeseparators = function () { | |
var chunks = []; | |
for (var i = 0; i < this.chunks.length; i++) { | |
if (this.chunks[i].opcodenum !== Opcode.OP_CODESEPARATOR) { | |
chunks.push(this.chunks[i]); | |
} | |
} | |
this.chunks = chunks; | |
return this; | |
}; | |
// high level script builder methods | |
/** | |
* @returns {Script} a new Multisig output script for given public keys, | |
* requiring m of those public keys to spend | |
* @param {PublicKey[]} publicKeys - list of all public keys controlling the output | |
* @param {number} threshold - amount of required signatures to spend the output | |
* @param {Object=} opts - Several options: | |
* - noSorting: defaults to false, if true, don't sort the given | |
* public keys before creating the script | |
*/ | |
Script.buildMultisigOut = function (publicKeys, threshold, opts) { | |
$.checkArgument(threshold <= publicKeys.length, 'Number of required signatures must be less than or equal to the number of public keys'); | |
opts = opts || {}; | |
var script = new Script(); | |
script.add(Opcode.smallInt(threshold)); | |
publicKeys = _.map(publicKeys, PublicKey); | |
var sorted = publicKeys; | |
if (!opts.noSorting) { | |
sorted = _.sortBy(publicKeys, function (publicKey) { | |
return publicKey.toString('hex'); | |
}); | |
} | |
for (var i = 0; i < sorted.length; i++) { | |
var publicKey = sorted[i]; | |
script.add(publicKey.toBuffer()); | |
} | |
script.add(Opcode.smallInt(publicKeys.length)); | |
script.add(Opcode.OP_CHECKMULTISIG); | |
return script; | |
}; | |
/** | |
* A new Multisig input script for the given public keys, requiring m of those public keys to spend | |
* | |
* @param {PublicKey[]} pubkeys list of all public keys controlling the output | |
* @param {number} threshold amount of required signatures to spend the output | |
* @param {Array} signatures and array of signature buffers to append to the script | |
* @param {Object=} opts | |
* @param {boolean=} opts.noSorting don't sort the given public keys before creating the script (false by default) | |
* @param {Script=} opts.cachedMultisig don't recalculate the redeemScript | |
* | |
* @returns {Script} | |
*/ | |
Script.buildMultisigIn = function (pubkeys, threshold, signatures, opts) { | |
$.checkArgument(_.isArray(pubkeys)); | |
$.checkArgument(_.isNumber(threshold)); | |
$.checkArgument(_.isArray(signatures)); | |
opts = opts || {}; | |
var s = new Script(); | |
s.add(Opcode.OP_0); | |
_.each(signatures, function (signature) { | |
$.checkArgument(BufferUtil.isBuffer(signature), 'Signatures must be an array of Buffers'); | |
// TODO: allow signatures to be an array of Signature objects | |
s.add(signature); | |
}); | |
return s; | |
}; | |
/** | |
* A new P2SH Multisig input script for the given public keys, requiring m of those public keys to spend | |
* | |
* @param {PublicKey[]} pubkeys list of all public keys controlling the output | |
* @param {number} threshold amount of required signatures to spend the output | |
* @param {Array} signatures and array of signature buffers to append to the script | |
* @param {Object=} opts | |
* @param {boolean=} opts.noSorting don't sort the given public keys before creating the script (false by default) | |
* @param {Script=} opts.cachedMultisig don't recalculate the redeemScript | |
* | |
* @returns {Script} | |
*/ | |
Script.buildP2SHMultisigIn = function (pubkeys, threshold, signatures, opts) { | |
$.checkArgument(_.isArray(pubkeys)); | |
$.checkArgument(_.isNumber(threshold)); | |
$.checkArgument(_.isArray(signatures)); | |
opts = opts || {}; | |
var s = new Script(); | |
s.add(Opcode.OP_0); | |
_.each(signatures, function (signature) { | |
$.checkArgument(BufferUtil.isBuffer(signature), 'Signatures must be an array of Buffers'); | |
// TODO: allow signatures to be an array of Signature objects | |
s.add(signature); | |
}); | |
s.add((opts.cachedMultisig || Script.buildMultisigOut(pubkeys, threshold, opts)).toBuffer()); | |
return s; | |
}; | |
/** | |
* @returns {Script} a new pay to public key hash output for the given | |
* address or public key | |
* @param {(Address|PublicKey)} to - destination address or public key | |
*/ | |
Script.buildPublicKeyHashOut = function (to) { | |
$.checkArgument(!_.isUndefined(to)); | |
$.checkArgument(to instanceof PublicKey || to instanceof Address || _.isString(to)); | |
if (to instanceof PublicKey) { | |
to = to.toAddress(); | |
} else if (_.isString(to)) { | |
to = new Address(to); | |
} | |
var s = new Script(); | |
s.add(Opcode.OP_DUP).add(Opcode.OP_HASH160).add(to.hashBuffer).add(Opcode.OP_EQUALVERIFY).add(Opcode.OP_CHECKSIG); | |
s._network = to.network; | |
return s; | |
}; | |
/** | |
* @returns {Script} a new pay to public key output for the given | |
* public key | |
*/ | |
Script.buildPublicKeyOut = function (pubkey) { | |
$.checkArgument(pubkey instanceof PublicKey); | |
var s = new Script(); | |
s.add(pubkey.toBuffer()).add(Opcode.OP_CHECKSIG); | |
return s; | |
}; | |
/** | |
* @returns {Script} a new OP_RETURN script with data | |
* @param {(string|Buffer)} data - the data to embed in the output | |
* @param {(string)} encoding - the type of encoding of the string | |
*/ | |
Script.buildDataOut = function (data, encoding) { | |
$.checkArgument(_.isUndefined(data) || _.isString(data) || BufferUtil.isBuffer(data)); | |
if (_.isString(data)) { | |
data = new Buffer(data, encoding); | |
} | |
var s = new Script(); | |
s.add(Opcode.OP_RETURN); | |
if (!_.isUndefined(data)) { | |
s.add(data); | |
} | |
return s; | |
}; | |
/** | |
* @param {Script|Address} script - the redeemScript for the new p2sh output. | |
* It can also be a p2sh address | |
* @returns {Script} new pay to script hash script for given script | |
*/ | |
Script.buildScriptHashOut = function (script) { | |
$.checkArgument(script instanceof Script || script instanceof Address && script.isPayToScriptHash()); | |
var s = new Script(); | |
s.add(Opcode.OP_HASH160).add(script instanceof Address ? script.hashBuffer : Hash.sha256ripemd160(script.toBuffer())).add(Opcode.OP_EQUAL); | |
s._network = script._network || script.network; | |
return s; | |
}; | |
/** | |
* Builds a scriptSig (a script for an input) that signs a public key output script. | |
* | |
* @param {Signature|Buffer} signature - a Signature object, or the signature in DER canonical encoding | |
* @param {number=} sigtype - the type of the signature (defaults to SIGHASH_ALL) | |
*/ | |
Script.buildPublicKeyIn = function (signature, sigtype) { | |
$.checkArgument(signature instanceof Signature || BufferUtil.isBuffer(signature)); | |
$.checkArgument(_.isUndefined(sigtype) || _.isNumber(sigtype)); | |
if (signature instanceof Signature) { | |
signature = signature.toBuffer(); | |
} | |
var script = new Script(); | |
script.add(BufferUtil.concat([signature, BufferUtil.integerAsSingleByteBuffer(sigtype || Signature.SIGHASH_ALL)])); | |
return script; | |
}; | |
/** | |
* Builds a scriptSig (a script for an input) that signs a public key hash | |
* output script. | |
* | |
* @param {Buffer|string|PublicKey} publicKey | |
* @param {Signature|Buffer} signature - a Signature object, or the signature in DER canonical encoding | |
* @param {number=} sigtype - the type of the signature (defaults to SIGHASH_ALL) | |
*/ | |
Script.buildPublicKeyHashIn = function (publicKey, signature, sigtype) { | |
$.checkArgument(signature instanceof Signature || BufferUtil.isBuffer(signature)); | |
$.checkArgument(_.isUndefined(sigtype) || _.isNumber(sigtype)); | |
if (signature instanceof Signature) { | |
signature = signature.toBuffer(); | |
} | |
var script = new Script().add(BufferUtil.concat([signature, BufferUtil.integerAsSingleByteBuffer(sigtype || Signature.SIGHASH_ALL)])).add(new PublicKey(publicKey).toBuffer()); | |
return script; | |
}; | |
/** | |
* @returns {Script} an empty script | |
*/ | |
Script.empty = function () { | |
return new Script(); | |
}; | |
/** | |
* @returns {Script} a new pay to script hash script that pays to this script | |
*/ | |
Script.prototype.toScriptHashOut = function () { | |
return Script.buildScriptHashOut(this); | |
}; | |
/** | |
* @return {Script} an output script built from the address | |
*/ | |
Script.fromAddress = function (address) { | |
address = Address(address); | |
if (address.isPayToScriptHash()) { | |
return Script.buildScriptHashOut(address); | |
} else if (address.isPayToPublicKeyHash()) { | |
return Script.buildPublicKeyHashOut(address); | |
} | |
throw new errors.Script.UnrecognizedAddress(address); | |
}; | |
/** | |
* Will return the associated address information object | |
* @return {Address|boolean} | |
*/ | |
Script.prototype.getAddressInfo = function (opts) { | |
if (this._isInput) { | |
return this._getInputAddressInfo(); | |
} else if (this._isOutput) { | |
return this._getOutputAddressInfo(); | |
} else { | |
var info = this._getOutputAddressInfo(); | |
if (!info) { | |
return this._getInputAddressInfo(); | |
} | |
return info; | |
} | |
}; | |
/** | |
* Will return the associated output scriptPubKey address information object | |
* @return {Address|boolean} | |
* @private | |
*/ | |
Script.prototype._getOutputAddressInfo = function () { | |
var info = {}; | |
if (this.isScriptHashOut()) { | |
info.hashBuffer = this.getData(); | |
info.type = Address.PayToScriptHash; | |
} else if (this.isPublicKeyHashOut()) { | |
info.hashBuffer = this.getData(); | |
info.type = Address.PayToPublicKeyHash; | |
} else { | |
return false; | |
} | |
return info; | |
}; | |
/** | |
* Will return the associated input scriptSig address information object | |
* @return {Address|boolean} | |
* @private | |
*/ | |
Script.prototype._getInputAddressInfo = function () { | |
var info = {}; | |
if (this.isPublicKeyHashIn()) { | |
// hash the publickey found in the scriptSig | |
info.hashBuffer = Hash.sha256ripemd160(this.chunks[1].buf); | |
info.type = Address.PayToPublicKeyHash; | |
} else if (this.isScriptHashIn()) { | |
// hash the redeemscript found at the end of the scriptSig | |
info.hashBuffer = Hash.sha256ripemd160(this.chunks[this.chunks.length - 1].buf); | |
info.type = Address.PayToScriptHash; | |
} else { | |
return false; | |
} | |
return info; | |
}; | |
/** | |
* @param {Network=} network | |
* @return {Address|boolean} the associated address for this script if possible, or false | |
*/ | |
Script.prototype.toAddress = function (network) { | |
var info = this.getAddressInfo(); | |
if (!info) { | |
return false; | |
} | |
info.network = Networks.get(network) || this._network || Networks.defaultNetwork; | |
return new Address(info); | |
}; | |
/** | |
* Analogous to bitcoind's FindAndDelete. Find and delete equivalent chunks, | |
* typically used with push data chunks. Note that this will find and delete | |
* not just the same data, but the same data with the same push data op as | |
* produced by default. i.e., if a pushdata in a tx does not use the minimal | |
* pushdata op, then when you try to remove the data it is pushing, it will not | |
* be removed, because they do not use the same pushdata op. | |
*/ | |
Script.prototype.findAndDelete = function (script) { | |
var buf = script.toBuffer(); | |
var hex = buf.toString('hex'); | |
for (var i = 0; i < this.chunks.length; i++) { | |
var script2 = Script({ | |
chunks: [this.chunks[i]] | |
}); | |
var buf2 = script2.toBuffer(); | |
var hex2 = buf2.toString('hex'); | |
if (hex === hex2) { | |
this.chunks.splice(i, 1); | |
} | |
} | |
return this; | |
}; | |
/** | |
* Comes from bitcoind's script interpreter CheckMinimalPush function | |
* @returns {boolean} if the chunk {i} is the smallest way to push that particular data. | |
*/ | |
Script.prototype.checkMinimalPush = function (i) { | |
var chunk = this.chunks[i]; | |
var buf = chunk.buf; | |
var opcodenum = chunk.opcodenum; | |
if (!buf) { | |
return true; | |
} | |
if (buf.length === 0) { | |
// Could have used OP_0. | |
return opcodenum === Opcode.OP_0; | |
} else if (buf.length === 1 && buf[0] >= 1 && buf[0] <= 16) { | |
// Could have used OP_1 .. OP_16. | |
return opcodenum === Opcode.OP_1 + (buf[0] - 1); | |
} else if (buf.length === 1 && buf[0] === 0x81) { | |
// Could have used OP_1NEGATE | |
return opcodenum === Opcode.OP_1NEGATE; | |
} else if (buf.length <= 75) { | |
// Could have used a direct push (opcode indicating number of bytes pushed + those bytes). | |
return opcodenum === buf.length; | |
} else if (buf.length <= 255) { | |
// Could have used OP_PUSHDATA. | |
return opcodenum === Opcode.OP_PUSHDATA1; | |
} else if (buf.length <= 65535) { | |
// Could have used OP_PUSHDATA2. | |
return opcodenum === Opcode.OP_PUSHDATA2; | |
} | |
return true; | |
}; | |
/** | |
* Comes from bitcoind's script DecodeOP_N function | |
* @param {number} opcode | |
* @returns {number} numeric value in range of 0 to 16 | |
*/ | |
Script.prototype._decodeOP_N = function (opcode) { | |
if (opcode === Opcode.OP_0) { | |
return 0; | |
} else if (opcode >= Opcode.OP_1 && opcode <= Opcode.OP_16) { | |
return opcode - (Opcode.OP_1 - 1); | |
} else { | |
throw new Error('Invalid opcode: ' + JSON.stringify(opcode)); | |
} | |
}; | |
/** | |
* Comes from bitcoind's script GetSigOpCount(boolean) function | |
* @param {boolean} use current (true) or pre-version-0.6 (false) logic | |
* @returns {number} number of signature operations required by this script | |
*/ | |
Script.prototype.getSignatureOperationsCount = function (accurate) { | |
accurate = _.isUndefined(accurate) ? true : accurate; | |
var self = this; | |
var n = 0; | |
var lastOpcode = Opcode.OP_INVALIDOPCODE; | |
_.each(self.chunks, function getChunk(chunk) { | |
var opcode = chunk.opcodenum; | |
if (opcode == Opcode.OP_CHECKSIG || opcode == Opcode.OP_CHECKSIGVERIFY) { | |
n++; | |
} else if (opcode == Opcode.OP_CHECKMULTISIG || opcode == Opcode.OP_CHECKMULTISIGVERIFY) { | |
if (accurate && lastOpcode >= Opcode.OP_1 && lastOpcode <= Opcode.OP_16) { | |
n += self._decodeOP_N(lastOpcode); | |
} else { | |
n += 20; | |
} | |
} | |
lastOpcode = opcode; | |
}); | |
return n; | |
}; | |
module.exports = Script; | |
}).call(this,require("buffer").Buffer) | |
},{"../address":27,"../crypto/hash":34,"../crypto/signature":37,"../encoding/bufferreader":40,"../encoding/bufferwriter":41,"../errors":43,"../networks":47,"../opcode":48,"../publickey":50,"../util/buffer":68,"../util/js":69,"../util/preconditions":70,"buffer":148,"lodash":267}],54:[function(require,module,exports){ | |
'use strict'; | |
module.exports = require('./transaction'); | |
module.exports.Input = require('./input'); | |
module.exports.Output = require('./output'); | |
module.exports.UnspentOutput = require('./unspentoutput'); | |
module.exports.Signature = require('./signature'); | |
module.exports.Sighash = require('./sighash'); | |
},{"./input":55,"./output":61,"./sighash":62,"./signature":63,"./transaction":64,"./unspentoutput":65}],55:[function(require,module,exports){ | |
'use strict'; | |
module.exports = require('./input'); | |
module.exports.PublicKey = require('./publickey'); | |
module.exports.PublicKeyHash = require('./publickeyhash'); | |
module.exports.MultiSig = require('./multisig.js'); | |
module.exports.MultiSigScriptHash = require('./multisigscripthash.js'); | |
},{"./input":56,"./multisig.js":57,"./multisigscripthash.js":58,"./publickey":59,"./publickeyhash":60}],56:[function(require,module,exports){ | |
'use strict'; | |
var _ = require('lodash'); | |
var $ = require('../../util/preconditions'); | |
var errors = require('../../errors'); | |
var BufferWriter = require('../../encoding/bufferwriter'); | |
var buffer = require('buffer'); | |
var BufferUtil = require('../../util/buffer'); | |
var JSUtil = require('../../util/js'); | |
var Script = require('../../script'); | |
var Sighash = require('../sighash'); | |
var Output = require('../output'); | |
var MAXINT = 0xffffffff; // Math.pow(2, 32) - 1; | |
var DEFAULT_RBF_SEQNUMBER = MAXINT - 2; | |
var DEFAULT_SEQNUMBER = MAXINT; | |
var DEFAULT_LOCKTIME_SEQNUMBER = MAXINT - 1; | |
function Input(params) { | |
if (!(this instanceof Input)) { | |
return new Input(params); | |
} | |
if (params) { | |
return this._fromObject(params); | |
} | |
} | |
Input.MAXINT = MAXINT; | |
Input.DEFAULT_SEQNUMBER = DEFAULT_SEQNUMBER; | |
Input.DEFAULT_LOCKTIME_SEQNUMBER = DEFAULT_LOCKTIME_SEQNUMBER; | |
Input.DEFAULT_RBF_SEQNUMBER = DEFAULT_RBF_SEQNUMBER; | |
Object.defineProperty(Input.prototype, 'script', { | |
configurable: false, | |
enumerable: true, | |
get: function get() { | |
if (this.isNull()) { | |
return null; | |
} | |
if (!this._script) { | |
this._script = new Script(this._scriptBuffer); | |
this._script._isInput = true; | |
} | |
return this._script; | |
} | |
}); | |
Input.fromObject = function (obj) { | |
$.checkArgument(_.isObject(obj)); | |
var input = new Input(); | |
return input._fromObject(obj); | |
}; | |
Input.prototype._fromObject = function (params) { | |
var prevTxId; | |
if (_.isString(params.prevTxId) && JSUtil.isHexa(params.prevTxId)) { | |
prevTxId = new buffer.Buffer(params.prevTxId, 'hex'); | |
} else { | |
prevTxId = params.prevTxId; | |
} | |
this.output = params.output ? params.output instanceof Output ? params.output : new Output(params.output) : undefined; | |
this.prevTxId = prevTxId || params.txidbuf; | |
this.outputIndex = _.isUndefined(params.outputIndex) ? params.txoutnum : params.outputIndex; | |
this.sequenceNumber = _.isUndefined(params.sequenceNumber) ? _.isUndefined(params.seqnum) ? DEFAULT_SEQNUMBER : params.seqnum : params.sequenceNumber; | |
if (_.isUndefined(params.script) && _.isUndefined(params.scriptBuffer)) { | |
throw new errors.Transaction.Input.MissingScript(); | |
} | |
this.setScript(params.scriptBuffer || params.script); | |
return this; | |
}; | |
Input.prototype.toObject = Input.prototype.toJSON = function toObject() { | |
var obj = { | |
prevTxId: this.prevTxId.toString('hex'), | |
outputIndex: this.outputIndex, | |
sequenceNumber: this.sequenceNumber, | |
script: this._scriptBuffer.toString('hex') | |
}; | |
// add human readable form if input contains valid script | |
if (this.script) { | |
obj.scriptString = this.script.toString(); | |
} | |
if (this.output) { | |
obj.output = this.output.toObject(); | |
} | |
return obj; | |
}; | |
Input.fromBufferReader = function (br) { | |
var input = new Input(); | |
input.prevTxId = br.readReverse(32); | |
input.outputIndex = br.readUInt32LE(); | |
input._scriptBuffer = br.readVarLengthBuffer(); | |
input.sequenceNumber = br.readUInt32LE(); | |
// TODO: return different classes according to which input it is | |
// e.g: CoinbaseInput, PublicKeyHashInput, MultiSigScriptHashInput, etc. | |
return input; | |
}; | |
Input.prototype.toBufferWriter = function (writer) { | |
if (!writer) { | |
writer = new BufferWriter(); | |
} | |
writer.writeReverse(this.prevTxId); | |
writer.writeUInt32LE(this.outputIndex); | |
var script = this._scriptBuffer; | |
writer.writeVarintNum(script.length); | |
writer.write(script); | |
writer.writeUInt32LE(this.sequenceNumber); | |
return writer; | |
}; | |
Input.prototype.setScript = function (script) { | |
this._script = null; | |
if (script instanceof Script) { | |
this._script = script; | |
this._script._isInput = true; | |
this._scriptBuffer = script.toBuffer(); | |
} else if (JSUtil.isHexa(script)) { | |
// hex string script | |
this._scriptBuffer = new buffer.Buffer(script, 'hex'); | |
} else if (_.isString(script)) { | |
// human readable string script | |
this._script = new Script(script); | |
this._script._isInput = true; | |
this._scriptBuffer = this._script.toBuffer(); | |
} else if (BufferUtil.isBuffer(script)) { | |
// buffer script | |
this._scriptBuffer = new buffer.Buffer(script); | |
} else { | |
throw new TypeError('Invalid argument type: script'); | |
} | |
return this; | |
}; | |
/** | |
* Retrieve signatures for the provided PrivateKey. | |
* | |
* @param {Transaction} transaction - the transaction to be signed | |
* @param {PrivateKey} privateKey - the private key to use when signing | |
* @param {number} inputIndex - the index of this input in the provided transaction | |
* @param {number} sigType - defaults to Signature.SIGHASH_ALL | |
* @param {Buffer} addressHash - if provided, don't calculate the hash of the | |
* public key associated with the private key provided | |
* @abstract | |
*/ | |
Input.prototype.getSignatures = function () { | |
throw new errors.AbstractMethodInvoked('Trying to sign unsupported output type (only P2PKH and P2SH multisig inputs are supported)' + ' for input: ' + JSON.stringify(this)); | |
}; | |
Input.prototype.isFullySigned = function () { | |
throw new errors.AbstractMethodInvoked('Input#isFullySigned'); | |
}; | |
Input.prototype.isFinal = function () { | |
return this.sequenceNumber !== 4294967295; | |
}; | |
Input.prototype.addSignature = function () { | |
throw new errors.AbstractMethodInvoked('Input#addSignature'); | |
}; | |
Input.prototype.clearSignatures = function () { | |
throw new errors.AbstractMethodInvoked('Input#clearSignatures'); | |
}; | |
Input.prototype.isValidSignature = function (transaction, signature) { | |
// FIXME: Refactor signature so this is not necessary | |
signature.signature.nhashtype = signature.sigtype; | |
return Sighash.verify(transaction, signature.signature, signature.publicKey, signature.inputIndex, this.output.script); | |
}; | |
/** | |
* @returns true if this is a coinbase input (represents no input) | |
*/ | |
Input.prototype.isNull = function () { | |
return this.prevTxId.toString('hex') === '0000000000000000000000000000000000000000000000000000000000000000' && this.outputIndex === 0xffffffff; | |
}; | |
Input.prototype._estimateSize = function () { | |
return this.toBufferWriter().toBuffer().length; | |
}; | |
module.exports = Input; | |
},{"../../encoding/bufferwriter":41,"../../errors":43,"../../script":51,"../../util/buffer":68,"../../util/js":69,"../../util/preconditions":70,"../output":61,"../sighash":62,"buffer":148,"lodash":267}],57:[function(require,module,exports){ | |
'use strict'; | |
var _ = require('lodash'); | |
var inherits = require('inherits'); | |
var Transaction = require('../transaction'); | |
var Input = require('./input'); | |
var Output = require('../output'); | |
var $ = require('../../util/preconditions'); | |
var Script = require('../../script'); | |
var Signature = require('../../crypto/signature'); | |
var Sighash = require('../sighash'); | |
var PublicKey = require('../../publickey'); | |
var BufferUtil = require('../../util/buffer'); | |
var TransactionSignature = require('../signature'); | |
/** | |
* @constructor | |
*/ | |
function MultiSigInput(input, pubkeys, threshold, signatures) { | |
Input.apply(this, arguments); | |
var self = this; | |
pubkeys = pubkeys || input.publicKeys; | |
threshold = threshold || input.threshold; | |
signatures = signatures || input.signatures; | |
this.publicKeys = _.sortBy(pubkeys, function (publicKey) { | |
return publicKey.toString('hex'); | |
}); | |
$.checkState(Script.buildMultisigOut(this.publicKeys, threshold).equals(this.output.script), 'Provided public keys don\'t match to the provided output script'); | |
this.publicKeyIndex = {}; | |
_.each(this.publicKeys, function (publicKey, index) { | |
self.publicKeyIndex[publicKey.toString()] = index; | |
}); | |
this.threshold = threshold; | |
// Empty array of signatures | |
this.signatures = signatures ? this._deserializeSignatures(signatures) : new Array(this.publicKeys.length); | |
} | |
inherits(MultiSigInput, Input); | |
MultiSigInput.prototype.toObject = function () { | |
var obj = Input.prototype.toObject.apply(this, arguments); | |
obj.threshold = this.threshold; | |
obj.publicKeys = _.map(this.publicKeys, function (publicKey) { | |
return publicKey.toString(); | |
}); | |
obj.signatures = this._serializeSignatures(); | |
return obj; | |
}; | |
MultiSigInput.prototype._deserializeSignatures = function (signatures) { | |
return _.map(signatures, function (signature) { | |
if (!signature) { | |
return undefined; | |
} | |
return new TransactionSignature(signature); | |
}); | |
}; | |
MultiSigInput.prototype._serializeSignatures = function () { | |
return _.map(this.signatures, function (signature) { | |
if (!signature) { | |
return undefined; | |
} | |
return signature.toObject(); | |
}); | |
}; | |
MultiSigInput.prototype.getSignatures = function (transaction, privateKey, index, sigtype) { | |
$.checkState(this.output instanceof Output); | |
sigtype = sigtype || Signature.SIGHASH_ALL; | |
var self = this; | |
var results = []; | |
_.each(this.publicKeys, function (publicKey) { | |
if (publicKey.toString() === privateKey.publicKey.toString()) { | |
results.push(new TransactionSignature({ | |
publicKey: privateKey.publicKey, | |
prevTxId: self.prevTxId, | |
outputIndex: self.outputIndex, | |
inputIndex: index, | |
signature: Sighash.sign(transaction, privateKey, sigtype, index, self.output.script), | |
sigtype: sigtype | |
})); | |
} | |
}); | |
return results; | |
}; | |
MultiSigInput.prototype.addSignature = function (transaction, signature) { | |
$.checkState(!this.isFullySigned(), 'All needed signatures have already been added'); | |
$.checkArgument(!_.isUndefined(this.publicKeyIndex[signature.publicKey.toString()]), 'Signature has no matching public key'); | |
$.checkState(this.isValidSignature(transaction, signature)); | |
this.signatures[this.publicKeyIndex[signature.publicKey.toString()]] = signature; | |
this._updateScript(); | |
return this; | |
}; | |
MultiSigInput.prototype._updateScript = function () { | |
this.setScript(Script.buildMultisigIn(this.publicKeys, this.threshold, this._createSignatures())); | |
return this; | |
}; | |
MultiSigInput.prototype._createSignatures = function () { | |
return _.map(_.filter(this.signatures, function (signature) { | |
return !_.isUndefined(signature); | |
}), function (signature) { | |
return BufferUtil.concat([signature.signature.toDER(), BufferUtil.integerAsSingleByteBuffer(signature.sigtype)]); | |
}); | |
}; | |
MultiSigInput.prototype.clearSignatures = function () { | |
this.signatures = new Array(this.publicKeys.length); | |
this._updateScript(); | |
}; | |
MultiSigInput.prototype.isFullySigned = function () { | |
return this.countSignatures() === this.threshold; | |
}; | |
MultiSigInput.prototype.countMissingSignatures = function () { | |
return this.threshold - this.countSignatures(); | |
}; | |
MultiSigInput.prototype.countSignatures = function () { | |
return _.reduce(this.signatures, function (sum, signature) { | |
return sum + !!signature; | |
}, 0); | |
}; | |
MultiSigInput.prototype.publicKeysWithoutSignature = function () { | |
var self = this; | |
return _.filter(this.publicKeys, function (publicKey) { | |
return !self.signatures[self.publicKeyIndex[publicKey.toString()]]; | |
}); | |
}; | |
MultiSigInput.prototype.isValidSignature = function (transaction, signature) { | |
// FIXME: Refactor signature so this is not necessary | |
signature.signature.nhashtype = signature.sigtype; | |
return Sighash.verify(transaction, signature.signature, signature.publicKey, signature.inputIndex, this.output.script); | |
}; | |
/** | |
* | |
* @param {Buffer[]} signatures | |
* @param {PublicKey[]} publicKeys | |
* @param {Transaction} transaction | |
* @param {Integer} inputIndex | |
* @param {Input} input | |
* @returns {TransactionSignature[]} | |
*/ | |
MultiSigInput.normalizeSignatures = function (transaction, input, inputIndex, signatures, publicKeys) { | |
return publicKeys.map(function (pubKey) { | |
var signatureMatch = null; | |
signatures = signatures.filter(function (signatureBuffer) { | |
if (signatureMatch) { | |
return true; | |
} | |
var signature = new TransactionSignature({ | |
signature: Signature.fromTxFormat(signatureBuffer), | |
publicKey: pubKey, | |
prevTxId: input.prevTxId, | |
outputIndex: input.outputIndex, | |
inputIndex: inputIndex, | |
sigtype: Signature.SIGHASH_ALL | |
}); | |
signature.signature.nhashtype = signature.sigtype; | |
var isMatch = Sighash.verify(transaction, signature.signature, signature.publicKey, signature.inputIndex, input.output.script); | |
if (isMatch) { | |
signatureMatch = signature; | |
return false; | |
} | |
return true; | |
}); | |
return signatureMatch ? signatureMatch : null; | |
}); | |
}; | |
MultiSigInput.OPCODES_SIZE = 1; // 0 | |
MultiSigInput.SIGNATURE_SIZE = 73; // size (1) + DER (<=72) | |
MultiSigInput.prototype._estimateSize = function () { | |
return MultiSigInput.OPCODES_SIZE + this.threshold * MultiSigInput.SIGNATURE_SIZE; | |
}; | |
module.exports = MultiSigInput; | |
},{"../../crypto/signature":37,"../../publickey":50,"../../script":51,"../../util/buffer":68,"../../util/preconditions":70,"../output":61,"../sighash":62,"../signature":63,"../transaction":64,"./input":56,"inherits":256,"lodash":267}],58:[function(require,module,exports){ | |
'use strict'; | |
var _ = require('lodash'); | |
var inherits = require('inherits'); | |
var Input = require('./input'); | |
var Output = require('../output'); | |
var $ = require('../../util/preconditions'); | |
var Script = require('../../script'); | |
var Signature = require('../../crypto/signature'); | |
var Sighash = require('../sighash'); | |
var PublicKey = require('../../publickey'); | |
var BufferUtil = require('../../util/buffer'); | |
var TransactionSignature = require('../signature'); | |
/** | |
* @constructor | |
*/ | |
function MultiSigScriptHashInput(input, pubkeys, threshold, signatures) { | |
Input.apply(this, arguments); | |
var self = this; | |
pubkeys = pubkeys || input.publicKeys; | |
threshold = threshold || input.threshold; | |
signatures = signatures || input.signatures; | |
this.publicKeys = _.sortBy(pubkeys, function (publicKey) { | |
return publicKey.toString('hex'); | |
}); | |
this.redeemScript = Script.buildMultisigOut(this.publicKeys, threshold); | |
$.checkState(Script.buildScriptHashOut(this.redeemScript).equals(this.output.script), 'Provided public keys don\'t hash to the provided output'); | |
this.publicKeyIndex = {}; | |
_.each(this.publicKeys, function (publicKey, index) { | |
self.publicKeyIndex[publicKey.toString()] = index; | |
}); | |
this.threshold = threshold; | |
// Empty array of signatures | |
this.signatures = signatures ? this._deserializeSignatures(signatures) : new Array(this.publicKeys.length); | |
} | |
inherits(MultiSigScriptHashInput, Input); | |
MultiSigScriptHashInput.prototype.toObject = function () { | |
var obj = Input.prototype.toObject.apply(this, arguments); | |
obj.threshold = this.threshold; | |
obj.publicKeys = _.map(this.publicKeys, function (publicKey) { | |
return publicKey.toString(); | |
}); | |
obj.signatures = this._serializeSignatures(); | |
return obj; | |
}; | |
MultiSigScriptHashInput.prototype._deserializeSignatures = function (signatures) { | |
return _.map(signatures, function (signature) { | |
if (!signature) { | |
return undefined; | |
} | |
return new TransactionSignature(signature); | |
}); | |
}; | |
MultiSigScriptHashInput.prototype._serializeSignatures = function () { | |
return _.map(this.signatures, function (signature) { | |
if (!signature) { | |
return undefined; | |
} | |
return signature.toObject(); | |
}); | |
}; | |
MultiSigScriptHashInput.prototype.getSignatures = function (transaction, privateKey, index, sigtype) { | |
$.checkState(this.output instanceof Output); | |
sigtype = sigtype || Signature.SIGHASH_ALL; | |
var self = this; | |
var results = []; | |
_.each(this.publicKeys, function (publicKey) { | |
if (publicKey.toString() === privateKey.publicKey.toString()) { | |
results.push(new TransactionSignature({ | |
publicKey: privateKey.publicKey, | |
prevTxId: self.prevTxId, | |
outputIndex: self.outputIndex, | |
inputIndex: index, | |
signature: Sighash.sign(transaction, privateKey, sigtype, index, self.redeemScript), | |
sigtype: sigtype | |
})); | |
} | |
}); | |
return results; | |
}; | |
MultiSigScriptHashInput.prototype.addSignature = function (transaction, signature) { | |
$.checkState(!this.isFullySigned(), 'All needed signatures have already been added'); | |
$.checkArgument(!_.isUndefined(this.publicKeyIndex[signature.publicKey.toString()]), 'Signature has no matching public key'); | |
$.checkState(this.isValidSignature(transaction, signature)); | |
this.signatures[this.publicKeyIndex[signature.publicKey.toString()]] = signature; | |
this._updateScript(); | |
return this; | |
}; | |
MultiSigScriptHashInput.prototype._updateScript = function () { | |
this.setScript(Script.buildP2SHMultisigIn(this.publicKeys, this.threshold, this._createSignatures(), { cachedMultisig: this.redeemScript })); | |
return this; | |
}; | |
MultiSigScriptHashInput.prototype._createSignatures = function () { | |
return _.map(_.filter(this.signatures, function (signature) { | |
return !_.isUndefined(signature); | |
}), function (signature) { | |
return BufferUtil.concat([signature.signature.toDER(), BufferUtil.integerAsSingleByteBuffer(signature.sigtype)]); | |
}); | |
}; | |
MultiSigScriptHashInput.prototype.clearSignatures = function () { | |
this.signatures = new Array(this.publicKeys.length); | |
this._updateScript(); | |
}; | |
MultiSigScriptHashInput.prototype.isFullySigned = function () { | |
return this.countSignatures() === this.threshold; | |
}; | |
MultiSigScriptHashInput.prototype.countMissingSignatures = function () { | |
return this.threshold - this.countSignatures(); | |
}; | |
MultiSigScriptHashInput.prototype.countSignatures = function () { | |
return _.reduce(this.signatures, function (sum, signature) { | |
return sum + !!signature; | |
}, 0); | |
}; | |
MultiSigScriptHashInput.prototype.publicKeysWithoutSignature = function () { | |
var self = this; | |
return _.filter(this.publicKeys, function (publicKey) { | |
return !self.signatures[self.publicKeyIndex[publicKey.toString()]]; | |
}); | |
}; | |
MultiSigScriptHashInput.prototype.isValidSignature = function (transaction, signature) { | |
// FIXME: Refactor signature so this is not necessary | |
signature.signature.nhashtype = signature.sigtype; | |
return Sighash.verify(transaction, signature.signature, signature.publicKey, signature.inputIndex, this.redeemScript); | |
}; | |
MultiSigScriptHashInput.OPCODES_SIZE = 7; // serialized size (<=3) + 0 .. N .. M OP_CHECKMULTISIG | |
MultiSigScriptHashInput.SIGNATURE_SIZE = 74; // size (1) + DER (<=72) + sighash (1) | |
MultiSigScriptHashInput.PUBKEY_SIZE = 34; // size (1) + DER (<=33) | |
MultiSigScriptHashInput.prototype._estimateSize = function () { | |
return MultiSigScriptHashInput.OPCODES_SIZE + this.threshold * MultiSigScriptHashInput.SIGNATURE_SIZE + this.publicKeys.length * MultiSigScriptHashInput.PUBKEY_SIZE; | |
}; | |
module.exports = MultiSigScriptHashInput; | |
},{"../../crypto/signature":37,"../../publickey":50,"../../script":51,"../../util/buffer":68,"../../util/preconditions":70,"../output":61,"../sighash":62,"../signature":63,"./input":56,"inherits":256,"lodash":267}],59:[function(require,module,exports){ | |
'use strict'; | |
var inherits = require('inherits'); | |
var $ = require('../../util/preconditions'); | |
var BufferUtil = require('../../util/buffer'); | |
var Input = require('./input'); | |
var Output = require('../output'); | |
var Sighash = require('../sighash'); | |
var Script = require('../../script'); | |
var Signature = require('../../crypto/signature'); | |
var TransactionSignature = require('../signature'); | |
/** | |
* Represents a special kind of input of PayToPublicKey kind. | |
* @constructor | |
*/ | |
function PublicKeyInput() { | |
Input.apply(this, arguments); | |
} | |
inherits(PublicKeyInput, Input); | |
/** | |
* @param {Transaction} transaction - the transaction to be signed | |
* @param {PrivateKey} privateKey - the private key with which to sign the transaction | |
* @param {number} index - the index of the input in the transaction input vector | |
* @param {number=} sigtype - the type of signature, defaults to Signature.SIGHASH_ALL | |
* @return {Array} of objects that can be | |
*/ | |
PublicKeyInput.prototype.getSignatures = function (transaction, privateKey, index, sigtype) { | |
$.checkState(this.output instanceof Output); | |
sigtype = sigtype || Signature.SIGHASH_ALL; | |
var publicKey = privateKey.toPublicKey(); | |
if (publicKey.toString() === this.output.script.getPublicKey().toString('hex')) { | |
return [new TransactionSignature({ | |
publicKey: publicKey, | |
prevTxId: this.prevTxId, | |
outputIndex: this.outputIndex, | |
inputIndex: index, | |
signature: Sighash.sign(transaction, privateKey, sigtype, index, this.output.script), | |
sigtype: sigtype | |
})]; | |
} | |
return []; | |
}; | |
/** | |
* Add the provided signature | |
* | |
* @param {Object} signature | |
* @param {PublicKey} signature.publicKey | |
* @param {Signature} signature.signature | |
* @param {number=} signature.sigtype | |
* @return {PublicKeyInput} this, for chaining | |
*/ | |
PublicKeyInput.prototype.addSignature = function (transaction, signature) { | |
$.checkState(this.isValidSignature(transaction, signature), 'Signature is invalid'); | |
this.setScript(Script.buildPublicKeyIn(signature.signature.toDER(), signature.sigtype)); | |
return this; | |
}; | |
/** | |
* Clear the input's signature | |
* @return {PublicKeyHashInput} this, for chaining | |
*/ | |
PublicKeyInput.prototype.clearSignatures = function () { | |
this.setScript(Script.empty()); | |
return this; | |
}; | |
/** | |
* Query whether the input is signed | |
* @return {boolean} | |
*/ | |
PublicKeyInput.prototype.isFullySigned = function () { | |
return this.script.isPublicKeyIn(); | |
}; | |
PublicKeyInput.SCRIPT_MAX_SIZE = 73; // sigsize (1 + 72) | |
PublicKeyInput.prototype._estimateSize = function () { | |
return PublicKeyInput.SCRIPT_MAX_SIZE; | |
}; | |
module.exports = PublicKeyInput; | |
},{"../../crypto/signature":37,"../../script":51,"../../util/buffer":68,"../../util/preconditions":70,"../output":61,"../sighash":62,"../signature":63,"./input":56,"inherits":256}],60:[function(require,module,exports){ | |
'use strict'; | |
var inherits = require('inherits'); | |
var $ = require('../../util/preconditions'); | |
var BufferUtil = require('../../util/buffer'); | |
var Hash = require('../../crypto/hash'); | |
var Input = require('./input'); | |
var Output = require('../output'); | |
var Sighash = require('../sighash'); | |
var Script = require('../../script'); | |
var Signature = require('../../crypto/signature'); | |
var TransactionSignature = require('../signature'); | |
/** | |
* Represents a special kind of input of PayToPublicKeyHash kind. | |
* @constructor | |
*/ | |
function PublicKeyHashInput() { | |
Input.apply(this, arguments); | |
} | |
inherits(PublicKeyHashInput, Input); | |
/* jshint maxparams: 5 */ | |
/** | |
* @param {Transaction} transaction - the transaction to be signed | |
* @param {PrivateKey} privateKey - the private key with which to sign the transaction | |
* @param {number} index - the index of the input in the transaction input vector | |
* @param {number=} sigtype - the type of signature, defaults to Signature.SIGHASH_ALL | |
* @param {Buffer=} hashData - the precalculated hash of the public key associated with the privateKey provided | |
* @return {Array} of objects that can be | |
*/ | |
PublicKeyHashInput.prototype.getSignatures = function (transaction, privateKey, index, sigtype, hashData) { | |
$.checkState(this.output instanceof Output); | |
hashData = hashData || Hash.sha256ripemd160(privateKey.publicKey.toBuffer()); | |
sigtype = sigtype || Signature.SIGHASH_ALL; | |
if (BufferUtil.equals(hashData, this.output.script.getPublicKeyHash())) { | |
return [new TransactionSignature({ | |
publicKey: privateKey.publicKey, | |
prevTxId: this.prevTxId, | |
outputIndex: this.outputIndex, | |
inputIndex: index, | |
signature: Sighash.sign(transaction, privateKey, sigtype, index, this.output.script), | |
sigtype: sigtype | |
})]; | |
} | |
return []; | |
}; | |
/* jshint maxparams: 3 */ | |
/** | |
* Add the provided signature | |
* | |
* @param {Object} signature | |
* @param {PublicKey} signature.publicKey | |
* @param {Signature} signature.signature | |
* @param {number=} signature.sigtype | |
* @return {PublicKeyHashInput} this, for chaining | |
*/ | |
PublicKeyHashInput.prototype.addSignature = function (transaction, signature) { | |
$.checkState(this.isValidSignature(transaction, signature), 'Signature is invalid'); | |
this.setScript(Script.buildPublicKeyHashIn(signature.publicKey, signature.signature.toDER(), signature.sigtype)); | |
return this; | |
}; | |
/** | |
* Clear the input's signature | |
* @return {PublicKeyHashInput} this, for chaining | |
*/ | |
PublicKeyHashInput.prototype.clearSignatures = function () { | |
this.setScript(Script.empty()); | |
return this; | |
}; | |
/** | |
* Query whether the input is signed | |
* @return {boolean} | |
*/ | |
PublicKeyHashInput.prototype.isFullySigned = function () { | |
return this.script.isPublicKeyHashIn(); | |
}; | |
PublicKeyHashInput.SCRIPT_MAX_SIZE = 73 + 34; // sigsize (1 + 72) + pubkey (1 + 33) | |
PublicKeyHashInput.prototype._estimateSize = function () { | |
return PublicKeyHashInput.SCRIPT_MAX_SIZE; | |
}; | |
module.exports = PublicKeyHashInput; | |
},{"../../crypto/hash":34,"../../crypto/signature":37,"../../script":51,"../../util/buffer":68,"../../util/preconditions":70,"../output":61,"../sighash":62,"../signature":63,"./input":56,"inherits":256}],61:[function(require,module,exports){ | |
'use strict'; | |
var _ = require('lodash'); | |
var BN = require('../crypto/bn'); | |
var buffer = require('buffer'); | |
var bufferUtil = require('../util/buffer'); | |
var JSUtil = require('../util/js'); | |
var BufferWriter = require('../encoding/bufferwriter'); | |
var Script = require('../script'); | |
var $ = require('../util/preconditions'); | |
var errors = require('../errors'); | |
var MAX_SAFE_INTEGER = 0x1fffffffffffff; | |
function Output(args) { | |
if (!(this instanceof Output)) { | |
return new Output(args); | |
} | |
if (_.isObject(args)) { | |
this.satoshis = args.satoshis; | |
if (bufferUtil.isBuffer(args.script)) { | |
this._scriptBuffer = args.script; | |
} else { | |
var script; | |
if (_.isString(args.script) && JSUtil.isHexa(args.script)) { | |
script = new buffer.Buffer(args.script, 'hex'); | |
} else { | |
script = args.script; | |
} | |
this.setScript(script); | |
} | |
} else { | |
throw new TypeError('Unrecognized argument for Output'); | |
} | |
} | |
Object.defineProperty(Output.prototype, 'script', { | |
configurable: false, | |
enumerable: true, | |
get: function get() { | |
if (this._script) { | |
return this._script; | |
} else { | |
this.setScriptFromBuffer(this._scriptBuffer); | |
return this._script; | |
} | |
} | |
}); | |
Object.defineProperty(Output.prototype, 'satoshis', { | |
configurable: false, | |
enumerable: true, | |
get: function get() { | |
return this._satoshis; | |
}, | |
set: function set(num) { | |
if (num instanceof BN) { | |
this._satoshisBN = num; | |
this._satoshis = num.toNumber(); | |
} else if (_.isString(num)) { | |
this._satoshis = parseInt(num); | |
this._satoshisBN = BN.fromNumber(this._satoshis); | |
} else { | |
$.checkArgument(JSUtil.isNaturalNumber(num), 'Output satoshis is not a natural number'); | |
this._satoshisBN = BN.fromNumber(num); | |
this._satoshis = num; | |
} | |
$.checkState(JSUtil.isNaturalNumber(this._satoshis), 'Output satoshis is not a natural number'); | |
} | |
}); | |
Output.prototype.invalidSatoshis = function () { | |
if (this._satoshis > MAX_SAFE_INTEGER) { | |
return 'transaction txout satoshis greater than max safe integer'; | |
} | |
if (this._satoshis !== this._satoshisBN.toNumber()) { | |
return 'transaction txout satoshis has corrupted value'; | |
} | |
if (this._satoshis < 0) { | |
return 'transaction txout negative'; | |
} | |
return false; | |
}; | |
Output.prototype.toObject = Output.prototype.toJSON = function toObject() { | |
var obj = { | |
satoshis: this.satoshis | |
}; | |
obj.script = this._scriptBuffer.toString('hex'); | |
return obj; | |
}; | |
Output.fromObject = function (data) { | |
return new Output(data); | |
}; | |
Output.prototype.setScriptFromBuffer = function (buffer) { | |
this._scriptBuffer = buffer; | |
try { | |
this._script = Script.fromBuffer(this._scriptBuffer); | |
this._script._isOutput = true; | |
} catch (e) { | |
if (e instanceof errors.Script.InvalidBuffer) { | |
this._script = null; | |
} else { | |
throw e; | |
} | |
} | |
}; | |
Output.prototype.setScript = function (script) { | |
if (script instanceof Script) { | |
this._scriptBuffer = script.toBuffer(); | |
this._script = script; | |
this._script._isOutput = true; | |
} else if (_.isString(script)) { | |
this._script = Script.fromString(script); | |
this._scriptBuffer = this._script.toBuffer(); | |
this._script._isOutput = true; | |
} else if (bufferUtil.isBuffer(script)) { | |
this.setScriptFromBuffer(script); | |
} else { | |
throw new TypeError('Invalid argument type: script'); | |
} | |
return this; | |
}; | |
Output.prototype.inspect = function () { | |
var scriptStr; | |
if (this.script) { | |
scriptStr = this.script.inspect(); | |
} else { | |
scriptStr = this._scriptBuffer.toString('hex'); | |
} | |
return '<Output (' + this.satoshis + ' sats) ' + scriptStr + '>'; | |
}; | |
Output.fromBufferReader = function (br) { | |
var obj = {}; | |
obj.satoshis = br.readUInt64LEBN(); | |
var size = br.readVarintNum(); | |
if (size !== 0) { | |
obj.script = br.read(size); | |
} else { | |
obj.script = new buffer.Buffer([]); | |
} | |
return new Output(obj); | |
}; | |
Output.prototype.toBufferWriter = function (writer) { | |
if (!writer) { | |
writer = new BufferWriter(); | |
} | |
writer.writeUInt64LEBN(this._satoshisBN); | |
var script = this._scriptBuffer; | |
writer.writeVarintNum(script.length); | |
writer.write(script); | |
return writer; | |
}; | |
module.exports = Output; | |
},{"../crypto/bn":32,"../encoding/bufferwriter":41,"../errors":43,"../script":51,"../util/buffer":68,"../util/js":69,"../util/preconditions":70,"buffer":148,"lodash":267}],62:[function(require,module,exports){ | |
(function (Buffer){ | |
'use strict'; | |
var buffer = require('buffer'); | |
var Signature = require('../crypto/signature'); | |
var Script = require('../script'); | |
var Output = require('./output'); | |
var BufferReader = require('../encoding/bufferreader'); | |
var BufferWriter = require('../encoding/bufferwriter'); | |
var BN = require('../crypto/bn'); | |
var Hash = require('../crypto/hash'); | |
var ECDSA = require('../crypto/ecdsa'); | |
var $ = require('../util/preconditions'); | |
var _ = require('lodash'); | |
var SIGHASH_SINGLE_BUG = '0000000000000000000000000000000000000000000000000000000000000001'; | |
var BITS_64_ON = 'ffffffffffffffff'; | |
/** | |
* Returns a buffer of length 32 bytes with the hash that needs to be signed | |
* for OP_CHECKSIG. | |
* | |
* @name Signing.sighash | |
* @param {Transaction} transaction the transaction to sign | |
* @param {number} sighashType the type of the hash | |
* @param {number} inputNumber the input index for the signature | |
* @param {Script} subscript the script that will be signed | |
*/ | |
var sighash = function sighash(transaction, sighashType, inputNumber, subscript) { | |
var Transaction = require('./transaction'); | |
var Input = require('./input'); | |
var i; | |
// Copy transaction | |
var txcopy = Transaction.shallowCopy(transaction); | |
// Copy script | |
subscript = new Script(subscript); | |
subscript.removeCodeseparators(); | |
for (i = 0; i < txcopy.inputs.length; i++) { | |
// Blank signatures for other inputs | |
txcopy.inputs[i] = new Input(txcopy.inputs[i]).setScript(Script.empty()); | |
} | |
txcopy.inputs[inputNumber] = new Input(txcopy.inputs[inputNumber]).setScript(subscript); | |
if ((sighashType & 31) === Signature.SIGHASH_NONE || (sighashType & 31) === Signature.SIGHASH_SINGLE) { | |
// clear all sequenceNumbers | |
for (i = 0; i < txcopy.inputs.length; i++) { | |
if (i !== inputNumber) { | |
txcopy.inputs[i].sequenceNumber = 0; | |
} | |
} | |
} | |
if ((sighashType & 31) === Signature.SIGHASH_NONE) { | |
txcopy.outputs = []; | |
} else if ((sighashType & 31) === Signature.SIGHASH_SINGLE) { | |
// The SIGHASH_SINGLE bug. | |
// https://bitcointalk.org/index.php?topic=260595.0 | |
if (inputNumber >= txcopy.outputs.length) { | |
return new Buffer(SIGHASH_SINGLE_BUG, 'hex'); | |
} | |
txcopy.outputs.length = inputNumber + 1; | |
for (i = 0; i < inputNumber; i++) { | |
txcopy.outputs[i] = new Output({ | |
satoshis: BN.fromBuffer(new buffer.Buffer(BITS_64_ON, 'hex')), | |
script: Script.empty() | |
}); | |
} | |
} | |
if (sighashType & Signature.SIGHASH_ANYONECANPAY) { | |
txcopy.inputs = [txcopy.inputs[inputNumber]]; | |
} | |
var buf = new BufferWriter().write(txcopy.toBuffer()).writeInt32LE(sighashType).toBuffer(); | |
var ret = Hash.sha256sha256(buf); | |
ret = new BufferReader(ret).readReverse(); | |
return ret; | |
}; | |
/** | |
* Create a signature | |
* | |
* @name Signing.sign | |
* @param {Transaction} transaction | |
* @param {PrivateKey} privateKey | |
* @param {number} sighash | |
* @param {number} inputIndex | |
* @param {Script} subscript | |
* @return {Signature} | |
*/ | |
function sign(transaction, privateKey, sighashType, inputIndex, subscript) { | |
var hashbuf = sighash(transaction, sighashType, inputIndex, subscript); | |
var sig = ECDSA.sign(hashbuf, privateKey, 'little').set({ | |
nhashtype: sighashType | |
}); | |
return sig; | |
} | |
/** | |
* Verify a signature | |
* | |
* @name Signing.verify | |
* @param {Transaction} transaction | |
* @param {Signature} signature | |
* @param {PublicKey} publicKey | |
* @param {number} inputIndex | |
* @param {Script} subscript | |
* @return {boolean} | |
*/ | |
function verify(transaction, signature, publicKey, inputIndex, subscript) { | |
$.checkArgument(!_.isUndefined(transaction)); | |
$.checkArgument(!_.isUndefined(signature) && !_.isUndefined(signature.nhashtype)); | |
var hashbuf = sighash(transaction, signature.nhashtype, inputIndex, subscript); | |
return ECDSA.verify(hashbuf, signature, publicKey, 'little'); | |
} | |
/** | |
* @namespace Signing | |
*/ | |
module.exports = { | |
sighash: sighash, | |
sign: sign, | |
verify: verify | |
}; | |
}).call(this,require("buffer").Buffer) | |
},{"../crypto/bn":32,"../crypto/ecdsa":33,"../crypto/hash":34,"../crypto/signature":37,"../encoding/bufferreader":40,"../encoding/bufferwriter":41,"../script":51,"../util/preconditions":70,"./input":55,"./output":61,"./transaction":64,"buffer":148,"lodash":267}],63:[function(require,module,exports){ | |
(function (Buffer){ | |
'use strict'; | |
var _ = require('lodash'); | |
var $ = require('../util/preconditions'); | |
var inherits = require('inherits'); | |
var BufferUtil = require('../util/buffer'); | |
var JSUtil = require('../util/js'); | |
var PublicKey = require('../publickey'); | |
var errors = require('../errors'); | |
var Signature = require('../crypto/signature'); | |
/** | |
* @desc | |
* Wrapper around Signature with fields related to signing a transaction specifically | |
* | |
* @param {Object|string|TransactionSignature} arg | |
* @constructor | |
*/ | |
function TransactionSignature(arg) { | |
if (!(this instanceof TransactionSignature)) { | |
return new TransactionSignature(arg); | |
} | |
if (arg instanceof TransactionSignature) { | |
return arg; | |
} | |
if (_.isObject(arg)) { | |
return this._fromObject(arg); | |
} | |
throw new errors.InvalidArgument('TransactionSignatures must be instantiated from an object'); | |
} | |
inherits(TransactionSignature, Signature); | |
TransactionSignature.prototype._fromObject = function (arg) { | |
this._checkObjectArgs(arg); | |
this.publicKey = new PublicKey(arg.publicKey); | |
this.prevTxId = BufferUtil.isBuffer(arg.prevTxId) ? arg.prevTxId : new Buffer(arg.prevTxId, 'hex'); | |
this.outputIndex = arg.outputIndex; | |
this.inputIndex = arg.inputIndex; | |
this.signature = arg.signature instanceof Signature ? arg.signature : BufferUtil.isBuffer(arg.signature) ? Signature.fromBuffer(arg.signature) : Signature.fromString(arg.signature); | |
this.sigtype = arg.sigtype; | |
return this; | |
}; | |
TransactionSignature.prototype._checkObjectArgs = function (arg) { | |
$.checkArgument(PublicKey(arg.publicKey), 'publicKey'); | |
$.checkArgument(!_.isUndefined(arg.inputIndex), 'inputIndex'); | |
$.checkArgument(!_.isUndefined(arg.outputIndex), 'outputIndex'); | |
$.checkState(_.isNumber(arg.inputIndex), 'inputIndex must be a number'); | |
$.checkState(_.isNumber(arg.outputIndex), 'outputIndex must be a number'); | |
$.checkArgument(arg.signature, 'signature'); | |
$.checkArgument(arg.prevTxId, 'prevTxId'); | |
$.checkState(arg.signature instanceof Signature || BufferUtil.isBuffer(arg.signature) || JSUtil.isHexa(arg.signature), 'signature must be a buffer or hexa value'); | |
$.checkState(BufferUtil.isBuffer(arg.prevTxId) || JSUtil.isHexa(arg.prevTxId), 'prevTxId must be a buffer or hexa value'); | |
$.checkArgument(arg.sigtype, 'sigtype'); | |
$.checkState(_.isNumber(arg.sigtype), 'sigtype must be a number'); | |
}; | |
/** | |
* Serializes a transaction to a plain JS object | |
* @return {Object} | |
*/ | |
TransactionSignature.prototype.toObject = TransactionSignature.prototype.toJSON = function toObject() { | |
return { | |
publicKey: this.publicKey.toString(), | |
prevTxId: this.prevTxId.toString('hex'), | |
outputIndex: this.outputIndex, | |
inputIndex: this.inputIndex, | |
signature: this.signature.toString(), | |
sigtype: this.sigtype | |
}; | |
}; | |
/** | |
* Builds a TransactionSignature from an object | |
* @param {Object} object | |
* @return {TransactionSignature} | |
*/ | |
TransactionSignature.fromObject = function (object) { | |
$.checkArgument(object); | |
return new TransactionSignature(object); | |
}; | |
module.exports = TransactionSignature; | |
}).call(this,require("buffer").Buffer) | |
},{"../crypto/signature":37,"../errors":43,"../publickey":50,"../util/buffer":68,"../util/js":69,"../util/preconditions":70,"buffer":148,"inherits":256,"lodash":267}],64:[function(require,module,exports){ | |
(function (Buffer){ | |
'use strict'; | |
var _ = require('lodash'); | |
var $ = require('../util/preconditions'); | |
var buffer = require('buffer'); | |
var compare = Buffer.compare || require('buffer-compare'); | |
var errors = require('../errors'); | |
var BufferUtil = require('../util/buffer'); | |
var JSUtil = require('../util/js'); | |
var BufferReader = require('../encoding/bufferreader'); | |
var BufferWriter = require('../encoding/bufferwriter'); | |
var Hash = require('../crypto/hash'); | |
var Signature = require('../crypto/signature'); | |
var Sighash = require('./sighash'); | |
var Address = require('../address'); | |
var UnspentOutput = require('./unspentoutput'); | |
var Input = require('./input'); | |
var PublicKeyHashInput = Input.PublicKeyHash; | |
var PublicKeyInput = Input.PublicKey; | |
var MultiSigScriptHashInput = Input.MultiSigScriptHash; | |
var MultiSigInput = Input.MultiSig; | |
var Output = require('./output'); | |
var Script = require('../script'); | |
var PrivateKey = require('../privatekey'); | |
var BN = require('../crypto/bn'); | |
/** | |
* Represents a transaction, a set of inputs and outputs to change ownership of tokens | |
* | |
* @param {*} serialized | |
* @constructor | |
*/ | |
function Transaction(serialized) { | |
if (!(this instanceof Transaction)) { | |
return new Transaction(serialized); | |
} | |
this.inputs = []; | |
this.outputs = []; | |
this._inputAmount = undefined; | |
this._outputAmount = undefined; | |
if (serialized) { | |
if (serialized instanceof Transaction) { | |
return Transaction.shallowCopy(serialized); | |
} else if (JSUtil.isHexa(serialized)) { | |
this.fromString(serialized); | |
} else if (BufferUtil.isBuffer(serialized)) { | |
this.fromBuffer(serialized); | |
} else if (_.isObject(serialized)) { | |
this.fromObject(serialized); | |
} else { | |
throw new errors.InvalidArgument('Must provide an object or string to deserialize a transaction'); | |
} | |
} else { | |
this._newTransaction(); | |
} | |
} | |
var CURRENT_VERSION = 1; | |
var DEFAULT_NLOCKTIME = 0; | |
var MAX_BLOCK_SIZE = 1000000; | |
// Minimum amount for an output for it not to be considered a dust output | |
Transaction.DUST_AMOUNT = 546; | |
// Margin of error to allow fees in the vecinity of the expected value but doesn't allow a big difference | |
Transaction.FEE_SECURITY_MARGIN = 150; | |
// max amount of satoshis in circulation | |
Transaction.MAX_MONEY = 21000000 * 1e8; | |
// nlocktime limit to be considered block height rather than a timestamp | |
Transaction.NLOCKTIME_BLOCKHEIGHT_LIMIT = 5e8; | |
// Max value for an unsigned 32 bit value | |
Transaction.NLOCKTIME_MAX_VALUE = 4294967295; | |
// Value used for fee estimation (satoshis per kilobyte) | |
Transaction.FEE_PER_KB = 100000; | |
// Safe upper bound for change address script size in bytes | |
Transaction.CHANGE_OUTPUT_MAX_SIZE = 20 + 4 + 34 + 4; | |
Transaction.MAXIMUM_EXTRA_SIZE = 4 + 9 + 9 + 4; | |
/* Constructors and Serialization */ | |
/** | |
* Create a 'shallow' copy of the transaction, by serializing and deserializing | |
* it dropping any additional information that inputs and outputs may have hold | |
* | |
* @param {Transaction} transaction | |
* @return {Transaction} | |
*/ | |
Transaction.shallowCopy = function (transaction) { | |
var copy = new Transaction(transaction.toBuffer()); | |
return copy; | |
}; | |
var hashProperty = { | |
configurable: false, | |
enumerable: true, | |
get: function get() { | |
return new BufferReader(this._getHash()).readReverse().toString('hex'); | |
} | |
}; | |
Object.defineProperty(Transaction.prototype, 'hash', hashProperty); | |
Object.defineProperty(Transaction.prototype, 'id', hashProperty); | |
var ioProperty = { | |
configurable: false, | |
enumerable: true, | |
get: function get() { | |
return this._getInputAmount(); | |
} | |
}; | |
Object.defineProperty(Transaction.prototype, 'inputAmount', ioProperty); | |
ioProperty.get = function () { | |
return this._getOutputAmount(); | |
}; | |
Object.defineProperty(Transaction.prototype, 'outputAmount', ioProperty); | |
/** | |
* Retrieve the little endian hash of the transaction (used for serialization) | |
* @return {Buffer} | |
*/ | |
Transaction.prototype._getHash = function () { | |
return Hash.sha256sha256(this.toBuffer()); | |
}; | |
/** | |
* Retrieve a hexa string that can be used with bitcoind's CLI interface | |
* (decoderawtransaction, sendrawtransaction) | |
* | |
* @param {Object|boolean=} unsafe if true, skip all tests. if it's an object, | |
* it's expected to contain a set of flags to skip certain tests: | |
* * `disableAll`: disable all checks | |
* * `disableSmallFees`: disable checking for fees that are too small | |
* * `disableLargeFees`: disable checking for fees that are too large | |
* * `disableIsFullySigned`: disable checking if all inputs are fully signed | |
* * `disableDustOutputs`: disable checking if there are no outputs that are dust amounts | |
* * `disableMoreOutputThanInput`: disable checking if the transaction spends more bitcoins than the sum of the input amounts | |
* @return {string} | |
*/ | |
Transaction.prototype.serialize = function (unsafe) { | |
if (true === unsafe || unsafe && unsafe.disableAll) { | |
return this.uncheckedSerialize(); | |
} else { | |
return this.checkedSerialize(unsafe); | |
} | |
}; | |
Transaction.prototype.uncheckedSerialize = Transaction.prototype.toString = function () { | |
return this.toBuffer().toString('hex'); | |
}; | |
/** | |
* Retrieve a hexa string that can be used with bitcoind's CLI interface | |
* (decoderawtransaction, sendrawtransaction) | |
* | |
* @param {Object} opts allows to skip certain tests. {@see Transaction#serialize} | |
* @return {string} | |
*/ | |
Transaction.prototype.checkedSerialize = function (opts) { | |
var serializationError = this.getSerializationError(opts); | |
if (serializationError) { | |
serializationError.message += ' - For more information please see: ' + 'https://bitcore.io/api/lib/transaction#serialization-checks'; | |
throw serializationError; | |
} | |
return this.uncheckedSerialize(); | |
}; | |
Transaction.prototype.invalidSatoshis = function () { | |
var invalid = false; | |
for (var i = 0; i < this.outputs.length; i++) { | |
if (this.outputs[i].invalidSatoshis()) { | |
invalid = true; | |
} | |
} | |
return invalid; | |
}; | |
/** | |
* Retrieve a possible error that could appear when trying to serialize and | |
* broadcast this transaction. | |
* | |
* @param {Object} opts allows to skip certain tests. {@see Transaction#serialize} | |
* @return {bitcore.Error} | |
*/ | |
Transaction.prototype.getSerializationError = function (opts) { | |
opts = opts || {}; | |
if (this.invalidSatoshis()) { | |
return new errors.Transaction.InvalidSatoshis(); | |
} | |
var unspent = this._getUnspentValue(); | |
var unspentError; | |
if (unspent < 0) { | |
if (!opts.disableMoreOutputThanInput) { | |
unspentError = new errors.Transaction.InvalidOutputAmountSum(); | |
} | |
} else { | |
unspentError = this._hasFeeError(opts, unspent); | |
} | |
return unspentError || this._hasDustOutputs(opts) || this._isMissingSignatures(opts); | |
}; | |
Transaction.prototype._hasFeeError = function (opts, unspent) { | |
if (!_.isUndefined(this._fee) && this._fee !== unspent) { | |
return new errors.Transaction.FeeError.Different('Unspent value is ' + unspent + ' but specified fee is ' + this._fee); | |
} | |
if (!opts.disableLargeFees) { | |
var maximumFee = Math.floor(Transaction.FEE_SECURITY_MARGIN * this._estimateFee()); | |
if (unspent > maximumFee) { | |
if (this._missingChange()) { | |
return new errors.Transaction.ChangeAddressMissing('Fee is too large and no change address was provided'); | |
} | |
return new errors.Transaction.FeeError.TooLarge('expected less than ' + maximumFee + ' but got ' + unspent); | |
} | |
} | |
if (!opts.disableSmallFees) { | |
var minimumFee = Math.ceil(this._estimateFee() / Transaction.FEE_SECURITY_MARGIN); | |
if (unspent < minimumFee) { | |
return new errors.Transaction.FeeError.TooSmall('expected more than ' + minimumFee + ' but got ' + unspent); | |
} | |
} | |
}; | |
Transaction.prototype._missingChange = function () { | |
return !this._changeScript; | |
}; | |
Transaction.prototype._hasDustOutputs = function (opts) { | |
if (opts.disableDustOutputs) { | |
return; | |
} | |
var index, output; | |
for (index in this.outputs) { | |
output = this.outputs[index]; | |
if (output.satoshis < Transaction.DUST_AMOUNT && !output.script.isDataOut()) { | |
return new errors.Transaction.DustOutputs(); | |
} | |
} | |
}; | |
Transaction.prototype._isMissingSignatures = function (opts) { | |
if (opts.disableIsFullySigned) { | |
return; | |
} | |
if (!this.isFullySigned()) { | |
return new errors.Transaction.MissingSignatures(); | |
} | |
}; | |
Transaction.prototype.inspect = function () { | |
return '<Transaction: ' + this.uncheckedSerialize() + '>'; | |
}; | |
Transaction.prototype.toBuffer = function () { | |
var writer = new BufferWriter(); | |
return this.toBufferWriter(writer).toBuffer(); | |
}; | |
Transaction.prototype.toBufferWriter = function (writer) { | |
writer.writeInt32LE(this.version); | |
writer.writeVarintNum(this.inputs.length); | |
_.each(this.inputs, function (input) { | |
input.toBufferWriter(writer); | |
}); | |
writer.writeVarintNum(this.outputs.length); | |
_.each(this.outputs, function (output) { | |
output.toBufferWriter(writer); | |
}); | |
writer.writeUInt32LE(this.nLockTime); | |
return writer; | |
}; | |
Transaction.prototype.fromBuffer = function (buffer) { | |
var reader = new BufferReader(buffer); | |
return this.fromBufferReader(reader); | |
}; | |
Transaction.prototype.fromBufferReader = function (reader) { | |
$.checkArgument(!reader.finished(), 'No transaction data received'); | |
var i, sizeTxIns, sizeTxOuts; | |
this.version = reader.readInt32LE(); | |
sizeTxIns = reader.readVarintNum(); | |
for (i = 0; i < sizeTxIns; i++) { | |
var input = Input.fromBufferReader(reader); | |
this.inputs.push(input); | |
} | |
sizeTxOuts = reader.readVarintNum(); | |
for (i = 0; i < sizeTxOuts; i++) { | |
this.outputs.push(Output.fromBufferReader(reader)); | |
} | |
this.nLockTime = reader.readUInt32LE(); | |
return this; | |
}; | |
Transaction.prototype.toObject = Transaction.prototype.toJSON = function toObject() { | |
var inputs = []; | |
this.inputs.forEach(function (input) { | |
inputs.push(input.toObject()); | |
}); | |
var outputs = []; | |
this.outputs.forEach(function (output) { | |
outputs.push(output.toObject()); | |
}); | |
var obj = { | |
hash: this.hash, | |
version: this.version, | |
inputs: inputs, | |
outputs: outputs, | |
nLockTime: this.nLockTime | |
}; | |
if (this._changeScript) { | |
obj.changeScript = this._changeScript.toString(); | |
} | |
if (!_.isUndefined(this._changeIndex)) { | |
obj.changeIndex = this._changeIndex; | |
} | |
if (!_.isUndefined(this._fee)) { | |
obj.fee = this._fee; | |
} | |
return obj; | |
}; | |
Transaction.prototype.fromObject = function fromObject(arg) { | |
/* jshint maxstatements: 20 */ | |
$.checkArgument(_.isObject(arg) || arg instanceof Transaction); | |
var self = this; | |
var transaction; | |
if (arg instanceof Transaction) { | |
transaction = transaction.toObject(); | |
} else { | |
transaction = arg; | |
} | |
_.each(transaction.inputs, function (input) { | |
if (!input.output || !input.output.script) { | |
self.uncheckedAddInput(new Input(input)); | |
return; | |
} | |
var script = new Script(input.output.script); | |
var txin; | |
if (script.isPublicKeyHashOut()) { | |
txin = new Input.PublicKeyHash(input); | |
} else if (script.isScriptHashOut() && input.publicKeys && input.threshold) { | |
txin = new Input.MultiSigScriptHash(input, input.publicKeys, input.threshold, input.signatures); | |
} else if (script.isPublicKeyOut()) { | |
txin = new Input.PublicKey(input); | |
} else { | |
throw new errors.Transaction.Input.UnsupportedScript(input.output.script); | |
} | |
self.addInput(txin); | |
}); | |
_.each(transaction.outputs, function (output) { | |
self.addOutput(new Output(output)); | |
}); | |
if (transaction.changeIndex) { | |
this._changeIndex = transaction.changeIndex; | |
} | |
if (transaction.changeScript) { | |
this._changeScript = new Script(transaction.changeScript); | |
} | |
if (transaction.fee) { | |
this._fee = transaction.fee; | |
} | |
this.nLockTime = transaction.nLockTime; | |
this.version = transaction.version; | |
this._checkConsistency(arg); | |
return this; | |
}; | |
Transaction.prototype._checkConsistency = function (arg) { | |
if (!_.isUndefined(this._changeIndex)) { | |
$.checkState(this._changeScript, 'Change script is expected.'); | |
$.checkState(this.outputs[this._changeIndex], 'Change index points to undefined output.'); | |
$.checkState(this.outputs[this._changeIndex].script.toString() === this._changeScript.toString(), 'Change output has an unexpected script.'); | |
} | |
if (arg && arg.hash) { | |
$.checkState(arg.hash === this.hash, 'Hash in object does not match transaction hash.'); | |
} | |
}; | |
/** | |
* Sets nLockTime so that transaction is not valid until the desired date(a | |
* timestamp in seconds since UNIX epoch is also accepted) | |
* | |
* @param {Date | Number} time | |
* @return {Transaction} this | |
*/ | |
Transaction.prototype.lockUntilDate = function (time) { | |
$.checkArgument(time); | |
if (_.isNumber(time) && time < Transaction.NLOCKTIME_BLOCKHEIGHT_LIMIT) { | |
throw new errors.Transaction.LockTimeTooEarly(); | |
} | |
if (_.isDate(time)) { | |
time = time.getTime() / 1000; | |
} | |
for (var i = 0; i < this.inputs.length; i++) { | |
if (this.inputs[i].sequenceNumber === Input.DEFAULT_SEQNUMBER) { | |
this.inputs[i].sequenceNumber = Input.DEFAULT_LOCKTIME_SEQNUMBER; | |
} | |
} | |
this.nLockTime = time; | |
return this; | |
}; | |
/** | |
* Sets nLockTime so that transaction is not valid until the desired block | |
* height. | |
* | |
* @param {Number} height | |
* @return {Transaction} this | |
*/ | |
Transaction.prototype.lockUntilBlockHeight = function (height) { | |
$.checkArgument(_.isNumber(height)); | |
if (height >= Transaction.NLOCKTIME_BLOCKHEIGHT_LIMIT) { | |
throw new errors.Transaction.BlockHeightTooHigh(); | |
} | |
if (height < 0) { | |
throw new errors.Transaction.NLockTimeOutOfRange(); | |
} | |
for (var i = 0; i < this.inputs.length; i++) { | |
if (this.inputs[i].sequenceNumber === Input.DEFAULT_SEQNUMBER) { | |
this.inputs[i].sequenceNumber = Input.DEFAULT_LOCKTIME_SEQNUMBER; | |
} | |
} | |
this.nLockTime = height; | |
return this; | |
}; | |
/** | |
* Returns a semantic version of the transaction's nLockTime. | |
* @return {Number|Date} | |
* If nLockTime is 0, it returns null, | |
* if it is < 500000000, it returns a block height (number) | |
* else it returns a Date object. | |
*/ | |
Transaction.prototype.getLockTime = function () { | |
if (!this.nLockTime) { | |
return null; | |
} | |
if (this.nLockTime < Transaction.NLOCKTIME_BLOCKHEIGHT_LIMIT) { | |
return this.nLockTime; | |
} | |
return new Date(1000 * this.nLockTime); | |
}; | |
Transaction.prototype.fromString = function (string) { | |
this.fromBuffer(new buffer.Buffer(string, 'hex')); | |
}; | |
Transaction.prototype._newTransaction = function () { | |
this.version = CURRENT_VERSION; | |
this.nLockTime = DEFAULT_NLOCKTIME; | |
}; | |
/* Transaction creation interface */ | |
/** | |
* @typedef {Object} Transaction~fromObject | |
* @property {string} prevTxId | |
* @property {number} outputIndex | |
* @property {(Buffer|string|Script)} script | |
* @property {number} satoshis | |
*/ | |
/** | |
* Add an input to this transaction. This is a high level interface | |
* to add an input, for more control, use @{link Transaction#addInput}. | |
* | |
* Can receive, as output information, the output of bitcoind's `listunspent` command, | |
* and a slightly fancier format recognized by bitcore: | |
* | |
* ``` | |
* { | |
* address: 'mszYqVnqKoQx4jcTdJXxwKAissE3Jbrrc1', | |
* txId: 'a477af6b2667c29670467e4e0728b685ee07b240235771862318e29ddbe58458', | |
* outputIndex: 0, | |
* script: Script.empty(), | |
* satoshis: 1020000 | |
* } | |
* ``` | |
* Where `address` can be either a string or a bitcore Address object. The | |
* same is true for `script`, which can be a string or a bitcore Script. | |
* | |
* Beware that this resets all the signatures for inputs (in further versions, | |
* SIGHASH_SINGLE or SIGHASH_NONE signatures will not be reset). | |
* | |
* @example | |
* ```javascript | |
* var transaction = new Transaction(); | |
* | |
* // From a pay to public key hash output from bitcoind's listunspent | |
* transaction.from({'txid': '0000...', vout: 0, amount: 0.1, scriptPubKey: 'OP_DUP ...'}); | |
* | |
* // From a pay to public key hash output | |
* transaction.from({'txId': '0000...', outputIndex: 0, satoshis: 1000, script: 'OP_DUP ...'}); | |
* | |
* // From a multisig P2SH output | |
* transaction.from({'txId': '0000...', inputIndex: 0, satoshis: 1000, script: '... OP_HASH'}, | |
* ['03000...', '02000...'], 2); | |
* ``` | |
* | |
* @param {(Array.<Transaction~fromObject>|Transaction~fromObject)} utxo | |
* @param {Array=} pubkeys | |
* @param {number=} threshold | |
*/ | |
Transaction.prototype.from = function (utxo, pubkeys, threshold) { | |
if (_.isArray(utxo)) { | |
var self = this; | |
_.each(utxo, function (utxo) { | |
self.from(utxo, pubkeys, threshold); | |
}); | |
return this; | |
} | |
var exists = _.some(this.inputs, function (input) { | |
// TODO: Maybe prevTxId should be a string? Or defined as read only property? | |
return input.prevTxId.toString('hex') === utxo.txId && input.outputIndex === utxo.outputIndex; | |
}); | |
if (exists) { | |
return this; | |
} | |
if (pubkeys && threshold) { | |
this._fromMultisigUtxo(utxo, pubkeys, threshold); | |
} else { | |
this._fromNonP2SH(utxo); | |
} | |
return this; | |
}; | |
Transaction.prototype._fromNonP2SH = function (utxo) { | |
var clazz; | |
utxo = new UnspentOutput(utxo); | |
if (utxo.script.isPublicKeyHashOut()) { | |
clazz = PublicKeyHashInput; | |
} else if (utxo.script.isPublicKeyOut()) { | |
clazz = PublicKeyInput; | |
} else { | |
clazz = Input; | |
} | |
this.addInput(new clazz({ | |
output: new Output({ | |
script: utxo.script, | |
satoshis: utxo.satoshis | |
}), | |
prevTxId: utxo.txId, | |
outputIndex: utxo.outputIndex, | |
script: Script.empty() | |
})); | |
}; | |
Transaction.prototype._fromMultisigUtxo = function (utxo, pubkeys, threshold) { | |
$.checkArgument(threshold <= pubkeys.length, 'Number of required signatures must be greater than the number of public keys'); | |
var clazz; | |
utxo = new UnspentOutput(utxo); | |
if (utxo.script.isMultisigOut()) { | |
clazz = MultiSigInput; | |
} else if (utxo.script.isScriptHashOut()) { | |
clazz = MultiSigScriptHashInput; | |
} else { | |
throw new Error("@TODO"); | |
} | |
this.addInput(new clazz({ | |
output: new Output({ | |
script: utxo.script, | |
satoshis: utxo.satoshis | |
}), | |
prevTxId: utxo.txId, | |
outputIndex: utxo.outputIndex, | |
script: Script.empty() | |
}, pubkeys, threshold)); | |
}; | |
/** | |
* Add an input to this transaction. The input must be an instance of the `Input` class. | |
* It should have information about the Output that it's spending, but if it's not already | |
* set, two additional parameters, `outputScript` and `satoshis` can be provided. | |
* | |
* @param {Input} input | |
* @param {String|Script} outputScript | |
* @param {number} satoshis | |
* @return Transaction this, for chaining | |
*/ | |
Transaction.prototype.addInput = function (input, outputScript, satoshis) { | |
$.checkArgumentType(input, Input, 'input'); | |
if (!input.output && (_.isUndefined(outputScript) || _.isUndefined(satoshis))) { | |
throw new errors.Transaction.NeedMoreInfo('Need information about the UTXO script and satoshis'); | |
} | |
if (!input.output && outputScript && !_.isUndefined(satoshis)) { | |
outputScript = outputScript instanceof Script ? outputScript : new Script(outputScript); | |
$.checkArgumentType(satoshis, 'number', 'satoshis'); | |
input.output = new Output({ | |
script: outputScript, | |
satoshis: satoshis | |
}); | |
} | |
return this.uncheckedAddInput(input); | |
}; | |
/** | |
* Add an input to this transaction, without checking that the input has information about | |
* the output that it's spending. | |
* | |
* @param {Input} input | |
* @return Transaction this, for chaining | |
*/ | |
Transaction.prototype.uncheckedAddInput = function (input) { | |
$.checkArgumentType(input, Input, 'input'); | |
this.inputs.push(input); | |
this._inputAmount = undefined; | |
this._updateChangeOutput(); | |
return this; | |
}; | |
/** | |
* Returns true if the transaction has enough info on all inputs to be correctly validated | |
* | |
* @return {boolean} | |
*/ | |
Transaction.prototype.hasAllUtxoInfo = function () { | |
return _.every(this.inputs.map(function (input) { | |
return !!input.output; | |
})); | |
}; | |
/** | |
* Manually set the fee for this transaction. Beware that this resets all the signatures | |
* for inputs (in further versions, SIGHASH_SINGLE or SIGHASH_NONE signatures will not | |
* be reset). | |
* | |
* @param {number} amount satoshis to be sent | |
* @return {Transaction} this, for chaining | |
*/ | |
Transaction.prototype.fee = function (amount) { | |
$.checkArgument(_.isNumber(amount), 'amount must be a number'); | |
this._fee = amount; | |
this._updateChangeOutput(); | |
return this; | |
}; | |
/** | |
* Manually set the fee per KB for this transaction. Beware that this resets all the signatures | |
* for inputs (in further versions, SIGHASH_SINGLE or SIGHASH_NONE signatures will not | |
* be reset). | |
* | |
* @param {number} amount satoshis per KB to be sent | |
* @return {Transaction} this, for chaining | |
*/ | |
Transaction.prototype.feePerKb = function (amount) { | |
$.checkArgument(_.isNumber(amount), 'amount must be a number'); | |
this._feePerKb = amount; | |
this._updateChangeOutput(); | |
return this; | |
}; | |
/* Output management */ | |
/** | |
* Set the change address for this transaction | |
* | |
* Beware that this resets all the signatures for inputs (in further versions, | |
* SIGHASH_SINGLE or SIGHASH_NONE signatures will not be reset). | |
* | |
* @param {Address} address An address for change to be sent to. | |
* @return {Transaction} this, for chaining | |
*/ | |
Transaction.prototype.change = function (address) { | |
$.checkArgument(address, 'address is required'); | |
this._changeScript = Script.fromAddress(address); | |
this._updateChangeOutput(); | |
return this; | |
}; | |
/** | |
* @return {Output} change output, if it exists | |
*/ | |
Transaction.prototype.getChangeOutput = function () { | |
if (!_.isUndefined(this._changeIndex)) { | |
return this.outputs[this._changeIndex]; | |
} | |
return null; | |
}; | |
/** | |
* @typedef {Object} Transaction~toObject | |
* @property {(string|Address)} address | |
* @property {number} satoshis | |
*/ | |
/** | |
* Add an output to the transaction. | |
* | |
* Beware that this resets all the signatures for inputs (in further versions, | |
* SIGHASH_SINGLE or SIGHASH_NONE signatures will not be reset). | |
* | |
* @param {(string|Address|Array.<Transaction~toObject>)} address | |
* @param {number} amount in satoshis | |
* @return {Transaction} this, for chaining | |
*/ | |
Transaction.prototype.to = function (address, amount) { | |
if (_.isArray(address)) { | |
var self = this; | |
_.each(address, function (to) { | |
self.to(to.address, to.satoshis); | |
}); | |
return this; | |
} | |
$.checkArgument(JSUtil.isNaturalNumber(amount), 'Amount is expected to be a positive integer'); | |
this.addOutput(new Output({ | |
script: Script(new Address(address)), | |
satoshis: amount | |
})); | |
return this; | |
}; | |
/** | |
* Add an OP_RETURN output to the transaction. | |
* | |
* Beware that this resets all the signatures for inputs (in further versions, | |
* SIGHASH_SINGLE or SIGHASH_NONE signatures will not be reset). | |
* | |
* @param {Buffer|string} value the data to be stored in the OP_RETURN output. | |
* In case of a string, the UTF-8 representation will be stored | |
* @return {Transaction} this, for chaining | |
*/ | |
Transaction.prototype.addData = function (value) { | |
this.addOutput(new Output({ | |
script: Script.buildDataOut(value), | |
satoshis: 0 | |
})); | |
return this; | |
}; | |
/** | |
* Add an output to the transaction. | |
* | |
* @param {Output} output the output to add. | |
* @return {Transaction} this, for chaining | |
*/ | |
Transaction.prototype.addOutput = function (output) { | |
$.checkArgumentType(output, Output, 'output'); | |
this._addOutput(output); | |
this._updateChangeOutput(); | |
return this; | |
}; | |
/** | |
* Remove all outputs from the transaction. | |
* | |
* @return {Transaction} this, for chaining | |
*/ | |
Transaction.prototype.clearOutputs = function () { | |
this.outputs = []; | |
this._clearSignatures(); | |
this._outputAmount = undefined; | |
this._changeIndex = undefined; | |
this._updateChangeOutput(); | |
return this; | |
}; | |
Transaction.prototype._addOutput = function (output) { | |
this.outputs.push(output); | |
this._outputAmount = undefined; | |
}; | |
/** | |
* Calculates or gets the total output amount in satoshis | |
* | |
* @return {Number} the transaction total output amount | |
*/ | |
Transaction.prototype._getOutputAmount = function () { | |
if (_.isUndefined(this._outputAmount)) { | |
var self = this; | |
this._outputAmount = 0; | |
_.each(this.outputs, function (output) { | |
self._outputAmount += output.satoshis; | |
}); | |
} | |
return this._outputAmount; | |
}; | |
/** | |
* Calculates or gets the total input amount in satoshis | |
* | |
* @return {Number} the transaction total input amount | |
*/ | |
Transaction.prototype._getInputAmount = function () { | |
if (_.isUndefined(this._inputAmount)) { | |
var self = this; | |
this._inputAmount = 0; | |
_.each(this.inputs, function (input) { | |
if (_.isUndefined(input.output)) { | |
throw new errors.Transaction.Input.MissingPreviousOutput(); | |
} | |
self._inputAmount += input.output.satoshis; | |
}); | |
} | |
return this._inputAmount; | |
}; | |
Transaction.prototype._updateChangeOutput = function () { | |
if (!this._changeScript) { | |
return; | |
} | |
this._clearSignatures(); | |
if (!_.isUndefined(this._changeIndex)) { | |
this._removeOutput(this._changeIndex); | |
} | |
var available = this._getUnspentValue(); | |
var fee = this.getFee(); | |
var changeAmount = available - fee; | |
if (changeAmount > 0) { | |
this._changeIndex = this.outputs.length; | |
this._addOutput(new Output({ | |
script: this._changeScript, | |
satoshis: changeAmount | |
})); | |
} else { | |
this._changeIndex = undefined; | |
} | |
}; | |
/** | |
* Calculates the fee of the transaction. | |
* | |
* If there's a fixed fee set, return that. | |
* | |
* If there is no change output set, the fee is the | |
* total value of the outputs minus inputs. Note that | |
* a serialized transaction only specifies the value | |
* of its outputs. (The value of inputs are recorded | |
* in the previous transaction outputs being spent.) | |
* This method therefore raises a "MissingPreviousOutput" | |
* error when called on a serialized transaction. | |
* | |
* If there's no fee set and no change address, | |
* estimate the fee based on size. | |
* | |
* @return {Number} fee of this transaction in satoshis | |
*/ | |
Transaction.prototype.getFee = function () { | |
if (this.isCoinbase()) { | |
return 0; | |
} | |
if (!_.isUndefined(this._fee)) { | |
return this._fee; | |
} | |
// if no change output is set, fees should equal all the unspent amount | |
if (!this._changeScript) { | |
return this._getUnspentValue(); | |
} | |
return this._estimateFee(); | |
}; | |
/** | |
* Estimates fee from serialized transaction size in bytes. | |
*/ | |
Transaction.prototype._estimateFee = function () { | |
var estimatedSize = this._estimateSize(); | |
var available = this._getUnspentValue(); | |
return Transaction._estimateFee(estimatedSize, available, this._feePerKb); | |
}; | |
Transaction.prototype._getUnspentValue = function () { | |
return this._getInputAmount() - this._getOutputAmount(); | |
}; | |
Transaction.prototype._clearSignatures = function () { | |
_.each(this.inputs, function (input) { | |
input.clearSignatures(); | |
}); | |
}; | |
Transaction._estimateFee = function (size, amountAvailable, feePerKb) { | |
var fee = Math.ceil(size / 1000) * (feePerKb || Transaction.FEE_PER_KB); | |
if (amountAvailable > fee) { | |
size += Transaction.CHANGE_OUTPUT_MAX_SIZE; | |
} | |
return Math.ceil(size / 1000) * (feePerKb || Transaction.FEE_PER_KB); | |
}; | |
Transaction.prototype._estimateSize = function () { | |
var result = Transaction.MAXIMUM_EXTRA_SIZE; | |
_.each(this.inputs, function (input) { | |
result += input._estimateSize(); | |
}); | |
_.each(this.outputs, function (output) { | |
result += output.script.toBuffer().length + 9; | |
}); | |
return result; | |
}; | |
Transaction.prototype._removeOutput = function (index) { | |
var output = this.outputs[index]; | |
this.outputs = _.without(this.outputs, output); | |
this._outputAmount = undefined; | |
}; | |
Transaction.prototype.removeOutput = function (index) { | |
this._removeOutput(index); | |
this._updateChangeOutput(); | |
}; | |
/** | |
* Sort a transaction's inputs and outputs according to BIP69 | |
* | |
* @see {https://github.com/bitcoin/bips/blob/master/bip-0069.mediawiki} | |
* @return {Transaction} this | |
*/ | |
Transaction.prototype.sort = function () { | |
this.sortInputs(function (inputs) { | |
var copy = Array.prototype.concat.apply([], inputs); | |
copy.sort(function (first, second) { | |
return compare(first.prevTxId, second.prevTxId) || first.outputIndex - second.outputIndex; | |
}); | |
return copy; | |
}); | |
this.sortOutputs(function (outputs) { | |
var copy = Array.prototype.concat.apply([], outputs); | |
copy.sort(function (first, second) { | |
return first.satoshis - second.satoshis || compare(first.script.toBuffer(), second.script.toBuffer()); | |
}); | |
return copy; | |
}); | |
return this; | |
}; | |
/** | |
* Randomize this transaction's outputs ordering. The shuffling algorithm is a | |
* version of the Fisher-Yates shuffle, provided by lodash's _.shuffle(). | |
* | |
* @return {Transaction} this | |
*/ | |
Transaction.prototype.shuffleOutputs = function () { | |
return this.sortOutputs(_.shuffle); | |
}; | |
/** | |
* Sort this transaction's outputs, according to a given sorting function that | |
* takes an array as argument and returns a new array, with the same elements | |
* but with a different order. The argument function MUST NOT modify the order | |
* of the original array | |
* | |
* @param {Function} sortingFunction | |
* @return {Transaction} this | |
*/ | |
Transaction.prototype.sortOutputs = function (sortingFunction) { | |
var outs = sortingFunction(this.outputs); | |
return this._newOutputOrder(outs); | |
}; | |
/** | |
* Sort this transaction's inputs, according to a given sorting function that | |
* takes an array as argument and returns a new array, with the same elements | |
* but with a different order. | |
* | |
* @param {Function} sortingFunction | |
* @return {Transaction} this | |
*/ | |
Transaction.prototype.sortInputs = function (sortingFunction) { | |
this.inputs = sortingFunction(this.inputs); | |
this._clearSignatures(); | |
return this; | |
}; | |
Transaction.prototype._newOutputOrder = function (newOutputs) { | |
var isInvalidSorting = this.outputs.length !== newOutputs.length || _.difference(this.outputs, newOutputs).length !== 0; | |
if (isInvalidSorting) { | |
throw new errors.Transaction.InvalidSorting(); | |
} | |
if (!_.isUndefined(this._changeIndex)) { | |
var changeOutput = this.outputs[this._changeIndex]; | |
this._changeIndex = _.findIndex(newOutputs, changeOutput); | |
} | |
this.outputs = newOutputs; | |
return this; | |
}; | |
Transaction.prototype.removeInput = function (txId, outputIndex) { | |
var index; | |
if (!outputIndex && _.isNumber(txId)) { | |
index = txId; | |
} else { | |
index = _.findIndex(this.inputs, function (input) { | |
return input.prevTxId.toString('hex') === txId && input.outputIndex === outputIndex; | |
}); | |
} | |
if (index < 0 || index >= this.inputs.length) { | |
throw new errors.Transaction.InvalidIndex(index, this.inputs.length); | |
} | |
var input = this.inputs[index]; | |
this.inputs = _.without(this.inputs, input); | |
this._inputAmount = undefined; | |
this._updateChangeOutput(); | |
}; | |
/* Signature handling */ | |
/** | |
* Sign the transaction using one or more private keys. | |
* | |
* It tries to sign each input, verifying that the signature will be valid | |
* (matches a public key). | |
* | |
* @param {Array|String|PrivateKey} privateKey | |
* @param {number} sigtype | |
* @return {Transaction} this, for chaining | |
*/ | |
Transaction.prototype.sign = function (privateKey, sigtype) { | |
$.checkState(this.hasAllUtxoInfo(), 'Not all utxo information is available to sign the transaction.'); | |
var self = this; | |
if (_.isArray(privateKey)) { | |
_.each(privateKey, function (privateKey) { | |
self.sign(privateKey, sigtype); | |
}); | |
return this; | |
} | |
_.each(this.getSignatures(privateKey, sigtype), function (signature) { | |
self.applySignature(signature); | |
}); | |
return this; | |
}; | |
Transaction.prototype.getSignatures = function (privKey, sigtype) { | |
privKey = new PrivateKey(privKey); | |
sigtype = sigtype || Signature.SIGHASH_ALL; | |
var transaction = this; | |
var results = []; | |
var hashData = Hash.sha256ripemd160(privKey.publicKey.toBuffer()); | |
_.each(this.inputs, function forEachInput(input, index) { | |
_.each(input.getSignatures(transaction, privKey, index, sigtype, hashData), function (signature) { | |
results.push(signature); | |
}); | |
}); | |
return results; | |
}; | |
/** | |
* Add a signature to the transaction | |
* | |
* @param {Object} signature | |
* @param {number} signature.inputIndex | |
* @param {number} signature.sigtype | |
* @param {PublicKey} signature.publicKey | |
* @param {Signature} signature.signature | |
* @return {Transaction} this, for chaining | |
*/ | |
Transaction.prototype.applySignature = function (signature) { | |
this.inputs[signature.inputIndex].addSignature(this, signature); | |
return this; | |
}; | |
Transaction.prototype.isFullySigned = function () { | |
_.each(this.inputs, function (input) { | |
if (input.isFullySigned === Input.prototype.isFullySigned) { | |
throw new errors.Transaction.UnableToVerifySignature('Unrecognized script kind, or not enough information to execute script.' + 'This usually happens when creating a transaction from a serialized transaction'); | |
} | |
}); | |
return _.every(_.map(this.inputs, function (input) { | |
return input.isFullySigned(); | |
})); | |
}; | |
Transaction.prototype.isValidSignature = function (signature) { | |
var self = this; | |
if (this.inputs[signature.inputIndex].isValidSignature === Input.prototype.isValidSignature) { | |
throw new errors.Transaction.UnableToVerifySignature('Unrecognized script kind, or not enough information to execute script.' + 'This usually happens when creating a transaction from a serialized transaction'); | |
} | |
return this.inputs[signature.inputIndex].isValidSignature(self, signature); | |
}; | |
/** | |
* @returns {bool} whether the signature is valid for this transaction input | |
*/ | |
Transaction.prototype.verifySignature = function (sig, pubkey, nin, subscript) { | |
return Sighash.verify(this, sig, pubkey, nin, subscript); | |
}; | |
/** | |
* Check that a transaction passes basic sanity tests. If not, return a string | |
* describing the error. This function contains the same logic as | |
* CheckTransaction in bitcoin core. | |
*/ | |
Transaction.prototype.verify = function () { | |
// Basic checks that don't depend on any context | |
if (this.inputs.length === 0) { | |
return 'transaction txins empty'; | |
} | |
if (this.outputs.length === 0) { | |
return 'transaction txouts empty'; | |
} | |
// Check for negative or overflow output values | |
var valueoutbn = new BN(0); | |
for (var i = 0; i < this.outputs.length; i++) { | |
var txout = this.outputs[i]; | |
if (txout.invalidSatoshis()) { | |
return 'transaction txout ' + i + ' satoshis is invalid'; | |
} | |
if (txout._satoshisBN.gt(new BN(Transaction.MAX_MONEY, 10))) { | |
return 'transaction txout ' + i + ' greater than MAX_MONEY'; | |
} | |
valueoutbn = valueoutbn.add(txout._satoshisBN); | |
if (valueoutbn.gt(new BN(Transaction.MAX_MONEY))) { | |
return 'transaction txout ' + i + ' total output greater than MAX_MONEY'; | |
} | |
} | |
// Size limits | |
if (this.toBuffer().length > MAX_BLOCK_SIZE) { | |
return 'transaction over the maximum block size'; | |
} | |
// Check for duplicate inputs | |
var txinmap = {}; | |
for (i = 0; i < this.inputs.length; i++) { | |
var txin = this.inputs[i]; | |
var inputid = txin.prevTxId + ':' + txin.outputIndex; | |
if (!_.isUndefined(txinmap[inputid])) { | |
return 'transaction input ' + i + ' duplicate input'; | |
} | |
txinmap[inputid] = true; | |
} | |
var isCoinbase = this.isCoinbase(); | |
if (isCoinbase) { | |
var buf = this.inputs[0]._scriptBuffer; | |
if (buf.length < 2 || buf.length > 100) { | |
return 'coinbase transaction script size invalid'; | |
} | |
} else { | |
for (i = 0; i < this.inputs.length; i++) { | |
if (this.inputs[i].isNull()) { | |
return 'transaction input ' + i + ' has null input'; | |
} | |
} | |
} | |
return true; | |
}; | |
/** | |
* Analogous to bitcoind's IsCoinBase function in transaction.h | |
*/ | |
Transaction.prototype.isCoinbase = function () { | |
return this.inputs.length === 1 && this.inputs[0].isNull(); | |
}; | |
/** | |
* Determines if this transaction can be replaced in the mempool with another | |
* transaction that provides a sufficiently higher fee (RBF). | |
*/ | |
Transaction.prototype.isRBF = function () { | |
for (var i = 0; i < this.inputs.length; i++) { | |
var input = this.inputs[i]; | |
if (input.sequenceNumber < Input.MAXINT - 1) { | |
return true; | |
} | |
} | |
return false; | |
}; | |
/** | |
* Enable this transaction to be replaced in the mempool (RBF) if a transaction | |
* includes a sufficiently higher fee. It will set the sequenceNumber to | |
* DEFAULT_RBF_SEQNUMBER for all inputs if the sequence number does not | |
* already enable RBF. | |
*/ | |
Transaction.prototype.enableRBF = function () { | |
for (var i = 0; i < this.inputs.length; i++) { | |
var input = this.inputs[i]; | |
if (input.sequenceNumber >= Input.MAXINT - 1) { | |
input.sequenceNumber = Input.DEFAULT_RBF_SEQNUMBER; | |
} | |
} | |
return this; | |
}; | |
module.exports = Transaction; | |
}).call(this,require("buffer").Buffer) | |
},{"../address":27,"../crypto/bn":32,"../crypto/hash":34,"../crypto/signature":37,"../encoding/bufferreader":40,"../encoding/bufferwriter":41,"../errors":43,"../privatekey":49,"../script":51,"../util/buffer":68,"../util/js":69,"../util/preconditions":70,"./input":55,"./output":61,"./sighash":62,"./unspentoutput":65,"buffer":148,"buffer-compare":146,"lodash":267}],65:[function(require,module,exports){ | |
'use strict'; | |
var _ = require('lodash'); | |
var $ = require('../util/preconditions'); | |
var JSUtil = require('../util/js'); | |
var Script = require('../script'); | |
var Address = require('../address'); | |
var Unit = require('../unit'); | |
/** | |
* Represents an unspent output information: its script, associated amount and address, | |
* transaction id and output index. | |
* | |
* @constructor | |
* @param {object} data | |
* @param {string} data.txid the previous transaction id | |
* @param {string=} data.txId alias for `txid` | |
* @param {number} data.vout the index in the transaction | |
* @param {number=} data.outputIndex alias for `vout` | |
* @param {string|Script} data.scriptPubKey the script that must be resolved to release the funds | |
* @param {string|Script=} data.script alias for `scriptPubKey` | |
* @param {number} data.amount amount of bitcoins associated | |
* @param {number=} data.satoshis alias for `amount`, but expressed in satoshis (1 BTC = 1e8 satoshis) | |
* @param {string|Address=} data.address the associated address to the script, if provided | |
*/ | |
function UnspentOutput(data) { | |
/* jshint maxcomplexity: 20 */ | |
/* jshint maxstatements: 20 */ | |
if (!(this instanceof UnspentOutput)) { | |
return new UnspentOutput(data); | |
} | |
$.checkArgument(_.isObject(data), 'Must provide an object from where to extract data'); | |
var address = data.address ? new Address(data.address) : undefined; | |
var txId = data.txid ? data.txid : data.txId; | |
if (!txId || !JSUtil.isHexaString(txId) || txId.length > 64) { | |
// TODO: Use the errors library | |
throw new Error('Invalid TXID in object', data); | |
} | |
var outputIndex = _.isUndefined(data.vout) ? data.outputIndex : data.vout; | |
if (!_.isNumber(outputIndex)) { | |
throw new Error('Invalid outputIndex, received ' + outputIndex); | |
} | |
$.checkArgument(!_.isUndefined(data.scriptPubKey) || !_.isUndefined(data.script), 'Must provide the scriptPubKey for that output!'); | |
var script = new Script(data.scriptPubKey || data.script); | |
$.checkArgument(!_.isUndefined(data.amount) || !_.isUndefined(data.satoshis), 'Must provide an amount for the output'); | |
var amount = !_.isUndefined(data.amount) ? new Unit.fromBTC(data.amount).toSatoshis() : data.satoshis; | |
$.checkArgument(_.isNumber(amount), 'Amount must be a number'); | |
JSUtil.defineImmutable(this, { | |
address: address, | |
txId: txId, | |
outputIndex: outputIndex, | |
script: script, | |
satoshis: amount | |
}); | |
} | |
/** | |
* Provide an informative output when displaying this object in the console | |
* @returns string | |
*/ | |
UnspentOutput.prototype.inspect = function () { | |
return '<UnspentOutput: ' + this.txId + ':' + this.outputIndex + ', satoshis: ' + this.satoshis + ', address: ' + this.address + '>'; | |
}; | |
/** | |
* String representation: just "txid:index" | |
* @returns string | |
*/ | |
UnspentOutput.prototype.toString = function () { | |
return this.txId + ':' + this.outputIndex; | |
}; | |
/** | |
* Deserialize an UnspentOutput from an object | |
* @param {object|string} data | |
* @return UnspentOutput | |
*/ | |
UnspentOutput.fromObject = function (data) { | |
return new UnspentOutput(data); | |
}; | |
/** | |
* Returns a plain object (no prototype or methods) with the associated info for this output | |
* @return {object} | |
*/ | |
UnspentOutput.prototype.toObject = UnspentOutput.prototype.toJSON = function toObject() { | |
return { | |
address: this.address ? this.address.toString() : undefined, | |
txid: this.txId, | |
vout: this.outputIndex, | |
scriptPubKey: this.script.toBuffer().toString('hex'), | |
amount: Unit.fromSatoshis(this.satoshis).toBTC() | |
}; | |
}; | |
module.exports = UnspentOutput; | |
},{"../address":27,"../script":51,"../unit":66,"../util/js":69,"../util/preconditions":70,"lodash":267}],66:[function(require,module,exports){ | |
'use strict'; | |
var _ = require('lodash'); | |
var errors = require('./errors'); | |
var $ = require('./util/preconditions'); | |
var UNITS = { | |
'BTC': [1e8, 8], | |
'mBTC': [1e5, 5], | |
'uBTC': [1e2, 2], | |
'bits': [1e2, 2], | |
'satoshis': [1, 0] | |
}; | |
/** | |
* Utility for handling and converting bitcoins units. The supported units are | |
* BTC, mBTC, bits (also named uBTC) and satoshis. A unit instance can be created with an | |
* amount and a unit code, or alternatively using static methods like {fromBTC}. | |
* It also allows to be created from a fiat amount and the exchange rate, or | |
* alternatively using the {fromFiat} static method. | |
* You can consult for different representation of a unit instance using it's | |
* {to} method, the fixed unit methods like {toSatoshis} or alternatively using | |
* the unit accessors. It also can be converted to a fiat amount by providing the | |
* corresponding BTC/fiat exchange rate. | |
* | |
* @example | |
* ```javascript | |
* var sats = Unit.fromBTC(1.3).toSatoshis(); | |
* var mili = Unit.fromBits(1.3).to(Unit.mBTC); | |
* var bits = Unit.fromFiat(1.3, 350).bits; | |
* var btc = new Unit(1.3, Unit.bits).BTC; | |
* ``` | |
* | |
* @param {Number} amount - The amount to be represented | |
* @param {String|Number} code - The unit of the amount or the exchange rate | |
* @returns {Unit} A new instance of an Unit | |
* @constructor | |
*/ | |
function Unit(amount, code) { | |
if (!(this instanceof Unit)) { | |
return new Unit(amount, code); | |
} | |
// convert fiat to BTC | |
if (_.isNumber(code)) { | |
if (code <= 0) { | |
throw new errors.Unit.InvalidRate(code); | |
} | |
amount = amount / code; | |
code = Unit.BTC; | |
} | |
this._value = this._from(amount, code); | |
var self = this; | |
var defineAccesor = function defineAccesor(key) { | |
Object.defineProperty(self, key, { | |
get: function get() { | |
return self.to(key); | |
}, | |
enumerable: true | |
}); | |
}; | |
Object.keys(UNITS).forEach(defineAccesor); | |
} | |
Object.keys(UNITS).forEach(function (key) { | |
Unit[key] = key; | |
}); | |
/** | |
* Returns a Unit instance created from JSON string or object | |
* | |
* @param {String|Object} json - JSON with keys: amount and code | |
* @returns {Unit} A Unit instance | |
*/ | |
Unit.fromObject = function fromObject(data) { | |
$.checkArgument(_.isObject(data), 'Argument is expected to be an object'); | |
return new Unit(data.amount, data.code); | |
}; | |
/** | |
* Returns a Unit instance created from an amount in BTC | |
* | |
* @param {Number} amount - The amount in BTC | |
* @returns {Unit} A Unit instance | |
*/ | |
Unit.fromBTC = function (amount) { | |
return new Unit(amount, Unit.BTC); | |
}; | |
/** | |
* Returns a Unit instance created from an amount in mBTC | |
* | |
* @param {Number} amount - The amount in mBTC | |
* @returns {Unit} A Unit instance | |
*/ | |
Unit.fromMillis = Unit.fromMilis = function (amount) { | |
return new Unit(amount, Unit.mBTC); | |
}; | |
/** | |
* Returns a Unit instance created from an amount in bits | |
* | |
* @param {Number} amount - The amount in bits | |
* @returns {Unit} A Unit instance | |
*/ | |
Unit.fromMicros = Unit.fromBits = function (amount) { | |
return new Unit(amount, Unit.bits); | |
}; | |
/** | |
* Returns a Unit instance created from an amount in satoshis | |
* | |
* @param {Number} amount - The amount in satoshis | |
* @returns {Unit} A Unit instance | |
*/ | |
Unit.fromSatoshis = function (amount) { | |
return new Unit(amount, Unit.satoshis); | |
}; | |
/** | |
* Returns a Unit instance created from a fiat amount and exchange rate. | |
* | |
* @param {Number} amount - The amount in fiat | |
* @param {Number} rate - The exchange rate BTC/fiat | |
* @returns {Unit} A Unit instance | |
*/ | |
Unit.fromFiat = function (amount, rate) { | |
return new Unit(amount, rate); | |
}; | |
Unit.prototype._from = function (amount, code) { | |
if (!UNITS[code]) { | |
throw new errors.Unit.UnknownCode(code); | |
} | |
return parseInt((amount * UNITS[code][0]).toFixed()); | |
}; | |
/** | |
* Returns the value represented in the specified unit | |
* | |
* @param {String|Number} code - The unit code or exchange rate | |
* @returns {Number} The converted value | |
*/ | |
Unit.prototype.to = function (code) { | |
if (_.isNumber(code)) { | |
if (code <= 0) { | |
throw new errors.Unit.InvalidRate(code); | |
} | |
return parseFloat((this.BTC * code).toFixed(2)); | |
} | |
if (!UNITS[code]) { | |
throw new errors.Unit.UnknownCode(code); | |
} | |
var value = this._value / UNITS[code][0]; | |
return parseFloat(value.toFixed(UNITS[code][1])); | |
}; | |
/** | |
* Returns the value represented in BTC | |
* | |
* @returns {Number} The value converted to BTC | |
*/ | |
Unit.prototype.toBTC = function () { | |
return this.to(Unit.BTC); | |
}; | |
/** | |
* Returns the value represented in mBTC | |
* | |
* @returns {Number} The value converted to mBTC | |
*/ | |
Unit.prototype.toMillis = Unit.prototype.toMilis = function () { | |
return this.to(Unit.mBTC); | |
}; | |
/** | |
* Returns the value represented in bits | |
* | |
* @returns {Number} The value converted to bits | |
*/ | |
Unit.prototype.toMicros = Unit.prototype.toBits = function () { | |
return this.to(Unit.bits); | |
}; | |
/** | |
* Returns the value represented in satoshis | |
* | |
* @returns {Number} The value converted to satoshis | |
*/ | |
Unit.prototype.toSatoshis = function () { | |
return this.to(Unit.satoshis); | |
}; | |
/** | |
* Returns the value represented in fiat | |
* | |
* @param {string} rate - The exchange rate between BTC/currency | |
* @returns {Number} The value converted to satoshis | |
*/ | |
Unit.prototype.atRate = function (rate) { | |
return this.to(rate); | |
}; | |
/** | |
* Returns a the string representation of the value in satoshis | |
* | |
* @returns {string} the value in satoshis | |
*/ | |
Unit.prototype.toString = function () { | |
return this.satoshis + ' satoshis'; | |
}; | |
/** | |
* Returns a plain object representation of the Unit | |
* | |
* @returns {Object} An object with the keys: amount and code | |
*/ | |
Unit.prototype.toObject = Unit.prototype.toJSON = function toObject() { | |
return { | |
amount: this.BTC, | |
code: Unit.BTC | |
}; | |
}; | |
/** | |
* Returns a string formatted for the console | |
* | |
* @returns {string} the value in satoshis | |
*/ | |
Unit.prototype.inspect = function () { | |
return '<Unit: ' + this.toString() + '>'; | |
}; | |
module.exports = Unit; | |
},{"./errors":43,"./util/preconditions":70,"lodash":267}],67:[function(require,module,exports){ | |
'use strict'; | |
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; | |
var _ = require('lodash'); | |
var URL = require('url'); | |
var Address = require('./address'); | |
var Unit = require('./unit'); | |
/** | |
* Bitcore URI | |
* | |
* Instantiate an URI from a bitcoin URI String or an Object. An URI instance | |
* can be created with a bitcoin uri string or an object. All instances of | |
* URI are valid, the static method isValid allows checking before instantiation. | |
* | |
* All standard parameters can be found as members of the class, the address | |
* is represented using an {Address} instance and the amount is represented in | |
* satoshis. Any other non-standard parameters can be found under the extra member. | |
* | |
* @example | |
* ```javascript | |
* | |
* var uri = new URI('bitcoin:12A1MyfXbW6RhdRAZEqofac5jCQQjwEPBu?amount=1.2'); | |
* console.log(uri.address, uri.amount); | |
* ``` | |
* | |
* @param {string|Object} data - A bitcoin URI string or an Object | |
* @param {Array.<string>=} knownParams - Required non-standard params | |
* @throws {TypeError} Invalid bitcoin address | |
* @throws {TypeError} Invalid amount | |
* @throws {Error} Unknown required argument | |
* @returns {URI} A new valid and frozen instance of URI | |
* @constructor | |
*/ | |
var URI = function URI(data, knownParams) { | |
if (!(this instanceof URI)) { | |
return new URI(data, knownParams); | |
} | |
this.extras = {}; | |
this.knownParams = knownParams || []; | |
this.address = this.network = this.amount = this.message = null; | |
if (typeof data === 'string') { | |
var params = URI.parse(data); | |
if (params.amount) { | |
params.amount = this._parseAmount(params.amount); | |
} | |
this._fromObject(params); | |
} else if ((typeof data === 'undefined' ? 'undefined' : _typeof(data)) === 'object') { | |
this._fromObject(data); | |
} else { | |
throw new TypeError('Unrecognized data format.'); | |
} | |
}; | |
/** | |
* Instantiate a URI from a String | |
* | |
* @param {string} str - JSON string or object of the URI | |
* @returns {URI} A new instance of a URI | |
*/ | |
URI.fromString = function fromString(str) { | |
if (typeof str !== 'string') { | |
throw new TypeError('Expected a string'); | |
} | |
return new URI(str); | |
}; | |
/** | |
* Instantiate a URI from an Object | |
* | |
* @param {Object} data - object of the URI | |
* @returns {URI} A new instance of a URI | |
*/ | |
URI.fromObject = function fromObject(json) { | |
return new URI(json); | |
}; | |
/** | |
* Check if an bitcoin URI string is valid | |
* | |
* @example | |
* ```javascript | |
* | |
* var valid = URI.isValid('bitcoin:12A1MyfXbW6RhdRAZEqofac5jCQQjwEPBu'); | |
* // true | |
* ``` | |
* | |
* @param {string|Object} data - A bitcoin URI string or an Object | |
* @param {Array.<string>=} knownParams - Required non-standard params | |
* @returns {boolean} Result of uri validation | |
*/ | |
URI.isValid = function (arg, knownParams) { | |
try { | |
new URI(arg, knownParams); | |
} catch (err) { | |
return false; | |
} | |
return true; | |
}; | |
/** | |
* Convert a bitcoin URI string into a simple object. | |
* | |
* @param {string} uri - A bitcoin URI string | |
* @throws {TypeError} Invalid bitcoin URI | |
* @returns {Object} An object with the parsed params | |
*/ | |
URI.parse = function (uri) { | |
var info = URL.parse(uri, true); | |
if (info.protocol !== 'bitcoin:') { | |
throw new TypeError('Invalid bitcoin URI'); | |
} | |
// workaround to host insensitiveness | |
var group = /[^:]*:\/?\/?([^?]*)/.exec(uri); | |
info.query.address = group && group[1] || undefined; | |
return info.query; | |
}; | |
URI.Members = ['address', 'amount', 'message', 'label', 'r']; | |
/** | |
* Internal function to load the URI instance with an object. | |
* | |
* @param {Object} obj - Object with the information | |
* @throws {TypeError} Invalid bitcoin address | |
* @throws {TypeError} Invalid amount | |
* @throws {Error} Unknown required argument | |
*/ | |
URI.prototype._fromObject = function (obj) { | |
/* jshint maxcomplexity: 10 */ | |
if (!Address.isValid(obj.address)) { | |
throw new TypeError('Invalid bitcoin address'); | |
} | |
this.address = new Address(obj.address); | |
this.network = this.address.network; | |
this.amount = obj.amount; | |
for (var key in obj) { | |
if (key === 'address' || key === 'amount') { | |
continue; | |
} | |
if (/^req-/.exec(key) && this.knownParams.indexOf(key) === -1) { | |
throw Error('Unknown required argument ' + key); | |
} | |
var destination = URI.Members.indexOf(key) > -1 ? this : this.extras; | |
destination[key] = obj[key]; | |
} | |
}; | |
/** | |
* Internal function to transform a BTC string amount into satoshis | |
* | |
* @param {string} amount - Amount BTC string | |
* @throws {TypeError} Invalid amount | |
* @returns {Object} Amount represented in satoshis | |
*/ | |
URI.prototype._parseAmount = function (amount) { | |
amount = Number(amount); | |
if (isNaN(amount)) { | |
throw new TypeError('Invalid amount'); | |
} | |
return Unit.fromBTC(amount).toSatoshis(); | |
}; | |
URI.prototype.toObject = URI.prototype.toJSON = function toObject() { | |
var json = {}; | |
for (var i = 0; i < URI.Members.length; i++) { | |
var m = URI.Members[i]; | |
if (this.hasOwnProperty(m) && typeof this[m] !== 'undefined') { | |
json[m] = this[m].toString(); | |
} | |
} | |
_.extend(json, this.extras); | |
return json; | |
}; | |
/** | |
* Will return a the string representation of the URI | |
* | |
* @returns {string} Bitcoin URI string | |
*/ | |
URI.prototype.toString = function () { | |
var query = {}; | |
if (this.amount) { | |
query.amount = Unit.fromSatoshis(this.amount).toBTC(); | |
} | |
if (this.message) { | |
query.message = this.message; | |
} | |
if (this.label) { | |
query.label = this.label; | |
} | |
if (this.r) { | |
query.r = this.r; | |
} | |
_.extend(query, this.extras); | |
return URL.format({ | |
protocol: 'bitcoin:', | |
host: this.address, | |
query: query | |
}); | |
}; | |
/** | |
* Will return a string formatted for the console | |
* | |
* @returns {string} Bitcoin URI | |
*/ | |
URI.prototype.inspect = function () { | |
return '<URI: ' + this.toString() + '>'; | |
}; | |
module.exports = URI; | |
},{"./address":27,"./unit":66,"lodash":267,"url":351}],68:[function(require,module,exports){ | |
(function (Buffer){ | |
'use strict'; | |
var buffer = require('buffer'); | |
var assert = require('assert'); | |
var js = require('./js'); | |
var $ = require('./preconditions'); | |
function equals(a, b) { | |
if (a.length !== b.length) { | |
return false; | |
} | |
var length = a.length; | |
for (var i = 0; i < length; i++) { | |
if (a[i] !== b[i]) { | |
return false; | |
} | |
} | |
return true; | |
} | |
module.exports = { | |
/** | |
* Fill a buffer with a value. | |
* | |
* @param {Buffer} buffer | |
* @param {number} value | |
* @return {Buffer} | |
*/ | |
fill: function fill(buffer, value) { | |
$.checkArgumentType(buffer, 'Buffer', 'buffer'); | |
$.checkArgumentType(value, 'number', 'value'); | |
var length = buffer.length; | |
for (var i = 0; i < length; i++) { | |
buffer[i] = value; | |
} | |
return buffer; | |
}, | |
/** | |
* Return a copy of a buffer | |
* | |
* @param {Buffer} original | |
* @return {Buffer} | |
*/ | |
copy: function copy(original) { | |
var buffer = new Buffer(original.length); | |
original.copy(buffer); | |
return buffer; | |
}, | |
/** | |
* Returns true if the given argument is an instance of a buffer. Tests for | |
* both node's Buffer and Uint8Array | |
* | |
* @param {*} arg | |
* @return {boolean} | |
*/ | |
isBuffer: function isBuffer(arg) { | |
return buffer.Buffer.isBuffer(arg) || arg instanceof Uint8Array; | |
}, | |
/** | |
* Returns a zero-filled byte array | |
* | |
* @param {number} bytes | |
* @return {Buffer} | |
*/ | |
emptyBuffer: function emptyBuffer(bytes) { | |
$.checkArgumentType(bytes, 'number', 'bytes'); | |
var result = new buffer.Buffer(bytes); | |
for (var i = 0; i < bytes; i++) { | |
result.write('\0', i); | |
} | |
return result; | |
}, | |
/** | |
* Concatenates a buffer | |
* | |
* Shortcut for <tt>buffer.Buffer.concat</tt> | |
*/ | |
concat: buffer.Buffer.concat, | |
equals: equals, | |
equal: equals, | |
/** | |
* Transforms a number from 0 to 255 into a Buffer of size 1 with that value | |
* | |
* @param {number} integer | |
* @return {Buffer} | |
*/ | |
integerAsSingleByteBuffer: function integerAsSingleByteBuffer(integer) { | |
$.checkArgumentType(integer, 'number', 'integer'); | |
return new buffer.Buffer([integer & 0xff]); | |
}, | |
/** | |
* Transform a 4-byte integer into a Buffer of length 4. | |
* | |
* @param {number} integer | |
* @return {Buffer} | |
*/ | |
integerAsBuffer: function integerAsBuffer(integer) { | |
$.checkArgumentType(integer, 'number', 'integer'); | |
var bytes = []; | |
bytes.push(integer >> 24 & 0xff); | |
bytes.push(integer >> 16 & 0xff); | |
bytes.push(integer >> 8 & 0xff); | |
bytes.push(integer & 0xff); | |
return new Buffer(bytes); | |
}, | |
/** | |
* Transform the first 4 values of a Buffer into a number, in little endian encoding | |
* | |
* @param {Buffer} buffer | |
* @return {number} | |
*/ | |
integerFromBuffer: function integerFromBuffer(buffer) { | |
$.checkArgumentType(buffer, 'Buffer', 'buffer'); | |
return buffer[0] << 24 | buffer[1] << 16 | buffer[2] << 8 | buffer[3]; | |
}, | |
/** | |
* Transforms the first byte of an array into a number ranging from -128 to 127 | |
* @param {Buffer} buffer | |
* @return {number} | |
*/ | |
integerFromSingleByteBuffer: function integerFromBuffer(buffer) { | |
$.checkArgumentType(buffer, 'Buffer', 'buffer'); | |
return buffer[0]; | |
}, | |
/** | |
* Transforms a buffer into a string with a number in hexa representation | |
* | |
* Shorthand for <tt>buffer.toString('hex')</tt> | |
* | |
* @param {Buffer} buffer | |
* @return {string} | |
*/ | |
bufferToHex: function bufferToHex(buffer) { | |
$.checkArgumentType(buffer, 'Buffer', 'buffer'); | |
return buffer.toString('hex'); | |
}, | |
/** | |
* Reverse a buffer | |
* @param {Buffer} param | |
* @return {Buffer} | |
*/ | |
reverse: function reverse(param) { | |
var ret = new buffer.Buffer(param.length); | |
for (var i = 0; i < param.length; i++) { | |
ret[i] = param[param.length - i - 1]; | |
} | |
return ret; | |
}, | |
/** | |
* Transforms an hexa encoded string into a Buffer with binary values | |
* | |
* Shorthand for <tt>Buffer(string, 'hex')</tt> | |
* | |
* @param {string} string | |
* @return {Buffer} | |
*/ | |
hexToBuffer: function hexToBuffer(string) { | |
assert(js.isHexa(string)); | |
return new buffer.Buffer(string, 'hex'); | |
} | |
}; | |
module.exports.NULL_HASH = module.exports.fill(new Buffer(32), 0); | |
module.exports.EMPTY_BUFFER = new Buffer(0); | |
}).call(this,require("buffer").Buffer) | |
},{"./js":69,"./preconditions":70,"assert":21,"buffer":148}],69:[function(require,module,exports){ | |
'use strict'; | |
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; | |
var _ = require('lodash'); | |
/** | |
* Determines whether a string contains only hexadecimal values | |
* | |
* @name JSUtil.isHexa | |
* @param {string} value | |
* @return {boolean} true if the string is the hexa representation of a number | |
*/ | |
var isHexa = function isHexa(value) { | |
if (!_.isString(value)) { | |
return false; | |
} | |
return (/^[0-9a-fA-F]+$/.test(value) | |
); | |
}; | |
/** | |
* @namespace JSUtil | |
*/ | |
module.exports = { | |
/** | |
* Test if an argument is a valid JSON object. If it is, returns a truthy | |
* value (the json object decoded), so no double JSON.parse call is necessary | |
* | |
* @param {string} arg | |
* @return {Object|boolean} false if the argument is not a JSON string. | |
*/ | |
isValidJSON: function isValidJSON(arg) { | |
var parsed; | |
if (!_.isString(arg)) { | |
return false; | |
} | |
try { | |
parsed = JSON.parse(arg); | |
} catch (e) { | |
return false; | |
} | |
if ((typeof parsed === 'undefined' ? 'undefined' : _typeof(parsed)) === 'object') { | |
return true; | |
} | |
return false; | |
}, | |
isHexa: isHexa, | |
isHexaString: isHexa, | |
/** | |
* Clone an array | |
*/ | |
cloneArray: function cloneArray(array) { | |
return [].concat(array); | |
}, | |
/** | |
* Define immutable properties on a target object | |
* | |
* @param {Object} target - An object to be extended | |
* @param {Object} values - An object of properties | |
* @return {Object} The target object | |
*/ | |
defineImmutable: function defineImmutable(target, values) { | |
Object.keys(values).forEach(function (key) { | |
Object.defineProperty(target, key, { | |
configurable: false, | |
enumerable: true, | |
value: values[key] | |
}); | |
}); | |
return target; | |
}, | |
/** | |
* Checks that a value is a natural number, a positive integer or zero. | |
* | |
* @param {*} value | |
* @return {Boolean} | |
*/ | |
isNaturalNumber: function isNaturalNumber(value) { | |
return typeof value === 'number' && isFinite(value) && Math.floor(value) === value && value >= 0; | |
} | |
}; | |
},{"lodash":267}],70:[function(require,module,exports){ | |
'use strict'; | |
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; | |
var errors = require('../errors'); | |
var _ = require('lodash'); | |
module.exports = { | |
checkState: function checkState(condition, message) { | |
if (!condition) { | |
throw new errors.InvalidState(message); | |
} | |
}, | |
checkArgument: function checkArgument(condition, argumentName, message, docsPath) { | |
if (!condition) { | |
throw new errors.InvalidArgument(argumentName, message, docsPath); | |
} | |
}, | |
checkArgumentType: function checkArgumentType(argument, type, argumentName) { | |
argumentName = argumentName || '(unknown name)'; | |
if (_.isString(type)) { | |
if (type === 'Buffer') { | |
var buffer = require('buffer'); // './buffer' fails on cordova & RN | |
if (!buffer.Buffer.isBuffer(argument)) { | |
throw new errors.InvalidArgumentType(argument, type, argumentName); | |
} | |
} else if ((typeof argument === 'undefined' ? 'undefined' : _typeof(argument)) !== type) { | |
throw new errors.InvalidArgumentType(argument, type, argumentName); | |
} | |
} else { | |
if (!(argument instanceof type)) { | |
throw new errors.InvalidArgumentType(argument, type.name, argumentName); | |
} | |
} | |
} | |
}; | |
},{"../errors":43,"buffer":148,"lodash":267}],71:[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":86,"./elliptic/curve":74,"./elliptic/curves":77,"./elliptic/ec":78,"./elliptic/eddsa":81,"./elliptic/utils":85,"brorand":100}],72:[function(require,module,exports){ | |
'use strict'; | |
var BN = require('bn.js'); | |
var elliptic = require('../../elliptic'); | |
var utils = elliptic.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); | |
// 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); | |
var I = (1 << doubles.step + 1) - (doubles.step % 2 === 0 ? 2 : 1); | |
I /= 3; | |
// Translate into more windowed form | |
var repr = []; | |
for (var j = 0; j < naf.length; j += doubles.step) { | |
var nafW = 0; | |
for (var k = j + doubles.step - 1; k >= j; k--) { | |
nafW = (nafW << 1) + naf[k]; | |
}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 (var j = 0; j < repr.length; j++) { | |
var 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); | |
// 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 k = 0; i >= 0 && naf[i] === 0; i--) { | |
k++; | |
}if (i >= 0) k++; | |
acc = acc.dblp(k); | |
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; | |
for (var i = 0; i < len; i++) { | |
var p = points[i]; | |
var nafPoints = p._getNAFPoints(defW); | |
wndWidth[i] = nafPoints.wnd; | |
wnd[i] = nafPoints.points; | |
} | |
// Comb small window NAFs | |
for (var 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]); | |
naf[b] = getNAF(coeffs[b], wndWidth[b]); | |
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 (var 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 (var i = max; i >= 0; i--) { | |
var k = 0; | |
while (i >= 0) { | |
var zero = true; | |
for (var 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 (var j = 0; j < len; j++) { | |
var z = tmp[j]; | |
var 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 (var 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; | |
}; | |
},{"../../elliptic":71,"bn.js":99}],73:[function(require,module,exports){ | |
'use strict'; | |
var curve = require('../curve'); | |
var elliptic = require('../../elliptic'); | |
var BN = require('bn.js'); | |
var inherits = require('inherits'); | |
var Base = curve.base; | |
var assert = elliptic.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 - 1) / (d y^2 + 1) | |
var y2 = y.redSqr(); | |
var lhs = y2.redSub(this.one); | |
var rhs = y2.redMul(this.d).redAdd(this.one); | |
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.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 '<EC Point Infinity>'; | |
return '<EC Point x: ' + this.x.fromRed().toString(16, 2) + ' y: ' + this.y.fromRed().toString(16, 2) + ' z: ' + this.z.fromRed().toString(16, 2) + '>'; | |
}; | |
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; | |
}; | |
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; | |
if (this.curve.twisted) { | |
// E = a * C | |
var 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 | |
var h = this.z.redSqr(); | |
// J = F - 2 * H | |
var 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 | |
var e = c.redAdd(d); | |
// H = (c * Z1)^2 | |
var h = this.curve._mulC(this.c.redMul(this.z)).redSqr(); | |
// J = E - 2 * H | |
var 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; | |
} | |
return false; | |
}; | |
// Compatibility with BaseCurve | |
Point.prototype.toP = Point.prototype.normalize; | |
Point.prototype.mixedAdd = Point.prototype.add; | |
},{"../../elliptic":71,"../curve":74,"bn.js":99,"inherits":256}],74:[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":72,"./edwards":73,"./mont":75,"./short":76}],75:[function(require,module,exports){ | |
'use strict'; | |
var curve = require('../curve'); | |
var BN = require('bn.js'); | |
var inherits = require('inherits'); | |
var Base = curve.base; | |
var elliptic = require('../../elliptic'); | |
var utils = elliptic.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 '<EC Point Infinity>'; | |
return '<EC Point x: ' + this.x.fromRed().toString(16, 2) + ' z: ' + this.z.fromRed().toString(16, 2) + '>'; | |
}; | |
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(); | |
}; | |
},{"../../elliptic":71,"../curve":74,"bn.js":99,"inherits":256}],76:[function(require,module,exports){ | |
'use strict'; | |
var curve = require('../curve'); | |
var elliptic = require('../../elliptic'); | |
var BN = require('bn.js'); | |
var inherits = require('inherits'); | |
var Base = curve.base; | |
var assert = elliptic.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 endoMul(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 '<EC Point Infinity>'; | |
return '<EC Point x: ' + this.x.fromRed().toString(16, 2) + ' y: ' + this.y.fromRed().toString(16, 2) + '>'; | |
}; | |
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._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 negate(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(); | |
if (this.curve.zeroA || this.curve.threeA) { | |
var r = this; | |
for (var 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 (var 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; | |
} | |
return false; | |
}; | |
JPoint.prototype.inspect = function inspect() { | |
if (this.isInfinity()) return '<EC JPoint Infinity>'; | |
return '<EC JPoint x: ' + this.x.toString(16, 2) + ' y: ' + this.y.toString(16, 2) + ' z: ' + this.z.toString(16, 2) + '>'; | |
}; | |
JPoint.prototype.isInfinity = function isInfinity() { | |
// XXX This code assumes that zero is always zero in red | |
return this.z.cmpn(0) === 0; | |
}; | |
},{"../../elliptic":71,"../curve":74,"bn.js":99,"inherits":256}],77:[function(require,module,exports){ | |
'use strict'; | |
var curves = exports; | |
var hash = require('hash.js'); | |
var elliptic = require('../elliptic'); | |
var assert = elliptic.utils.assert; | |
function PresetCurve(options) { | |
if (options.type === 'short') this.curve = new elliptic.curve.short(options);else if (options.type === 'edwards') this.curve = new elliptic.curve.edwards(options);else this.curve = new elliptic.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 get() { | |
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] | |
}); | |
},{"../elliptic":71,"./precomputed/secp256k1":84,"hash.js":240}],78:[function(require,module,exports){ | |
'use strict'; | |
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; | |
var BN = require('bn.js'); | |
var HmacDRBG = require('hmac-drbg'); | |
var elliptic = require('../../elliptic'); | |
var utils = elliptic.utils; | |
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(elliptic.curves.hasOwnProperty(options), 'Unknown curve ' + options); | |
options = elliptic.curves[options]; | |
} | |
// Shortcut for `elliptic.ec(elliptic.curves.curveName)` | |
if (options instanceof elliptic.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 || elliptic.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)); | |
do { | |
var priv = new BN(drbg.generate(bytes)); | |
if (priv.cmp(ns2) > 0) continue; | |
priv.iaddn(1); | |
return this.keyFromPrivate(priv); | |
} while (true); | |
}; | |
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 === 'undefined' ? 'undefined' : _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; true; 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); | |
if (!this.curve._maxwellTrick) { | |
var 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 | |
var 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'); | |
}; | |
},{"../../elliptic":71,"./key":79,"./signature":80,"bn.js":99,"hmac-drbg":253}],79:[function(require,module,exports){ | |
'use strict'; | |
var BN = require('bn.js'); | |
var elliptic = require('../../elliptic'); | |
var utils = elliptic.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) { | |
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 '<Key priv: ' + (this.priv && this.priv.toString(16, 2)) + ' pub: ' + (this.pub && this.pub.inspect()) + ' >'; | |
}; | |
},{"../../elliptic":71,"bn.js":99}],80:[function(require,module,exports){ | |
'use strict'; | |
var BN = require('bn.js'); | |
var elliptic = require('../../elliptic'); | |
var utils = elliptic.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; | |
var val = 0; | |
for (var i = 0, off = p.place; i < octetLen; i++, off++) { | |
val <<= 8; | |
val |= buf[off]; | |
} | |
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 + p.place !== data.length) { | |
return false; | |
} | |
if (data[p.place++] !== 0x02) { | |
return false; | |
} | |
var rlen = getLength(data, p); | |
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 (data.length !== slen + p.place) { | |
return false; | |
} | |
var s = data.slice(p.place, slen + p.place); | |
if (r[0] === 0 && r[1] & 0x80) { | |
r = r.slice(1); | |
} | |
if (s[0] === 0 && s[1] & 0x80) { | |
s = s.slice(1); | |
} | |
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); | |
}; | |
},{"../../elliptic":71,"bn.js":99}],81:[function(require,module,exports){ | |
'use strict'; | |
var hash = require('hash.js'); | |
var elliptic = require('../../elliptic'); | |
var utils = elliptic.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); | |
var curve = elliptic.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; | |
}; | |
},{"../../elliptic":71,"./key":82,"./signature":83,"hash.js":240}],82:[function(require,module,exports){ | |
'use strict'; | |
var elliptic = require('../../elliptic'); | |
var utils = elliptic.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<Byte>} [params.secret] - secret seed bytes | |
* @param {Point} [params.pub] - public key point (aka `A` in eddsa terms) | |
* @param {Array<Byte>} [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; | |
},{"../../elliptic":71}],83:[function(require,module,exports){ | |
'use strict'; | |
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; | |
var BN = require('bn.js'); | |
var elliptic = require('../../elliptic'); | |
var utils = elliptic.utils; | |
var assert = utils.assert; | |
var cachedProperty = utils.cachedProperty; | |
var parseBytes = utils.parseBytes; | |
/** | |
* @param {EDDSA} eddsa - eddsa instance | |
* @param {Array<Bytes>|Object} sig - | |
* @param {Array<Bytes>|Point} [sig.R] - R point as Point or bytes | |
* @param {Array<Bytes>|bn} [sig.S] - S scalar as bn or bytes | |
* @param {Array<Bytes>} [sig.Rencoded] - R point encoded | |
* @param {Array<Bytes>} [sig.Sencoded] - S scalar encoded | |
*/ | |
function Signature(eddsa, sig) { | |
this.eddsa = eddsa; | |
if ((typeof sig === 'undefined' ? 'undefined' : _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; | |
},{"../../elliptic":71,"bn.js":99}],84:[function(require,module,exports){ | |
'use strict'; | |
module.exports = { | |
doubles: { | |
step: 4, | |
points: [['e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0a', 'f7e3507399e595929db99f34f57937101296891e44d23f0be1f32cce69616821'], ['8282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508', '11f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf'], ['175e159f728b865a72f99cc6c6fc846de0b93833fd2222ed73fce5b551e5b739', 'd3506e0d9e3c79eba4ef97a51ff71f5eacb5955add24345c6efa6ffee9fed695'], ['363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640', '4e273adfc732221953b445397f3363145b9a89008199ecb62003c7f3bee9de9'], ['8b4b5f165df3c2be8c6244b5b745638843e4a781a15bcd1b69f79a55dffdf80c', '4aad0a6f68d308b4b3fbd7813ab0da04f9e336546162ee56b3eff0c65fd4fd36'], ['723cbaa6e5db996d6bf771c00bd548c7b700dbffa6c0e77bcb6115925232fcda', '96e867b5595cc498a921137488824d6e2660a0653779494801dc069d9eb39f5f'], ['eebfa4d493bebf98ba5feec812c2d3b50947961237a919839a533eca0e7dd7fa', '5d9a8ca3970ef0f269ee7edaf178089d9ae4cdc3a711f712ddfd4fdae1de8999'], ['100f44da696e71672791d0a09b7bde459f1215a29b3c03bfefd7835b39a48db0', 'cdd9e13192a00b772ec8f3300c090666b7ff4a18ff5195ac0fbd5cd62bc65a09'], ['e1031be262c7ed1b1dc9227a4a04c017a77f8d4464f3b3852c8acde6e534fd2d', '9d7061928940405e6bb6a4176597535af292dd419e1ced79a44f18f29456a00d'], ['feea6cae46d55b530ac2839f143bd7ec5cf8b266a41d6af52d5e688d9094696d', 'e57c6b6c97dce1bab06e4e12bf3ecd5c981c8957cc41442d3155debf18090088'], ['da67a91d91049cdcb367be4be6ffca3cfeed657d808583de33fa978bc1ec6cb1', '9bacaa35481642bc41f463f7ec9780e5dec7adc508f740a17e9ea8e27a68be1d'], ['53904faa0b334cdda6e000935ef22151ec08d0f7bb11069f57545ccc1a37b7c0', '5bc087d0bc80106d88c9eccac20d3c1c13999981e14434699dcb096b022771c8'], ['8e7bcd0bd35983a7719cca7764ca906779b53a043a9b8bcaeff959f43ad86047', '10b7770b2a3da4b3940310420ca9514579e88e2e47fd68b3ea10047e8460372a'], ['385eed34c1cdff21e6d0818689b81bde71a7f4f18397e6690a841e1599c43862', '283bebc3e8ea23f56701de19e9ebf4576b304eec2086dc8cc0458fe5542e5453'], ['6f9d9b803ecf191637c73a4413dfa180fddf84a5947fbc9c606ed86c3fac3a7', '7c80c68e603059ba69b8e2a30e45c4d47ea4dd2f5c281002d86890603a842160'], ['3322d401243c4e2582a2147c104d6ecbf774d163db0f5e5313b7e0e742d0e6bd', '56e70797e9664ef5bfb019bc4ddaf9b72805f63ea2873af624f3a2e96c28b2a0'], ['85672c7d2de0b7da2bd1770d89665868741b3f9af7643397721d74d28134ab83', '7c481b9b5b43b2eb6374049bfa62c2e5e77f17fcc5298f44c8e3094f790313a6'], ['948bf809b1988a46b06c9f1919413b10f9226c60f668832ffd959af60c82a0a', '53a562856dcb6646dc6b74c5d1c3418c6d4dff08c97cd2bed4cb7f88d8c8e589'], ['6260ce7f461801c34f067ce0f02873a8f1b0e44dfc69752accecd819f38fd8e8', 'bc2da82b6fa5b571a7f09049776a1ef7ecd292238051c198c1a84e95b2b4ae17'], ['e5037de0afc1d8d43d8348414bbf4103043ec8f575bfdc432953cc8d2037fa2d', '4571534baa94d3b5f9f98d09fb990bddbd5f5b03ec481f10e0e5dc841d755bda'], ['e06372b0f4a207adf5ea905e8f1771b4e7e8dbd1c6a6c5b725866a0ae4fce725', '7a908974bce18cfe12a27bb2ad5a488cd7484a7787104870b27034f94eee31dd'], ['213c7a715cd5d45358d0bbf9dc0ce02204b10bdde2a3f58540ad6908d0559754', '4b6dad0b5ae462507013ad06245ba190bb4850f5f36a7eeddff2c27534b458f2'], ['4e7c272a7af4b34e8dbb9352a5419a87e2838c70adc62cddf0cc3a3b08fbd53c', '17749c766c9d0b18e16fd09f6def681b530b9614bff7dd33e0b3941817dcaae6'], ['fea74e3dbe778b1b10f238ad61686aa5c76e3db2be43057632427e2840fb27b6', '6e0568db9b0b13297cf674deccb6af93126b596b973f7b77701d3db7f23cb96f'], ['76e64113f677cf0e10a2570d599968d31544e179b760432952c02a4417bdde39', 'c90ddf8dee4e95cf577066d70681f0d35e2a33d2b56d2032b4b1752d1901ac01'], ['c738c56b03b2abe1e8281baa743f8f9a8f7cc643df26cbee3ab150242bcbb891', '893fb578951ad2537f718f2eacbfbbbb82314eef7880cfe917e735d9699a84c3'], ['d895626548b65b81e264c7637c972877d1d72e5f3a925014372e9f6588f6c14b', 'febfaa38f2bc7eae728ec60818c340eb03428d632bb067e179363ed75d7d991f'], ['b8da94032a957518eb0f6433571e8761ceffc73693e84edd49150a564f676e03', '2804dfa44805a1e4d7c99cc9762808b092cc584d95ff3b511488e4e74efdf6e7'], ['e80fea14441fb33a7d8adab9475d7fab2019effb5156a792f1a11778e3c0df5d', 'eed1de7f638e00771e89768ca3ca94472d155e80af322ea9fcb4291b6ac9ec78'], ['a301697bdfcd704313ba48e51d567543f2a182031efd6915ddc07bbcc4e16070', '7370f91cfb67e4f5081809fa25d40f9b1735dbf7c0a11a130c0d1a041e177ea1'], ['90ad85b389d6b936463f9d0512678de208cc330b11307fffab7ac63e3fb04ed4', 'e507a3620a38261affdcbd9427222b839aefabe1582894d991d4d48cb6ef150'], ['8f68b9d2f63b5f339239c1ad981f162ee88c5678723ea3351b7b444c9ec4c0da', '662a9f2dba063986de1d90c2b6be215dbbea2cfe95510bfdf23cbf79501fff82'], ['e4f3fb0176af85d65ff99ff9198c36091f48e86503681e3e6686fd5053231e11', '1e63633ad0ef4f1c1661a6d0ea02b7286cc7e74ec951d1c9822c38576feb73bc'], ['8c00fa9b18ebf331eb961537a45a4266c7034f2f0d4e1d0716fb6eae20eae29e', 'efa47267fea521a1a9dc343a3736c974c2fadafa81e36c54e7d2a4c66702414b'], ['e7a26ce69dd4829f3e10cec0a9e98ed3143d084f308b92c0997fddfc60cb3e41', '2a758e300fa7984b471b006a1aafbb18d0a6b2c0420e83e20e8a9421cf2cfd51'], ['b6459e0ee3662ec8d23540c223bcbdc571cbcb967d79424f3cf29eb3de6b80ef', '67c876d06f3e06de1dadf16e5661db3c4b3ae6d48e35b2ff30bf0b61a71ba45'], ['d68a80c8280bb840793234aa118f06231d6f1fc67e73c5a5deda0f5b496943e8', 'db8ba9fff4b586d00c4b1f9177b0e28b5b0e7b8f7845295a294c84266b133120'], ['324aed7df65c804252dc0270907a30b09612aeb973449cea4095980fc28d3d5d', '648a365774b61f2ff130c0c35aec1f4f19213b0c7e332843967224af96ab7c84'], ['4df9c14919cde61f6d51dfdbe5fee5dceec4143ba8d1ca888e8bd373fd054c96', '35ec51092d8728050974c23a1d85d4b5d506cdc288490192ebac06cad10d5d'], ['9c3919a84a474870faed8a9c1cc66021523489054d7f0308cbfc99c8ac1f98cd', 'ddb84f0f4a4ddd57584f044bf260e641905326f76c64c8e6be7e5e03d4fc599d'], ['6057170b1dd12fdf8de05f281d8e06bb91e1493a8b91d4cc5a21382120a959e5', '9a1af0b26a6a4807add9a2daf71df262465152bc3ee24c65e899be932385a2a8'], ['a576df8e23a08411421439a4518da31880cef0fba7d4df12b1a6973eecb94266', '40a6bf20e76640b2c92b97afe58cd82c432e10a7f514d9f3ee8be11ae1b28ec8'], ['7778a78c28dec3e30a05fe9629de8c38bb30d1f5cf9a3a208f763889be58ad71', '34626d9ab5a5b22ff7098e12f2ff580087b38411ff24ac563b513fc1fd9f43ac'], ['928955ee637a84463729fd30e7afd2ed5f96274e5ad7e5cb09eda9c06d903ac', 'c25621003d3f42a827b78a13093a95eeac3d26efa8a8d83fc5180e935bcd091f'], ['85d0fef3ec6db109399064f3a0e3b2855645b4a907ad354527aae75163d82751', '1f03648413a38c0be29d496e582cf5663e8751e96877331582c237a24eb1f962'], ['ff2b0dce97eece97c1c9b6041798b85dfdfb6d8882da20308f5404824526087e', '493d13fef524ba188af4c4dc54d07936c7b7ed6fb90e2ceb2c951e01f0c29907'], ['827fbbe4b1e880ea9ed2b2e6301b212b57f1ee148cd6dd28780e5e2cf856e241', 'c60f9c923c727b0b71bef2c67d1d12687ff7a63186903166d605b68baec293ec'], ['eaa649f21f51bdbae7be4ae34ce6e5217a58fdce7f47f9aa7f3b58fa2120e2b3', 'be3279ed5bbbb03ac69a80f89879aa5a01a6b965f13f7e59d47a5305ba5ad93d'], ['e4a42d43c5cf169d9391df6decf42ee541b6d8f0c9a137401e23632dda34d24f', '4d9f92e716d1c73526fc99ccfb8ad34ce886eedfa8d8e4f13a7f7131deba9414'], ['1ec80fef360cbdd954160fadab352b6b92b53576a88fea4947173b9d4300bf19', 'aeefe93756b5340d2f3a4958a7abbf5e0146e77f6295a07b671cdc1cc107cefd'], ['146a778c04670c2f91b00af4680dfa8bce3490717d58ba889ddb5928366642be', 'b318e0ec3354028add669827f9d4b2870aaa971d2f7e5ed1d0b297483d83efd0'], ['fa50c0f61d22e5f07e3acebb1aa07b128d0012209a28b9776d76a8793180eef9', '6b84c6922397eba9b72cd2872281a68a5e683293a57a213b38cd8d7d3f4f2811'], ['da1d61d0ca721a11b1a5bf6b7d88e8421a288ab5d5bba5220e53d32b5f067ec2', '8157f55a7c99306c79c0766161c91e2966a73899d279b48a655fba0f1ad836f1'], ['a8e282ff0c9706907215ff98e8fd416615311de0446f1e062a73b0610d064e13', '7f97355b8db81c09abfb7f3c5b2515888b679a3e50dd6bd6cef7c73111f4cc0c'], ['174a53b9c9a285872d39e56e6913cab15d59b1fa512508c022f382de8319497c', 'ccc9dc37abfc9c1657b4155f2c47f9e6646b3a1d8cb9854383da13ac079afa73'], ['959396981943785c3d3e57edf5018cdbe039e730e4918b3d884fdff09475b7ba', '2e7e552888c331dd8ba0386a4b9cd6849c653f64c8709385e9b8abf87524f2fd'], ['d2a63a50ae401e56d645a1153b109a8fcca0a43d561fba2dbb51340c9d82b151', 'e82d86fb6443fcb7565aee58b2948220a70f750af484ca52d4142174dcf89405'], ['64587e2335471eb890ee7896d7cfdc866bacbdbd3839317b3436f9b45617e073', 'd99fcdd5bf6902e2ae96dd6447c299a185b90a39133aeab358299e5e9faf6589'], ['8481bde0e4e4d885b3a546d3e549de042f0aa6cea250e7fd358d6c86dd45e458', '38ee7b8cba5404dd84a25bf39cecb2ca900a79c42b262e556d64b1b59779057e'], ['13464a57a78102aa62b6979ae817f4637ffcfed3c4b1ce30bcd6303f6caf666b', '69be159004614580ef7e433453ccb0ca48f300a81d0942e13f495a907f6ecc27'], ['bc4a9df5b713fe2e9aef430bcc1dc97a0cd9ccede2f28588cada3a0d2d83f366', 'd3a81ca6e785c06383937adf4b798caa6e8a9fbfa547b16d758d666581f33c1'], ['8c28a97bf8298bc0d23d8c749452a32e694b65e30a9472a3954ab30fe5324caa', '40a30463a3305193378fedf31f7cc0eb7ae784f0451cb9459e71dc73cbef9482'], ['8ea9666139527a8c1dd94ce4f071fd23c8b350c5a4bb33748c4ba111faccae0', '620efabbc8ee2782e24e7c0cfb95c5d735b783be9cf0f8e955af34a30e62b945'], ['dd3625faef5ba06074669716bbd3788d89bdde815959968092f76cc4eb9a9787', '7a188fa3520e30d461da2501045731ca941461982883395937f68d00c644a573'], ['f710d79d9eb962297e4f6232b40e8f7feb2bc63814614d692c12de752408221e', 'ea98e67232d3b3295d3b535532115ccac8612c721851617526ae47a9c77bfc82']] | |
}, | |
naf: { | |
wnd: 7, | |
points: [['f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9', '388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672'], ['2f8bde4d1a07209355b4a7250a5c5128e88b84bddc619ab7cba8d569b240efe4', 'd8ac222636e5e3d6d4dba9dda6c9c426f788271bab0d6840dca87d3aa6ac62d6'], ['5cbdf0646e5db4eaa398f365f2ea7a0e3d419b7e0330e39ce92bddedcac4f9bc', '6aebca40ba255960a3178d6d861a54dba813d0b813fde7b5a5082628087264da'], ['acd484e2f0c7f65309ad178a9f559abde09796974c57e714c35f110dfc27ccbe', 'cc338921b0a7d9fd64380971763b61e9add888a4375f8e0f05cc262ac64f9c37'], ['774ae7f858a9411e5ef4246b70c65aac5649980be5c17891bbec17895da008cb', 'd984a032eb6b5e190243dd56d7b7b365372db1e2dff9d6a8301d74c9c953c61b'], ['f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8', 'ab0902e8d880a89758212eb65cdaf473a1a06da521fa91f29b5cb52db03ed81'], ['d7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e', '581e2872a86c72a683842ec228cc6defea40af2bd896d3a5c504dc9ff6a26b58'], ['defdea4cdb677750a420fee807eacf21eb9898ae79b9768766e4faa04a2d4a34', '4211ab0694635168e997b0ead2a93daeced1f4a04a95c0f6cfb199f69e56eb77'], ['2b4ea0a797a443d293ef5cff444f4979f06acfebd7e86d277475656138385b6c', '85e89bc037945d93b343083b5a1c86131a01f60c50269763b570c854e5c09b7a'], ['352bbf4a4cdd12564f93fa332ce333301d9ad40271f8107181340aef25be59d5', '321eb4075348f534d59c18259dda3e1f4a1b3b2e71b1039c67bd3d8bcf81998c'], ['2fa2104d6b38d11b0230010559879124e42ab8dfeff5ff29dc9cdadd4ecacc3f', '2de1068295dd865b64569335bd5dd80181d70ecfc882648423ba76b532b7d67'], ['9248279b09b4d68dab21a9b066edda83263c3d84e09572e269ca0cd7f5453714', '73016f7bf234aade5d1aa71bdea2b1ff3fc0de2a887912ffe54a32ce97cb3402'], ['daed4f2be3a8bf278e70132fb0beb7522f570e144bf615c07e996d443dee8729', 'a69dce4a7d6c98e8d4a1aca87ef8d7003f83c230f3afa726ab40e52290be1c55'], ['c44d12c7065d812e8acf28d7cbb19f9011ecd9e9fdf281b0e6a3b5e87d22e7db', '2119a460ce326cdc76c45926c982fdac0e106e861edf61c5a039063f0e0e6482'], ['6a245bf6dc698504c89a20cfded60853152b695336c28063b61c65cbd269e6b4', 'e022cf42c2bd4a708b3f5126f16a24ad8b33ba48d0423b6efd5e6348100d8a82'], ['1697ffa6fd9de627c077e3d2fe541084ce13300b0bec1146f95ae57f0d0bd6a5', 'b9c398f186806f5d27561506e4557433a2cf15009e498ae7adee9d63d01b2396'], ['605bdb019981718b986d0f07e834cb0d9deb8360ffb7f61df982345ef27a7479', '2972d2de4f8d20681a78d93ec96fe23c26bfae84fb14db43b01e1e9056b8c49'], ['62d14dab4150bf497402fdc45a215e10dcb01c354959b10cfe31c7e9d87ff33d', '80fc06bd8cc5b01098088a1950eed0db01aa132967ab472235f5642483b25eaf'], ['80c60ad0040f27dade5b4b06c408e56b2c50e9f56b9b8b425e555c2f86308b6f', '1c38303f1cc5c30f26e66bad7fe72f70a65eed4cbe7024eb1aa01f56430bd57a'], ['7a9375ad6167ad54aa74c6348cc54d344cc5dc9487d847049d5eabb0fa03c8fb', 'd0e3fa9eca8726909559e0d79269046bdc59ea10c70ce2b02d499ec224dc7f7'], ['d528ecd9b696b54c907a9ed045447a79bb408ec39b68df504bb51f459bc3ffc9', 'eecf41253136e5f99966f21881fd656ebc4345405c520dbc063465b521409933'], ['49370a4b5f43412ea25f514e8ecdad05266115e4a7ecb1387231808f8b45963', '758f3f41afd6ed428b3081b0512fd62a54c3f3afbb5b6764b653052a12949c9a'], ['77f230936ee88cbbd73df930d64702ef881d811e0e1498e2f1c13eb1fc345d74', '958ef42a7886b6400a08266e9ba1b37896c95330d97077cbbe8eb3c7671c60d6'], ['f2dac991cc4ce4b9ea44887e5c7c0bce58c80074ab9d4dbaeb28531b7739f530', 'e0dedc9b3b2f8dad4da1f32dec2531df9eb5fbeb0598e4fd1a117dba703a3c37'], ['463b3d9f662621fb1b4be8fbbe2520125a216cdfc9dae3debcba4850c690d45b', '5ed430d78c296c3543114306dd8622d7c622e27c970a1de31cb377b01af7307e'], ['f16f804244e46e2a09232d4aff3b59976b98fac14328a2d1a32496b49998f247', 'cedabd9b82203f7e13d206fcdf4e33d92a6c53c26e5cce26d6579962c4e31df6'], ['caf754272dc84563b0352b7a14311af55d245315ace27c65369e15f7151d41d1', 'cb474660ef35f5f2a41b643fa5e460575f4fa9b7962232a5c32f908318a04476'], ['2600ca4b282cb986f85d0f1709979d8b44a09c07cb86d7c124497bc86f082120', '4119b88753c15bd6a693b03fcddbb45d5ac6be74ab5f0ef44b0be9475a7e4b40'], ['7635ca72d7e8432c338ec53cd12220bc01c48685e24f7dc8c602a7746998e435', '91b649609489d613d1d5e590f78e6d74ecfc061d57048bad9e76f302c5b9c61'], ['754e3239f325570cdbbf4a87deee8a66b7f2b33479d468fbc1a50743bf56cc18', '673fb86e5bda30fb3cd0ed304ea49a023ee33d0197a695d0c5d98093c536683'], ['e3e6bd1071a1e96aff57859c82d570f0330800661d1c952f9fe2694691d9b9e8', '59c9e0bba394e76f40c0aa58379a3cb6a5a2283993e90c4167002af4920e37f5'], ['186b483d056a033826ae73d88f732985c4ccb1f32ba35f4b4cc47fdcf04aa6eb', '3b952d32c67cf77e2e17446e204180ab21fb8090895138b4a4a797f86e80888b'], ['df9d70a6b9876ce544c98561f4be4f725442e6d2b737d9c91a8321724ce0963f', '55eb2dafd84d6ccd5f862b785dc39d4ab157222720ef9da217b8c45cf2ba2417'], ['5edd5cc23c51e87a497ca815d5dce0f8ab52554f849ed8995de64c5f34ce7143', 'efae9c8dbc14130661e8cec030c89ad0c13c66c0d17a2905cdc706ab7399a868'], ['290798c2b6476830da12fe02287e9e777aa3fba1c355b17a722d362f84614fba', 'e38da76dcd440621988d00bcf79af25d5b29c094db2a23146d003afd41943e7a'], ['af3c423a95d9f5b3054754efa150ac39cd29552fe360257362dfdecef4053b45', 'f98a3fd831eb2b749a93b0e6f35cfb40c8cd5aa667a15581bc2feded498fd9c6'], ['766dbb24d134e745cccaa28c99bf274906bb66b26dcf98df8d2fed50d884249a', '744b1152eacbe5e38dcc887980da38b897584a65fa06cedd2c924f97cbac5996'], ['59dbf46f8c94759ba21277c33784f41645f7b44f6c596a58ce92e666191abe3e', 'c534ad44175fbc300f4ea6ce648309a042ce739a7919798cd85e216c4a307f6e'], ['f13ada95103c4537305e691e74e9a4a8dd647e711a95e73cb62dc6018cfd87b8', 'e13817b44ee14de663bf4bc808341f326949e21a6a75c2570778419bdaf5733d'], ['7754b4fa0e8aced06d4167a2c59cca4cda1869c06ebadfb6488550015a88522c', '30e93e864e669d82224b967c3020b8fa8d1e4e350b6cbcc537a48b57841163a2'], ['948dcadf5990e048aa3874d46abef9d701858f95de8041d2a6828c99e2262519', 'e491a42537f6e597d5d28a3224b1bc25df9154efbd2ef1d2cbba2cae5347d57e'], ['7962414450c76c1689c7b48f8202ec37fb224cf5ac0bfa1570328a8a3d7c77ab', '100b610ec4ffb4760d5c1fc133ef6f6b12507a051f04ac5760afa5b29db83437'], ['3514087834964b54b15b160644d915485a16977225b8847bb0dd085137ec47ca', 'ef0afbb2056205448e1652c48e8127fc6039e77c15c2378b7e7d15a0de293311'], ['d3cc30ad6b483e4bc79ce2c9dd8bc54993e947eb8df787b442943d3f7b527eaf', '8b378a22d827278d89c5e9be8f9508ae3c2ad46290358630afb34db04eede0a4'], ['1624d84780732860ce1c78fcbfefe08b2b29823db913f6493975ba0ff4847610', '68651cf9b6da903e0914448c6cd9d4ca896878f5282be4c8cc06e2a404078575'], ['733ce80da955a8a26902c95633e62a985192474b5af207da6df7b4fd5fc61cd4', 'f5435a2bd2badf7d485a4d8b8db9fcce3e1ef8e0201e4578c54673bc1dc5ea1d'], ['15d9441254945064cf1a1c33bbd3b49f8966c5092171e699ef258dfab81c045c', 'd56eb30b69463e7234f5137b73b84177434800bacebfc685fc37bbe9efe4070d'], ['a1d0fcf2ec9de675b612136e5ce70d271c21417c9d2b8aaaac138599d0717940', 'edd77f50bcb5a3cab2e90737309667f2641462a54070f3d519212d39c197a629'], ['e22fbe15c0af8ccc5780c0735f84dbe9a790badee8245c06c7ca37331cb36980', 'a855babad5cd60c88b430a69f53a1a7a38289154964799be43d06d77d31da06'], ['311091dd9860e8e20ee13473c1155f5f69635e394704eaa74009452246cfa9b3', '66db656f87d1f04fffd1f04788c06830871ec5a64feee685bd80f0b1286d8374'], ['34c1fd04d301be89b31c0442d3e6ac24883928b45a9340781867d4232ec2dbdf', '9414685e97b1b5954bd46f730174136d57f1ceeb487443dc5321857ba73abee'], ['f219ea5d6b54701c1c14de5b557eb42a8d13f3abbcd08affcc2a5e6b049b8d63', '4cb95957e83d40b0f73af4544cccf6b1f4b08d3c07b27fb8d8c2962a400766d1'], ['d7b8740f74a8fbaab1f683db8f45de26543a5490bca627087236912469a0b448', 'fa77968128d9c92ee1010f337ad4717eff15db5ed3c049b3411e0315eaa4593b'], ['32d31c222f8f6f0ef86f7c98d3a3335ead5bcd32abdd94289fe4d3091aa824bf', '5f3032f5892156e39ccd3d7915b9e1da2e6dac9e6f26e961118d14b8462e1661'], ['7461f371914ab32671045a155d9831ea8793d77cd59592c4340f86cbc18347b5', '8ec0ba238b96bec0cbdddcae0aa442542eee1ff50c986ea6b39847b3cc092ff6'], ['ee079adb1df1860074356a25aa38206a6d716b2c3e67453d287698bad7b2b2d6', '8dc2412aafe3be5c4c5f37e0ecc5f9f6a446989af04c4e25ebaac479ec1c8c1e'], ['16ec93e447ec83f0467b18302ee620f7e65de331874c9dc72bfd8616ba9da6b5', '5e4631150e62fb40d0e8c2a7ca5804a39d58186a50e497139626778e25b0674d'], ['eaa5f980c245f6f038978290afa70b6bd8855897f98b6aa485b96065d537bd99', 'f65f5d3e292c2e0819a528391c994624d784869d7e6ea67fb18041024edc07dc'], ['78c9407544ac132692ee1910a02439958ae04877151342ea96c4b6b35a49f51', 'f3e0319169eb9b85d5404795539a5e68fa1fbd583c064d2462b675f194a3ddb4'], ['494f4be219a1a77016dcd838431aea0001cdc8ae7a6fc688726578d9702857a5', '42242a969283a5f339ba7f075e36ba2af925ce30d767ed6e55f4b031880d562c'], ['a598a8030da6d86c6bc7f2f5144ea549d28211ea58faa70ebf4c1e665c1fe9b5', '204b5d6f84822c307e4b4a7140737aec23fc63b65b35f86a10026dbd2d864e6b'], ['c41916365abb2b5d09192f5f2dbeafec208f020f12570a184dbadc3e58595997', '4f14351d0087efa49d245b328984989d5caf9450f34bfc0ed16e96b58fa9913'], ['841d6063a586fa475a724604da03bc5b92a2e0d2e0a36acfe4c73a5514742881', '73867f59c0659e81904f9a1c7543698e62562d6744c169ce7a36de01a8d6154'], ['5e95bb399a6971d376026947f89bde2f282b33810928be4ded112ac4d70e20d5', '39f23f366809085beebfc71181313775a99c9aed7d8ba38b161384c746012865'], ['36e4641a53948fd476c39f8a99fd974e5ec07564b5315d8bf99471bca0ef2f66', 'd2424b1b1abe4eb8164227b085c9aa9456ea13493fd563e06fd51cf5694c78fc'], ['336581ea7bfbbb290c191a2f507a41cf5643842170e914faeab27c2c579f726', 'ead12168595fe1be99252129b6e56b3391f7ab1410cd1e0ef3dcdcabd2fda224'], ['8ab89816dadfd6b6a1f2634fcf00ec8403781025ed6890c4849742706bd43ede', '6fdcef09f2f6d0a044e654aef624136f503d459c3e89845858a47a9129cdd24e'], ['1e33f1a746c9c5778133344d9299fcaa20b0938e8acff2544bb40284b8c5fb94', '60660257dd11b3aa9c8ed618d24edff2306d320f1d03010e33a7d2057f3b3b6'], ['85b7c1dcb3cec1b7ee7f30ded79dd20a0ed1f4cc18cbcfcfa410361fd8f08f31', '3d98a9cdd026dd43f39048f25a8847f4fcafad1895d7a633c6fed3c35e999511'], ['29df9fbd8d9e46509275f4b125d6d45d7fbe9a3b878a7af872a2800661ac5f51', 'b4c4fe99c775a606e2d8862179139ffda61dc861c019e55cd2876eb2a27d84b'], ['a0b1cae06b0a847a3fea6e671aaf8adfdfe58ca2f768105c8082b2e449fce252', 'ae434102edde0958ec4b19d917a6a28e6b72da1834aff0e650f049503a296cf2'], ['4e8ceafb9b3e9a136dc7ff67e840295b499dfb3b2133e4ba113f2e4c0e121e5', 'cf2174118c8b6d7a4b48f6d534ce5c79422c086a63460502b827ce62a326683c'], ['d24a44e047e19b6f5afb81c7ca2f69080a5076689a010919f42725c2b789a33b', '6fb8d5591b466f8fc63db50f1c0f1c69013f996887b8244d2cdec417afea8fa3'], ['ea01606a7a6c9cdd249fdfcfacb99584001edd28abbab77b5104e98e8e3b35d4', '322af4908c7312b0cfbfe369f7a7b3cdb7d4494bc2823700cfd652188a3ea98d'], ['af8addbf2b661c8a6c6328655eb96651252007d8c5ea31be4ad196de8ce2131f', '6749e67c029b85f52a034eafd096836b2520818680e26ac8f3dfbcdb71749700'], ['e3ae1974566ca06cc516d47e0fb165a674a3dabcfca15e722f0e3450f45889', '2aeabe7e4531510116217f07bf4d07300de97e4874f81f533420a72eeb0bd6a4'], ['591ee355313d99721cf6993ffed1e3e301993ff3ed258802075ea8ced397e246', 'b0ea558a113c30bea60fc4775460c7901ff0b053d25ca2bdeee98f1a4be5d196'], ['11396d55fda54c49f19aa97318d8da61fa8584e47b084945077cf03255b52984', '998c74a8cd45ac01289d5833a7beb4744ff536b01b257be4c5767bea93ea57a4'], ['3c5d2a1ba39c5a1790000738c9e0c40b8dcdfd5468754b6405540157e017aa7a', 'b2284279995a34e2f9d4de7396fc18b80f9b8b9fdd270f6661f79ca4c81bd257'], ['cc8704b8a60a0defa3a99a7299f2e9c3fbc395afb04ac078425ef8a1793cc030', 'bdd46039feed17881d1e0862db347f8cf395b74fc4bcdc4e940b74e3ac1f1b13'], ['c533e4f7ea8555aacd9777ac5cad29b97dd4defccc53ee7ea204119b2889b197', '6f0a256bc5efdf429a2fb6242f1a43a2d9b925bb4a4b3a26bb8e0f45eb596096'], ['c14f8f2ccb27d6f109f6d08d03cc96a69ba8c34eec07bbcf566d48e33da6593', 'c359d6923bb398f7fd4473e16fe1c28475b740dd098075e6c0e8649113dc3a38'], ['a6cbc3046bc6a450bac24789fa17115a4c9739ed75f8f21ce441f72e0b90e6ef', '21ae7f4680e889bb130619e2c0f95a360ceb573c70603139862afd617fa9b9f'], ['347d6d9a02c48927ebfb86c1359b1caf130a3c0267d11ce6344b39f99d43cc38', '60ea7f61a353524d1c987f6ecec92f086d565ab687870cb12689ff1e31c74448'], ['da6545d2181db8d983f7dcb375ef5866d47c67b1bf31c8cf855ef7437b72656a', '49b96715ab6878a79e78f07ce5680c5d6673051b4935bd897fea824b77dc208a'], ['c40747cc9d012cb1a13b8148309c6de7ec25d6945d657146b9d5994b8feb1111', '5ca560753be2a12fc6de6caf2cb489565db936156b9514e1bb5e83037e0fa2d4'], ['4e42c8ec82c99798ccf3a610be870e78338c7f713348bd34c8203ef4037f3502', '7571d74ee5e0fb92a7a8b33a07783341a5492144cc54bcc40a94473693606437'], ['3775ab7089bc6af823aba2e1af70b236d251cadb0c86743287522a1b3b0dedea', 'be52d107bcfa09d8bcb9736a828cfa7fac8db17bf7a76a2c42ad961409018cf7'], ['cee31cbf7e34ec379d94fb814d3d775ad954595d1314ba8846959e3e82f74e26', '8fd64a14c06b589c26b947ae2bcf6bfa0149ef0be14ed4d80f448a01c43b1c6d'], ['b4f9eaea09b6917619f6ea6a4eb5464efddb58fd45b1ebefcdc1a01d08b47986', '39e5c9925b5a54b07433a4f18c61726f8bb131c012ca542eb24a8ac07200682a'], ['d4263dfc3d2df923a0179a48966d30ce84e2515afc3dccc1b77907792ebcc60e', '62dfaf07a0f78feb30e30d6295853ce189e127760ad6cf7fae164e122a208d54'], ['48457524820fa65a4f8d35eb6930857c0032acc0a4a2de422233eeda897612c4', '25a748ab367979d98733c38a1fa1c2e7dc6cc07db2d60a9ae7a76aaa49bd0f77'], ['dfeeef1881101f2cb11644f3a2afdfc2045e19919152923f367a1767c11cceda', 'ecfb7056cf1de042f9420bab396793c0c390bde74b4bbdff16a83ae09a9a7517'], ['6d7ef6b17543f8373c573f44e1f389835d89bcbc6062ced36c82df83b8fae859', 'cd450ec335438986dfefa10c57fea9bcc521a0959b2d80bbf74b190dca712d10'], ['e75605d59102a5a2684500d3b991f2e3f3c88b93225547035af25af66e04541f', 'f5c54754a8f71ee540b9b48728473e314f729ac5308b06938360990e2bfad125'], ['eb98660f4c4dfaa06a2be453d5020bc99a0c2e60abe388457dd43fefb1ed620c', '6cb9a8876d9cb8520609af3add26cd20a0a7cd8a9411131ce85f44100099223e'], ['13e87b027d8514d35939f2e6892b19922154596941888336dc3563e3b8dba942', 'fef5a3c68059a6dec5d624114bf1e91aac2b9da568d6abeb2570d55646b8adf1'], ['ee163026e9fd6fe017c38f06a5be6fc125424b371ce2708e7bf4491691e5764a', '1acb250f255dd61c43d94ccc670d0f58f49ae3fa15b96623e5430da0ad6c62b2'], ['b268f5ef9ad51e4d78de3a750c2dc89b1e626d43505867999932e5db33af3d80', '5f310d4b3c99b9ebb19f77d41c1dee018cf0d34fd4191614003e945a1216e423'], ['ff07f3118a9df035e9fad85eb6c7bfe42b02f01ca99ceea3bf7ffdba93c4750d', '438136d603e858a3a5c440c38eccbaddc1d2942114e2eddd4740d098ced1f0d8'], ['8d8b9855c7c052a34146fd20ffb658bea4b9f69e0d825ebec16e8c3ce2b526a1', 'cdb559eedc2d79f926baf44fb84ea4d44bcf50fee51d7ceb30e2e7f463036758'], ['52db0b5384dfbf05bfa9d472d7ae26dfe4b851ceca91b1eba54263180da32b63', 'c3b997d050ee5d423ebaf66a6db9f57b3180c902875679de924b69d84a7b375'], ['e62f9490d3d51da6395efd24e80919cc7d0f29c3f3fa48c6fff543becbd43352', '6d89ad7ba4876b0b22c2ca280c682862f342c8591f1daf5170e07bfd9ccafa7d'], ['7f30ea2476b399b4957509c88f77d0191afa2ff5cb7b14fd6d8e7d65aaab1193', 'ca5ef7d4b231c94c3b15389a5f6311e9daff7bb67b103e9880ef4bff637acaec'], ['5098ff1e1d9f14fb46a210fada6c903fef0fb7b4a1dd1d9ac60a0361800b7a00', '9731141d81fc8f8084d37c6e7542006b3ee1b40d60dfe5362a5b132fd17ddc0'], ['32b78c7de9ee512a72895be6b9cbefa6e2f3c4ccce445c96b9f2c81e2778ad58', 'ee1849f513df71e32efc3896ee28260c73bb80547ae2275ba497237794c8753c'], ['e2cb74fddc8e9fbcd076eef2a7c72b0ce37d50f08269dfc074b581550547a4f7', 'd3aa2ed71c9dd2247a62df062736eb0baddea9e36122d2be8641abcb005cc4a4'], ['8438447566d4d7bedadc299496ab357426009a35f235cb141be0d99cd10ae3a8', 'c4e1020916980a4da5d01ac5e6ad330734ef0d7906631c4f2390426b2edd791f'], ['4162d488b89402039b584c6fc6c308870587d9c46f660b878ab65c82c711d67e', '67163e903236289f776f22c25fb8a3afc1732f2b84b4e95dbda47ae5a0852649'], ['3fad3fa84caf0f34f0f89bfd2dcf54fc175d767aec3e50684f3ba4a4bf5f683d', 'cd1bc7cb6cc407bb2f0ca647c718a730cf71872e7d0d2a53fa20efcdfe61826'], ['674f2600a3007a00568c1a7ce05d0816c1fb84bf1370798f1c69532faeb1a86b', '299d21f9413f33b3edf43b257004580b70db57da0b182259e09eecc69e0d38a5'], ['d32f4da54ade74abb81b815ad1fb3b263d82d6c692714bcff87d29bd5ee9f08f', 'f9429e738b8e53b968e99016c059707782e14f4535359d582fc416910b3eea87'], ['30e4e670435385556e593657135845d36fbb6931f72b08cb1ed954f1e3ce3ff6', '462f9bce619898638499350113bbc9b10a878d35da70740dc695a559eb88db7b'], ['be2062003c51cc3004682904330e4dee7f3dcd10b01e580bf1971b04d4cad297', '62188bc49d61e5428573d48a74e1c655b1c61090905682a0d5558ed72dccb9bc'], ['93144423ace3451ed29e0fb9ac2af211cb6e84a601df5993c419859fff5df04a', '7c10dfb164c3425f5c71a3f9d7992038f1065224f72bb9d1d902a6d13037b47c'], ['b015f8044f5fcbdcf21ca26d6c34fb8197829205c7b7d2a7cb66418c157b112c', 'ab8c1e086d04e813744a655b2df8d5f83b3cdc6faa3088c1d3aea1454e3a1d5f'], ['d5e9e1da649d97d89e4868117a465a3a4f8a18de57a140d36b3f2af341a21b52', '4cb04437f391ed73111a13cc1d4dd0db1693465c2240480d8955e8592f27447a'], ['d3ae41047dd7ca065dbf8ed77b992439983005cd72e16d6f996a5316d36966bb', 'bd1aeb21ad22ebb22a10f0303417c6d964f8cdd7df0aca614b10dc14d125ac46'], ['463e2763d885f958fc66cdd22800f0a487197d0a82e377b49f80af87c897b065', 'bfefacdb0e5d0fd7df3a311a94de062b26b80c61fbc97508b79992671ef7ca7f'], ['7985fdfd127c0567c6f53ec1bb63ec3158e597c40bfe747c83cddfc910641917', '603c12daf3d9862ef2b25fe1de289aed24ed291e0ec6708703a5bd567f32ed03'], ['74a1ad6b5f76e39db2dd249410eac7f99e74c59cb83d2d0ed5ff1543da7703e9', 'cc6157ef18c9c63cd6193d83631bbea0093e0968942e8c33d5737fd790e0db08'], ['30682a50703375f602d416664ba19b7fc9bab42c72747463a71d0896b22f6da3', '553e04f6b018b4fa6c8f39e7f311d3176290d0e0f19ca73f17714d9977a22ff8'], ['9e2158f0d7c0d5f26c3791efefa79597654e7a2b2464f52b1ee6c1347769ef57', '712fcdd1b9053f09003a3481fa7762e9ffd7c8ef35a38509e2fbf2629008373'], ['176e26989a43c9cfeba4029c202538c28172e566e3c4fce7322857f3be327d66', 'ed8cc9d04b29eb877d270b4878dc43c19aefd31f4eee09ee7b47834c1fa4b1c3'], ['75d46efea3771e6e68abb89a13ad747ecf1892393dfc4f1b7004788c50374da8', '9852390a99507679fd0b86fd2b39a868d7efc22151346e1a3ca4726586a6bed8'], ['809a20c67d64900ffb698c4c825f6d5f2310fb0451c869345b7319f645605721', '9e994980d9917e22b76b061927fa04143d096ccc54963e6a5ebfa5f3f8e286c1'], ['1b38903a43f7f114ed4500b4eac7083fdefece1cf29c63528d563446f972c180', '4036edc931a60ae889353f77fd53de4a2708b26b6f5da72ad3394119daf408f9']] | |
} | |
}; | |
},{}],85:[function(require,module,exports){ | |
'use strict'; | |
var utils = exports; | |
var BN = require('bn.js'); | |
var minAssert = require('minimalistic-assert'); | |
var minUtils = require('minimalistic-crypto-utils'); | |
utils.assert = minAssert; | |
utils.toArray = minUtils.toArray; | |
utils.zero2 = minUtils.zero2; | |
utils.toHex = minUtils.toHex; | |
utils.encode = minUtils.encode; | |
// Represent num in a w-NAF form | |
function getNAF(num, w) { | |
var naf = []; | |
var ws = 1 << w + 1; | |
var k = num.clone(); | |
while (k.cmpn(1) >= 0) { | |
var z; | |
if (k.isOdd()) { | |
var mod = k.andln(ws - 1); | |
if (mod > (ws >> 1) - 1) z = (ws >> 1) - mod;else z = mod; | |
k.isubn(z); | |
} else { | |
z = 0; | |
} | |
naf.push(z); | |
// Optimization, shift by word if possible | |
var shift = k.cmpn(0) !== 0 && k.andln(ws - 1) === 0 ? w + 1 : 1; | |
for (var i = 1; i < shift; i++) { | |
naf.push(0); | |
}k.iushrn(shift); | |
} | |
return naf; | |
} | |
utils.getNAF = getNAF; | |
// Represent k1, k2 in a Joint Sparse Form | |
function getJSF(k1, k2) { | |
var jsf = [[], []]; | |
k1 = k1.clone(); | |
k2 = k2.clone(); | |
var d1 = 0; | |
var d2 = 0; | |
while (k1.cmpn(-d1) > 0 || k2.cmpn(-d2) > 0) { | |
// First phase | |
var m14 = k1.andln(3) + d1 & 3; | |
var m24 = k2.andln(3) + d2 & 3; | |
if (m14 === 3) m14 = -1; | |
if (m24 === 3) m24 = -1; | |
var u1; | |
if ((m14 & 1) === 0) { | |
u1 = 0; | |
} else { | |
var m8 = k1.andln(7) + d1 & 7; | |
if ((m8 === 3 || m8 === 5) && m24 === 2) u1 = -m14;else u1 = m14; | |
} | |
jsf[0].push(u1); | |
var u2; | |
if ((m24 & 1) === 0) { | |
u2 = 0; | |
} else { | |
var m8 = k2.andln(7) + d2 & 7; | |
if ((m8 === 3 || m8 === 5) && m14 === 2) u2 = -m24;else u2 = m24; | |
} | |
jsf[1].push(u2); | |
// Second phase | |
if (2 * d1 === u1 + 1) d1 = 1 - d1; | |
if (2 * d2 === u2 + 1) d2 = 1 - d2; | |
k1.iushrn(1); | |
k2.iushrn(1); | |
} | |
return jsf; | |
} | |
utils.getJSF = getJSF; | |
function cachedProperty(obj, name, computer) { | |
var key = '_' + name; | |
obj.prototype[name] = function cachedProperty() { | |
return this[key] !== undefined ? this[key] : this[key] = computer.call(this); | |
}; | |
} | |
utils.cachedProperty = cachedProperty; | |
function parseBytes(bytes) { | |
return typeof bytes === 'string' ? utils.toArray(bytes, 'hex') : bytes; | |
} | |
utils.parseBytes = parseBytes; | |
function intFromLE(bytes) { | |
return new BN(bytes, 'hex', 'le'); | |
} | |
utils.intFromLE = intFromLE; | |
},{"bn.js":99,"minimalistic-assert":271,"minimalistic-crypto-utils":272}],86:[function(require,module,exports){ | |
module.exports={ | |
"_from": "elliptic@=6.4.0", | |
"_id": "elliptic@6.4.0", | |
"_inBundle": false, | |
"_integrity": "sha1-ysmvh2LIWDYYcAPI3+GT5eLq5d8=", | |
"_location": "/bitcore-lib/elliptic", | |
"_phantomChildren": {}, | |
"_requested": { | |
"type": "version", | |
"registry": true, | |
"raw": "elliptic@=6.4.0", | |
"name": "elliptic", | |
"escapedName": "elliptic", | |
"rawSpec": "=6.4.0", | |
"saveSpec": null, | |
"fetchSpec": "=6.4.0" | |
}, | |
"_requiredBy": [ | |
"/bitcore-lib" | |
], | |
"_resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.0.tgz", | |
"_shasum": "cac9af8762c85836187003c8dfe193e5e2eae5df", | |
"_spec": "elliptic@=6.4.0", | |
"_where": "/home/chris/dev/eth-lightwallet/node_modules/bitcore-lib", | |
"author": { | |
"name": "Fedor Indutny", | |
"email": "fedor@indutny.com" | |
}, | |
"bugs": { | |
"url": "https://github.com/indutny/elliptic/issues" | |
}, | |
"bundleDependencies": false, | |
"dependencies": { | |
"bn.js": "^4.4.0", | |
"brorand": "^1.0.1", | |
"hash.js": "^1.0.0", | |
"hmac-drbg": "^1.0.0", | |
"inherits": "^2.0.1", | |
"minimalistic-assert": "^1.0.0", | |
"minimalistic-crypto-utils": "^1.0.0" | |
}, | |
"deprecated": false, | |
"description": "EC cryptography", | |
"devDependencies": { | |
"brfs": "^1.4.3", | |
"coveralls": "^2.11.3", | |
"grunt": "^0.4.5", | |
"grunt-browserify": "^5.0.0", | |
"grunt-cli": "^1.2.0", | |
"grunt-contrib-connect": "^1.0.0", | |
"grunt-contrib-copy": "^1.0.0", | |
"grunt-contrib-uglify": "^1.0.1", | |
"grunt-mocha-istanbul": "^3.0.1", | |
"grunt-saucelabs": "^8.6.2", | |
"istanbul": "^0.4.2", | |
"jscs": "^2.9.0", | |
"jshint": "^2.6.0", | |
"mocha": "^2.1.0" | |
}, | |
"files": [ | |
"lib" | |
], | |
"homepage": "https://github.com/indutny/elliptic", | |
"keywords": [ | |
"EC", | |
"Elliptic", | |
"curve", | |
"Cryptography" | |
], | |
"license": "MIT", | |
"main": "lib/elliptic.js", | |
"name": "elliptic", | |
"repository": { | |
"type": "git", | |
"url": "git+ssh://git@github.com/indutny/elliptic.git" | |
}, | |
"scripts": { | |
"jscs": "jscs benchmarks/*.js lib/*.js lib/**/*.js lib/**/**/*.js test/index.js", | |
"jshint": "jscs benchmarks/*.js lib/*.js lib/**/*.js lib/**/**/*.js test/index.js", | |
"lint": "npm run jscs && npm run jshint", | |
"test": "npm run lint && npm run unit", | |
"unit": "istanbul test _mocha --reporter=spec test/index.js", | |
"version": "grunt dist && git add dist/" | |
}, | |
"version": "6.4.0" | |
} | |
},{}],87:[function(require,module,exports){ | |
module.exports={ | |
"_from": "bitcore-lib@^0.15.0", | |
"_id": "bitcore-lib@0.15.0", | |
"_inBundle": false, | |
"_integrity": "sha512-AeXLWhiivF6CDFzrABZHT4jJrflyylDWTi32o30rF92HW9msfuKpjzrHtFKYGa9w0kNVv5HABQjCB3OEav4PhQ==", | |
"_location": "/bitcore-lib", | |
"_phantomChildren": { | |
"bn.js": "4.11.8", | |
"brorand": "1.1.0", | |
"hash.js": "1.1.3", | |
"hmac-drbg": "1.0.1", | |
"inherits": "2.0.1", | |
"minimalistic-assert": "1.0.0", | |
"minimalistic-crypto-utils": "1.0.1" | |
}, | |
"_requested": { | |
"type": "range", | |
"registry": true, | |
"raw": "bitcore-lib@^0.15.0", | |
"name": "bitcore-lib", | |
"escapedName": "bitcore-lib", | |
"rawSpec": "^0.15.0", | |
"saveSpec": null, | |
"fetchSpec": "^0.15.0" | |
}, | |
"_requiredBy": [ | |
"/", | |
"/bitcore-mnemonic" | |
], | |
"_resolved": "https://registry.npmjs.org/bitcore-lib/-/bitcore-lib-0.15.0.tgz", | |
"_shasum": "f924be13869f2aab7e04aeec5642ad3359b6cec2", | |
"_spec": "bitcore-lib@^0.15.0", | |
"_where": "/home/chris/dev/eth-lightwallet", | |
"author": { | |
"name": "BitPay", | |
"email": "dev@bitpay.com" | |
}, | |
"browser": { | |
"request": "browser-request" | |
}, | |
"bugs": { | |
"url": "https://github.com/bitpay/bitcore-lib/issues" | |
}, | |
"bundleDependencies": false, | |
"dependencies": { | |
"bn.js": "=4.11.8", | |
"bs58": "=4.0.1", | |
"buffer-compare": "=1.1.1", | |
"elliptic": "=6.4.0", | |
"inherits": "=2.0.1", | |
"lodash": "=4.17.4" | |
}, | |
"deprecated": false, | |
"description": "A pure and powerful JavaScript Bitcoin library.", | |
"devDependencies": { | |
"bitcore-build": "git+https://github.com/bitpay/bitcore-build.git#d4e8b2b2f1e2c065c3a807dcb6a6250f61d67ab3", | |
"brfs": "^1.2.0", | |
"chai": "^1.10.0", | |
"gulp": "^3.8.10", | |
"sinon": "^1.13.0" | |
}, | |
"homepage": "https://github.com/bitpay/bitcore-lib#readme", | |
"keywords": [ | |
"bitcoin", | |
"transaction", | |
"address", | |
"p2p", | |
"ecies", | |
"cryptocurrency", | |
"blockchain", | |
"payment", | |
"bip21", | |
"bip32", | |
"bip37", | |
"bip69", | |
"bip70", | |
"multisig" | |
], | |
"license": "MIT", | |
"main": "index.js", | |
"name": "bitcore-lib", | |
"repository": { | |
"type": "git", | |
"url": "git+https://github.com/bitpay/bitcore-lib.git" | |
}, | |
"scripts": { | |
"build": "gulp", | |
"coverage": "gulp coverage", | |
"lint": "gulp lint", | |
"test": "gulp test" | |
}, | |
"version": "0.15.0" | |
} | |
},{}],88:[function(require,module,exports){ | |
'use strict'; | |
module.exports = require('./lib/mnemonic'); | |
},{"./lib/mnemonic":90}],89:[function(require,module,exports){ | |
'use strict'; | |
var spec = { | |
name: 'Mnemonic', | |
message: 'Internal Error on bitcore-mnemonic module {0}', | |
errors: [{ | |
name: 'InvalidEntropy', | |
message: 'Entropy length must be an even multiple of 11 bits: {0}' | |
}, { | |
name: 'UnknownWordlist', | |
message: 'Could not detect the used word list: {0}' | |
}, { | |
name: 'InvalidMnemonic', | |
message: 'Mnemonic string is invalid: {0}' | |
}] | |
}; | |
module.exports = require('bitcore-lib').errors.extend(spec); | |
},{"bitcore-lib":26}],90:[function(require,module,exports){ | |
(function (Buffer){ | |
'use strict'; | |
var bitcore = require('bitcore-lib'); | |
var BN = bitcore.crypto.BN; | |
var unorm = require('unorm'); | |
var _ = bitcore.deps._; | |
var pbkdf2 = require('./pbkdf2'); | |
var errors = require('./errors'); | |
var Hash = bitcore.crypto.Hash; | |
var Random = bitcore.crypto.Random; | |
var $ = bitcore.util.preconditions; | |
/** | |
* This is an immutable class that represents a BIP39 Mnemonic code. | |
* See BIP39 specification for more info: https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki | |
* A Mnemonic code is a a group of easy to remember words used for the generation | |
* of deterministic wallets. A Mnemonic can be used to generate a seed using | |
* an optional passphrase, for later generate a HDPrivateKey. | |
* | |
* @example | |
* // generate a random mnemonic | |
* var mnemonic = new Mnemonic(); | |
* var phrase = mnemonic.phrase; | |
* | |
* // use a different language | |
* var mnemonic = new Mnemonic(Mnemonic.Words.SPANISH); | |
* var xprivkey = mnemonic.toHDPrivateKey(); | |
* | |
* @param {*=} data - a seed, phrase, or entropy to initialize (can be skipped) | |
* @param {Array=} wordlist - the wordlist to generate mnemonics from | |
* @returns {Mnemonic} A new instance of Mnemonic | |
* @constructor | |
*/ | |
var Mnemonic = function Mnemonic(data, wordlist) { | |
if (!(this instanceof Mnemonic)) { | |
return new Mnemonic(data, wordlist); | |
} | |
if (_.isArray(data)) { | |
wordlist = data; | |
data = null; | |
} | |
// handle data overloading | |
var ent, phrase, seed; | |
if (Buffer.isBuffer(data)) { | |
seed = data; | |
} else if (_.isString(data)) { | |
phrase = unorm.nfkd(data); | |
} else if (_.isNumber(data)) { | |
ent = data; | |
} else if (data) { | |
throw new bitcore.errors.InvalidArgument('data', 'Must be a Buffer, a string or an integer'); | |
} | |
ent = ent || 128; | |
// check and detect wordlist | |
wordlist = wordlist || Mnemonic._getDictionary(phrase); | |
if (phrase && !wordlist) { | |
throw new errors.UnknownWordlist(phrase); | |
} | |
wordlist = wordlist || Mnemonic.Words.ENGLISH; | |
if (seed) { | |
phrase = Mnemonic._entropy2mnemonic(seed, wordlist); | |
} | |
// validate phrase and ent | |
if (phrase && !Mnemonic.isValid(phrase, wordlist)) { | |
throw new errors.InvalidMnemonic(phrase); | |
} | |
if (ent % 32 !== 0 || ent < 128) { | |
throw new bitcore.errors.InvalidArgument('ENT', 'Values must be ENT > 128 and ENT % 32 == 0'); | |
} | |
phrase = phrase || Mnemonic._mnemonic(ent, wordlist); | |
Object.defineProperty(this, 'wordlist', { | |
configurable: false, | |
value: wordlist | |
}); | |
Object.defineProperty(this, 'phrase', { | |
configurable: false, | |
value: phrase | |
}); | |
}; | |
Mnemonic.Words = require('./words'); | |
/** | |
* Will return a boolean if the mnemonic is valid | |
* | |
* @example | |
* | |
* var valid = Mnemonic.isValid('lab rescue lunch elbow recall phrase perfect donkey biology guess moment husband'); | |
* // true | |
* | |
* @param {String} mnemonic - The mnemonic string | |
* @param {String} [wordlist] - The wordlist used | |
* @returns {boolean} | |
*/ | |
Mnemonic.isValid = function (mnemonic, wordlist) { | |
mnemonic = unorm.nfkd(mnemonic); | |
wordlist = wordlist || Mnemonic._getDictionary(mnemonic); | |
if (!wordlist) { | |
return false; | |
} | |
var words = mnemonic.split(' '); | |
var bin = ''; | |
for (var i = 0; i < words.length; i++) { | |
var ind = wordlist.indexOf(words[i]); | |
if (ind < 0) return false; | |
bin = bin + ('00000000000' + ind.toString(2)).slice(-11); | |
} | |
var cs = bin.length / 33; | |
var hash_bits = bin.slice(-cs); | |
var nonhash_bits = bin.slice(0, bin.length - cs); | |
var buf = new Buffer(nonhash_bits.length / 8); | |
for (i = 0; i < nonhash_bits.length / 8; i++) { | |
buf.writeUInt8(parseInt(bin.slice(i * 8, (i + 1) * 8), 2), i); | |
} | |
var expected_hash_bits = Mnemonic._entropyChecksum(buf); | |
return expected_hash_bits === hash_bits; | |
}; | |
/** | |
* Internal function to check if a mnemonic belongs to a wordlist. | |
* | |
* @param {String} mnemonic - The mnemonic string | |
* @param {String} wordlist - The wordlist | |
* @returns {boolean} | |
*/ | |
Mnemonic._belongsToWordlist = function (mnemonic, wordlist) { | |
var words = unorm.nfkd(mnemonic).split(' '); | |
for (var i = 0; i < words.length; i++) { | |
var ind = wordlist.indexOf(words[i]); | |
if (ind < 0) return false; | |
} | |
return true; | |
}; | |
/** | |
* Internal function to detect the wordlist used to generate the mnemonic. | |
* | |
* @param {String} mnemonic - The mnemonic string | |
* @returns {Array} the wordlist or null | |
*/ | |
Mnemonic._getDictionary = function (mnemonic) { | |
if (!mnemonic) return null; | |
var dicts = Object.keys(Mnemonic.Words); | |
for (var i = 0; i < dicts.length; i++) { | |
var key = dicts[i]; | |
if (Mnemonic._belongsToWordlist(mnemonic, Mnemonic.Words[key])) { | |
return Mnemonic.Words[key]; | |
} | |
} | |
return null; | |
}; | |
/** | |
* Will generate a seed based on the mnemonic and optional passphrase. | |
* | |
* @param {String} [passphrase] | |
* @returns {Buffer} | |
*/ | |
Mnemonic.prototype.toSeed = function (passphrase) { | |
passphrase = passphrase || ''; | |
return pbkdf2(unorm.nfkd(this.phrase), unorm.nfkd('mnemonic' + passphrase), 2048, 64); | |
}; | |
/** | |
* Will generate a Mnemonic object based on a seed. | |
* | |
* @param {Buffer} [seed] | |
* @param {string} [wordlist] | |
* @returns {Mnemonic} | |
*/ | |
Mnemonic.fromSeed = function (seed, wordlist) { | |
$.checkArgument(Buffer.isBuffer(seed), 'seed must be a Buffer.'); | |
$.checkArgument(_.isArray(wordlist) || _.isString(wordlist), 'wordlist must be a string or an array.'); | |
return new Mnemonic(seed, wordlist); | |
}; | |
/** | |
* | |
* Generates a HD Private Key from a Mnemonic. | |
* Optionally receive a passphrase and bitcoin network. | |
* | |
* @param {String=} [passphrase] | |
* @param {Network|String|number=} [network] - The network: 'livenet' or 'testnet' | |
* @returns {HDPrivateKey} | |
*/ | |
Mnemonic.prototype.toHDPrivateKey = function (passphrase, network) { | |
var seed = this.toSeed(passphrase); | |
return bitcore.HDPrivateKey.fromSeed(seed, network); | |
}; | |
/** | |
* Will return a the string representation of the mnemonic | |
* | |
* @returns {String} Mnemonic | |
*/ | |
Mnemonic.prototype.toString = function () { | |
return this.phrase; | |
}; | |
/** | |
* Will return a string formatted for the console | |
* | |
* @returns {String} Mnemonic | |
*/ | |
Mnemonic.prototype.inspect = function () { | |
return '<Mnemonic: ' + this.toString() + ' >'; | |
}; | |
/** | |
* Internal function to generate a random mnemonic | |
* | |
* @param {Number} ENT - Entropy size, defaults to 128 | |
* @param {Array} wordlist - Array of words to generate the mnemonic | |
* @returns {String} Mnemonic string | |
*/ | |
Mnemonic._mnemonic = function (ENT, wordlist) { | |
var buf = Random.getRandomBuffer(ENT / 8); | |
return Mnemonic._entropy2mnemonic(buf, wordlist); | |
}; | |
/** | |
* Internal function to generate mnemonic based on entropy | |
* | |
* @param {Number} entropy - Entropy buffer | |
* @param {Array} wordlist - Array of words to generate the mnemonic | |
* @returns {String} Mnemonic string | |
*/ | |
Mnemonic._entropy2mnemonic = function (entropy, wordlist) { | |
var bin = ''; | |
for (var i = 0; i < entropy.length; i++) { | |
bin = bin + ('00000000' + entropy[i].toString(2)).slice(-8); | |
} | |
bin = bin + Mnemonic._entropyChecksum(entropy); | |
if (bin.length % 11 !== 0) { | |
throw new errors.InvalidEntropy(bin); | |
} | |
var mnemonic = []; | |
for (i = 0; i < bin.length / 11; i++) { | |
var wi = parseInt(bin.slice(i * 11, (i + 1) * 11), 2); | |
mnemonic.push(wordlist[wi]); | |
} | |
var ret; | |
if (wordlist === Mnemonic.Words.JAPANESE) { | |
ret = mnemonic.join('\u3000'); | |
} else { | |
ret = mnemonic.join(' '); | |
} | |
return ret; | |
}; | |
/** | |
* Internal function to create checksum of entropy | |
* | |
* @param entropy | |
* @returns {string} Checksum of entropy length / 32 | |
* @private | |
*/ | |
Mnemonic._entropyChecksum = function (entropy) { | |
var hash = Hash.sha256(entropy); | |
var bits = entropy.length * 8; | |
var cs = bits / 32; | |
var hashbits = new BN(hash.toString('hex'), 16).toString(2); | |
// zero pad the hash bits | |
while (hashbits.length % 256 !== 0) { | |
hashbits = '0' + hashbits; | |
} | |
var checksum = hashbits.slice(0, cs); | |
return checksum; | |
}; | |
Mnemonic.bitcore = bitcore; | |
module.exports = Mnemonic; | |
}).call(this,require("buffer").Buffer) | |
},{"./errors":89,"./pbkdf2":91,"./words":95,"bitcore-lib":26,"buffer":148,"unorm":350}],91:[function(require,module,exports){ | |
(function (Buffer){ | |
'use strict'; | |
var crypto = require("crypto"); | |
/** | |
* PDKBF2 | |
* Credit to: https://github.com/stayradiated/pbkdf2-sha512 | |
* Copyright (c) 2014, JP Richardson Copyright (c) 2010-2011 Intalio Pte, All Rights Reserved | |
*/ | |
function pbkdf2(key, salt, iterations, dkLen) { | |
/* jshint maxstatements: 31 */ | |
/* jshint maxcomplexity: 9 */ | |
var hLen = 64; //SHA512 Mac length | |
if (dkLen > (Math.pow(2, 32) - 1) * hLen) { | |
throw Error('Requested key length too long'); | |
} | |
if (typeof key !== 'string' && !Buffer.isBuffer(key)) { | |
throw new TypeError('key must a string or Buffer'); | |
} | |
if (typeof salt !== 'string' && !Buffer.isBuffer(salt)) { | |
throw new TypeError('salt must a string or Buffer'); | |
} | |
if (typeof key === 'string') { | |
key = new Buffer(key); | |
} | |
if (typeof salt === 'string') { | |
salt = new Buffer(salt); | |
} | |
var DK = new Buffer(dkLen); | |
var U = new Buffer(hLen); | |
var T = new Buffer(hLen); | |
var block1 = new Buffer(salt.length + 4); | |
var l = Math.ceil(dkLen / hLen); | |
var r = dkLen - (l - 1) * hLen; | |
salt.copy(block1, 0, 0, salt.length); | |
for (var i = 1; i <= l; i++) { | |
block1[salt.length + 0] = i >> 24 & 0xff; | |
block1[salt.length + 1] = i >> 16 & 0xff; | |
block1[salt.length + 2] = i >> 8 & 0xff; | |
block1[salt.length + 3] = i >> 0 & 0xff; | |
U = crypto.createHmac('sha512', key).update(block1).digest(); | |
U.copy(T, 0, 0, hLen); | |
for (var j = 1; j < iterations; j++) { | |
U = crypto.createHmac('sha512', key).update(U).digest(); | |
for (var k = 0; k < hLen; k++) { | |
T[k] ^= U[k]; | |
} | |
} | |
var destPos = (i - 1) * hLen; | |
var len = i === l ? r : hLen; | |
T.copy(DK, destPos, 0, len); | |
} | |
return DK; | |
} | |
module.exports = pbkdf2; | |
}).call(this,require("buffer").Buffer) | |
},{"buffer":148,"crypto":173}],92:[function(require,module,exports){ | |
'use strict'; | |
var chinese = ['的', '一', '是', '在', '不', '了', '有', '和', '人', '这', '中', '大', '为', '上', '个', '国', '我', '以', '要', '他', '时', '来', '用', '们', '生', '到', '作', '地', '于', '出', '就', '分', '对', '成', '会', '可', '主', '发', '年', '动', '同', '工', '也', '能', '下', '过', '子', '说', '产', '种', '面', '而', '方', '后', '多', '定', '行', '学', '法', '所', '民', '得', '经', '十', '三', '之', '进', '着', '等', '部', '度', '家', '电', '力', '里', '如', '水', '化', '高', '自', '二', '理', '起', '小', '物', '现', '实', '加', '量', '都', '两', '体', '制', '机', '当', '使', '点', '从', '业', '本', '去', '把', '性', '好', '应', '开', '它', '合', '还', '因', '由', '其', '些', '然', '前', '外', '天', '政', '四', '日', '那', '社', '义', '事', '平', '形', '相', '全', '表', '间', '样', '与', '关', '各', '重', '新', '线', '内', '数', '正', '心', '反', '你', '明', '看', '原', '又', '么', '利', '比', '或', '但', '质', '气', '第', '向', '道', '命', '此', '变', '条', '只', '没', '结', '解', '问', '意', '建', '月', '公', '无', '系', '军', '很', '情', '者', '最', '立', '代', '想', '已', '通', '并', '提', '直', '题', '党', '程', '展', '五', '果', '料', '象', '员', '革', '位', '入', '常', '文', '总', '次', '品', '式', '活', '设', '及', '管', '特', '件', '长', '求', '老', '头', '基', '资', '边', '流', '路', '级', '少', '图', '山', '统', '接', '知', '较', '将', '组', '见', '计', '别', '她', '手', '角', '期', '根', '论', '运', '农', '指', '几', '九', '区', '强', '放', '决', '西', '被', '干', '做', '必', '战', '先', '回', '则', '任', '取', '据', '处', '队', '南', '给', '色', '光', '门', '即', '保', '治', '北', '造', '百', '规', '热', '领', '七', '海', '口', '东', '导', '器', '压', '志', '世', '金', '增', '争', '济', '阶', '油', '思', '术', '极', '交', '受', '联', '什', '认', '六', '共', '权', '收', '证', '改', '清', '美', '再', '采', '转', '更', '单', '风', '切', '打', '白', '教', '速', '花', '带', '安', '场', '身', '车', '例', '真', '务', '具', '万', '每', '目', '至', '达', '走', '积', '示', '议', '声', '报', '斗', '完', '类', '八', '离', '华', '名', '确', '才', '科', '张', '信', '马', '节', '话', '米', '整', '空', '元', '况', '今', '集', '温', '传', '土', '许', '步', '群', '广', '石', '记', '需', '段', '研', '界', '拉', '林', '律', '叫', '且', '究', '观', '越', '织', '装', '影', '算', '低', '持', '音', '众', '书', '布', '复', '容', '儿', '须', '际', '商', '非', '验', '连', '断', '深', '难', '近', '矿', '千', '周', '委', '素', '技', '备', '半', '办', '青', '省', '列', '习', '响', '约', '支', '般', '史', '感', '劳', '便', '团', '往', '酸', '历', '市', '克', '何', '除', '消', '构', '府', '称', '太', '准', '精', '值', '号', '率', '族', '维', '划', '选', '标', '写', '存', '候', '毛', '亲', '快', '效', '斯', '院', '查', '江', '型', '眼', '王', '按', '格', '养', '易', '置', '派', '层', '片', '始', '却', '专', '状', '育', '厂', '京', '识', '适', '属', '圆', '包', '火', '住', '调', '满', '县', '局', '照', '参', '红', '细', '引', '听', '该', '铁', '价', '严', '首', '底', '液', '官', '德', '随', '病', '苏', '失', '尔', '死', '讲', '配', '女', '黄', '推', '显', '谈', '罪', '神', '艺', '呢', '席', '含', '企', '望', '密', '批', '营', '项', '防', '举', '球', '英', '氧', '势', '告', '李', '台', '落', '木', '帮', '轮', '破', '亚', '师', '围', '注', '远', '字', '材', '排', '供', '河', '态', '封', '另', '施', '减', '树', '溶', '怎', '止', '案', '言', '士', '均', '武', '固', '叶', '鱼', '波', '视', '仅', '费', '紧', '爱', '左', '章', '早', '朝', '害', '续', '轻', '服', '试', '食', '充', '兵', '源', '判', '护', '司', '足', '某', '练', '差', '致', '板', '田', '降', '黑', '犯', '负', '击', '范', '继', '兴', '似', '余', '坚', '曲', '输', '修', '故', '城', '夫', '够', '送', '笔', '船', '占', '右', '财', '吃', '富', '春', '职', '觉', '汉', '画', '功', '巴', '跟', '虽', '杂', '飞', '检', '吸', '助', '升', '阳', '互', '初', '创', '抗', '考', '投', '坏', '策', '古', '径', '换', '未', '跑', '留', '钢', '曾', '端', '责', '站', '简', '述', '钱', '副', '尽', '帝', '射', '草', '冲', '承', '独', '令', '限', '阿', '宣', '环', '双', '请', '超', '微', '让', '控', '州', '良', '轴', '找', '否', '纪', '益', '依', '优', '顶', '础', '载', '倒', '房', '突', '坐', '粉', '敌', '略', '客', '袁', '冷', '胜', '绝', '析', '块', '剂', '测', '丝', '协', '诉', '念', '陈', '仍', '罗', '盐', '友', '洋', '错', '苦', '夜', '刑', '移', '频', '逐', '靠', '混', '母', '短', '皮', '终', '聚', '汽', '村', '云', '哪', '既', '距', '卫', '停', '烈', '央', '察', '烧', '迅', '境', '若', '印', '洲', '刻', '括', '激', '孔', '搞', '甚', '室', '待', '核', '校', '散', '侵', '吧', '甲', '游', '久', '菜', '味', '旧', '模', '湖', '货', '损', '预', '阻', '毫', '普', '稳', '乙', '妈', '植', '息', '扩', '银', '语', '挥', '酒', '守', '拿', '序', '纸', '医', '缺', '雨', '吗', '针', '刘', '啊', '急', '唱', '误', '训', '愿', '审', '附', '获', '茶', '鲜', '粮', '斤', '孩', '脱', '硫', '肥', '善', '龙', '演', '父', '渐', '血', '欢', '械', '掌', '歌', '沙', '刚', '攻', '谓', '盾', '讨', '晚', '粒', '乱', '燃', '矛', '乎', '杀', '药', '宁', '鲁', '贵', '钟', '煤', '读', '班', '伯', '香', '介', '迫', '句', '丰', '培', '握', '兰', '担', '弦', '蛋', '沉', '假', '穿', '执', '答', '乐', '谁', '顺', '烟', '缩', '征', '脸', '喜', '松', '脚', '困', '异', '免', '背', '星', '福', '买', '染', '井', '概', '慢', '怕', '磁', '倍', '祖', '皇', '促', '静', '补', '评', '翻', '肉', '践', '尼', '衣', '宽', '扬', '棉', '希', '伤', '操', '垂', '秋', '宜', '氢', '套', '督', '振', '架', '亮', '末', '宪', '庆', '编', '牛', '触', '映', '雷', '销', '诗', '座', '居', '抓', '裂', '胞', '呼', '娘', '景', '威', '绿', '晶', '厚', '盟', '衡', '鸡', '孙', '延', '危', '胶', '屋', '乡', '临', '陆', '顾', '掉', '呀', '灯', '岁', '措', '束', '耐', '剧', '玉', '赵', '跳', '哥', '季', '课', '凯', '胡', '额', '款', '绍', '卷', '齐', '伟', '蒸', '殖', '永', '宗', '苗', '川', '炉', '岩', '弱', '零', '杨', '奏', '沿', '露', '杆', '探', '滑', '镇', '饭', '浓', '航', '怀', '赶', '库', '夺', '伊', '灵', '税', '途', '灭', '赛', '归', '召', '鼓', '播', '盘', '裁', '险', '康', '唯', '录', '菌', '纯', '借', '糖', '盖', '横', '符', '私', '努', '堂', '域', '枪', '润', '幅', '哈', '竟', '熟', '虫', '泽', '脑', '壤', '碳', '欧', '遍', '侧', '寨', '敢', '彻', '虑', '斜', '薄', '庭', '纳', '弹', '饲', '伸', '折', '麦', '湿', '暗', '荷', '瓦', '塞', '床', '筑', '恶', '户', '访', '塔', '奇', '透', '梁', '刀', '旋', '迹', '卡', '氯', '遇', '份', '毒', '泥', '退', '洗', '摆', '灰', '彩', '卖', '耗', '夏', '择', '忙', '铜', '献', '硬', '予', '繁', '圈', '雪', '函', '亦', '抽', '篇', '阵', '阴', '丁', '尺', '追', '堆', '雄', '迎', '泛', '爸', '楼', '避', '谋', '吨', '野', '猪', '旗', '累', '偏', '典', '馆', '索', '秦', '脂', '潮', '爷', '豆', '忽', '托', '惊', '塑', '遗', '愈', '朱', '替', '纤', '粗', '倾', '尚', '痛', '楚', '谢', '奋', '购', '磨', '君', '池', '旁', '碎', '骨', '监', '捕', '弟', '暴', '割', '贯', '殊', '释', '词', '亡', '壁', '顿', '宝', '午', '尘', '闻', '揭', '炮', '残', '冬', '桥', '妇', '警', '综', '招', '吴', '付', '浮', '遭', '徐', '您', '摇', '谷', '赞', '箱', '隔', '订', '男', '吹', '园', '纷', '唐', '败', '宋', '玻', '巨', '耕', '坦', '荣', '闭', '湾', '键', '凡', '驻', '锅', '救', '恩', '剥', '凝', '碱', '齿', '截', '炼', '麻', '纺', '禁', '废', '盛', '版', '缓', '净', '睛', '昌', '婚', '涉', '筒', '嘴', '插', '岸', '朗', '庄', '街', '藏', '姑', '贸', '腐', '奴', '啦', '惯', '乘', '伙', '恢', '匀', '纱', '扎', '辩', '耳', '彪', '臣', '亿', '璃', '抵', '脉', '秀', '萨', '俄', '网', '舞', '店', '喷', '纵', '寸', '汗', '挂', '洪', '贺', '闪', '柬', '爆', '烯', '津', '稻', '墙', '软', '勇', '像', '滚', '厘', '蒙', '芳', '肯', '坡', '柱', '荡', '腿', '仪', '旅', '尾', '轧', '冰', '贡', '登', '黎', '削', '钻', '勒', '逃', '障', '氨', '郭', '峰', '币', '港', '伏', '轨', '亩', '毕', '擦', '莫', '刺', '浪', '秘', '援', '株', '健', '售', '股', '岛', '甘', '泡', '睡', '童', '铸', '汤', '阀', '休', '汇', '舍', '牧', '绕', '炸', '哲', '磷', '绩', '朋', '淡', '尖', '启', '陷', '柴', '呈', '徒', '颜', '泪', '稍', '忘', '泵', '蓝', '拖', '洞', '授', '镜', '辛', '壮', '锋', '贫', '虚', '弯', '摩', '泰', '幼', '廷', '尊', '窗', '纲', '弄', '隶', '疑', '氏', '宫', '姐', '震', '瑞', '怪', '尤', '琴', '循', '描', '膜', '违', '夹', '腰', '缘', '珠', '穷', '森', '枝', '竹', '沟', '催', '绳', '忆', '邦', '剩', '幸', '浆', '栏', '拥', '牙', '贮', '礼', '滤', '钠', '纹', '罢', '拍', '咱', '喊', '袖', '埃', '勤', '罚', '焦', '潜', '伍', '墨', '欲', '缝', '姓', '刊', '饱', '仿', '奖', '铝', '鬼', '丽', '跨', '默', '挖', '链', '扫', '喝', '袋', '炭', '污', '幕', '诸', '弧', '励', '梅', '奶', '洁', '灾', '舟', '鉴', '苯', '讼', '抱', '毁', '懂', '寒', '智', '埔', '寄', '届', '跃', '渡', '挑', '丹', '艰', '贝', '碰', '拔', '爹', '戴', '码', '梦', '芽', '熔', '赤', '渔', '哭', '敬', '颗', '奔', '铅', '仲', '虎', '稀', '妹', '乏', '珍', '申', '桌', '遵', '允', '隆', '螺', '仓', '魏', '锐', '晓', '氮', '兼', '隐', '碍', '赫', '拨', '忠', '肃', '缸', '牵', '抢', '博', '巧', '壳', '兄', '杜', '讯', '诚', '碧', '祥', '柯', '页', '巡', '矩', '悲', '灌', '龄', '伦', '票', '寻', '桂', '铺', '圣', '恐', '恰', '郑', '趣', '抬', '荒', '腾', '贴', '柔', '滴', '猛', '阔', '辆', '妻', '填', '撤', '储', '签', '闹', '扰', '紫', '砂', '递', '戏', '吊', '陶', '伐', '喂', '疗', '瓶', '婆', '抚', '臂', '摸', '忍', '虾', '蜡', '邻', '胸', '巩', '挤', '偶', '弃', '槽', '劲', '乳', '邓', '吉', '仁', '烂', '砖', '租', '乌', '舰', '伴', '瓜', '浅', '丙', '暂', '燥', '橡', '柳', '迷', '暖', '牌', '秧', '胆', '详', '簧', '踏', '瓷', '谱', '呆', '宾', '糊', '洛', '辉', '愤', '竞', '隙', '怒', '粘', '乃', '绪', '肩', '籍', '敏', '涂', '熙', '皆', '侦', '悬', '掘', '享', '纠', '醒', '狂', '锁', '淀', '恨', '牲', '霸', '爬', '赏', '逆', '玩', '陵', '祝', '秒', '浙', '貌', '役', '彼', '悉', '鸭', '趋', '凤', '晨', '畜', '辈', '秩', '卵', '署', '梯', '炎', '滩', '棋', '驱', '筛', '峡', '冒', '啥', '寿', '译', '浸', '泉', '帽', '迟', '硅', '疆', '贷', '漏', '稿', '冠', '嫩', '胁', '芯', '牢', '叛', '蚀', '奥', '鸣', '岭', '羊', '凭', '串', '塘', '绘', '酵', '融', '盆', '锡', '庙', '筹', '冻', '辅', '摄', '袭', '筋', '拒', '僚', '旱', '钾', '鸟', '漆', '沈', '眉', '疏', '添', '棒', '穗', '硝', '韩', '逼', '扭', '侨', '凉', '挺', '碗', '栽', '炒', '杯', '患', '馏', '劝', '豪', '辽', '勃', '鸿', '旦', '吏', '拜', '狗', '埋', '辊', '掩', '饮', '搬', '骂', '辞', '勾', '扣', '估', '蒋', '绒', '雾', '丈', '朵', '姆', '拟', '宇', '辑', '陕', '雕', '偿', '蓄', '崇', '剪', '倡', '厅', '咬', '驶', '薯', '刷', '斥', '番', '赋', '奉', '佛', '浇', '漫', '曼', '扇', '钙', '桃', '扶', '仔', '返', '俗', '亏', '腔', '鞋', '棱', '覆', '框', '悄', '叔', '撞', '骗', '勘', '旺', '沸', '孤', '吐', '孟', '渠', '屈', '疾', '妙', '惜', '仰', '狠', '胀', '谐', '抛', '霉', '桑', '岗', '嘛', '衰', '盗', '渗', '脏', '赖', '涌', '甜', '曹', '阅', '肌', '哩', '厉', '烃', '纬', '毅', '昨', '伪', '症', '煮', '叹', '钉', '搭', '茎', '笼', '酷', '偷', '弓', '锥', '恒', '杰', '坑', '鼻', '翼', '纶', '叙', '狱', '逮', '罐', '络', '棚', '抑', '膨', '蔬', '寺', '骤', '穆', '冶', '枯', '册', '尸', '凸', '绅', '坯', '牺', '焰', '轰', '欣', '晋', '瘦', '御', '锭', '锦', '丧', '旬', '锻', '垄', '搜', '扑', '邀', '亭', '酯', '迈', '舒', '脆', '酶', '闲', '忧', '酚', '顽', '羽', '涨', '卸', '仗', '陪', '辟', '惩', '杭', '姚', '肚', '捉', '飘', '漂', '昆', '欺', '吾', '郎', '烷', '汁', '呵', '饰', '萧', '雅', '邮', '迁', '燕', '撒', '姻', '赴', '宴', '烦', '债', '帐', '斑', '铃', '旨', '醇', '董', '饼', '雏', '姿', '拌', '傅', '腹', '妥', '揉', '贤', '拆', '歪', '葡', '胺', '丢', '浩', '徽', '昂', '垫', '挡', '览', '贪', '慰', '缴', '汪', '慌', '冯', '诺', '姜', '谊', '凶', '劣', '诬', '耀', '昏', '躺', '盈', '骑', '乔', '溪', '丛', '卢', '抹', '闷', '咨', '刮', '驾', '缆', '悟', '摘', '铒', '掷', '颇', '幻', '柄', '惠', '惨', '佳', '仇', '腊', '窝', '涤', '剑', '瞧', '堡', '泼', '葱', '罩', '霍', '捞', '胎', '苍', '滨', '俩', '捅', '湘', '砍', '霞', '邵', '萄', '疯', '淮', '遂', '熊', '粪', '烘', '宿', '档', '戈', '驳', '嫂', '裕', '徙', '箭', '捐', '肠', '撑', '晒', '辨', '殿', '莲', '摊', '搅', '酱', '屏', '疫', '哀', '蔡', '堵', '沫', '皱', '畅', '叠', '阁', '莱', '敲', '辖', '钩', '痕', '坝', '巷', '饿', '祸', '丘', '玄', '溜', '曰', '逻', '彭', '尝', '卿', '妨', '艇', '吞', '韦', '怨', '矮', '歇']; | |
module.exports = chinese; | |
},{}],93:[function(require,module,exports){ | |
'use strict'; | |
var english = ['abandon', 'ability', 'able', 'about', 'above', 'absent', 'absorb', 'abstract', 'absurd', 'abuse', 'access', 'accident', 'account', 'accuse', 'achieve', 'acid', 'acoustic', 'acquire', 'across', 'act', 'action', 'actor', 'actress', 'actual', 'adapt', 'add', 'addict', 'address', 'adjust', 'admit', 'adult', 'advance', 'advice', 'aerobic', 'affair', 'afford', 'afraid', 'again', 'age', 'agent', 'agree', 'ahead', 'aim', 'air', 'airport', 'aisle', 'alarm', 'album', 'alcohol', 'alert', 'alien', 'all', 'alley', 'allow', 'almost', 'alone', 'alpha', 'already', 'also', 'alter', 'always', 'amateur', 'amazing', 'among', 'amount', 'amused', 'analyst', 'anchor', 'ancient', 'anger', 'angle', 'angry', 'animal', 'ankle', 'announce', 'annual', 'another', 'answer', 'antenna', 'antique', 'anxiety', 'any', 'apart', 'apology', 'appear', 'apple', 'approve', 'april', 'arch', 'arctic', 'area', 'arena', 'argue', 'arm', 'armed', 'armor', 'army', 'around', 'arrange', 'arrest', 'arrive', 'arrow', 'art', 'artefact', 'artist', 'artwork', 'ask', 'aspect', 'assault', 'asset', 'assist', 'assume', 'asthma', 'athlete', 'atom', 'attack', 'attend', 'attitude', 'attract', 'auction', 'audit', 'august', 'aunt', 'author', 'auto', 'autumn', 'average', 'avocado', 'avoid', 'awake', 'aware', 'away', 'awesome', 'awful', 'awkward', 'axis', 'baby', 'bachelor', 'bacon', 'badge', 'bag', 'balance', 'balcony', 'ball', 'bamboo', 'banana', 'banner', 'bar', 'barely', 'bargain', 'barrel', 'base', 'basic', 'basket', 'battle', 'beach', 'bean', 'beauty', 'because', 'become', 'beef', 'before', 'begin', 'behave', 'behind', 'believe', 'below', 'belt', 'bench', 'benefit', 'best', 'betray', 'better', 'between', 'beyond', 'bicycle', 'bid', 'bike', 'bind', 'biology', 'bird', 'birth', 'bitter', 'black', 'blade', 'blame', 'blanket', 'blast', 'bleak', 'bless', 'blind', 'blood', 'blossom', 'blouse', 'blue', 'blur', 'blush', 'board', 'boat', 'body', 'boil', 'bomb', 'bone', 'bonus', 'book', 'boost', 'border', 'boring', 'borrow', 'boss', 'bottom', 'bounce', 'box', 'boy', 'bracket', 'brain', 'brand', 'brass', 'brave', 'bread', 'breeze', 'brick', 'bridge', 'brief', 'bright', 'bring', 'brisk', 'broccoli', 'broken', 'bronze', 'broom', 'brother', 'brown', 'brush', 'bubble', 'buddy', 'budget', 'buffalo', 'build', 'bulb', 'bulk', 'bullet', 'bundle', 'bunker', 'burden', 'burger', 'burst', 'bus', 'business', 'busy', 'butter', 'buyer', 'buzz', 'cabbage', 'cabin', 'cable', 'cactus', 'cage', 'cake', 'call', 'calm', 'camera', 'camp', 'can', 'canal', 'cancel', 'candy', 'cannon', 'canoe', 'canvas', 'canyon', 'capable', 'capital', 'captain', 'car', 'carbon', 'card', 'cargo', 'carpet', 'carry', 'cart', 'case', 'cash', 'casino', 'castle', 'casual', 'cat', 'catalog', 'catch', 'category', 'cattle', 'caught', 'cause', 'caution', 'cave', 'ceiling', 'celery', 'cement', 'census', 'century', 'cereal', 'certain', 'chair', 'chalk', 'champion', 'change', 'chaos', 'chapter', 'charge', 'chase', 'chat', 'cheap', 'check', 'cheese', 'chef', 'cherry', 'chest', 'chicken', 'chief', 'child', 'chimney', 'choice', 'choose', 'chronic', 'chuckle', 'chunk', 'churn', 'cigar', 'cinnamon', 'circle', 'citizen', 'city', 'civil', 'claim', 'clap', 'clarify', 'claw', 'clay', 'clean', 'clerk', 'clever', 'click', 'client', 'cliff', 'climb', 'clinic', 'clip', 'clock', 'clog', 'close', 'cloth', 'cloud', 'clown', 'club', 'clump', 'cluster', 'clutch', 'coach', 'coast', 'coconut', 'code', 'coffee', 'coil', 'coin', 'collect', 'color', 'column', 'combine', 'come', 'comfort', 'comic', 'common', 'company', 'concert', 'conduct', 'confirm', 'congress', 'connect', 'consider', 'control', 'convince', 'cook', 'cool', 'copper', 'copy', 'coral', 'core', 'corn', 'correct', 'cost', 'cotton', 'couch', 'country', 'couple', 'course', 'cousin', 'cover', 'coyote', 'crack', 'cradle', 'craft', 'cram', 'crane', 'crash', 'crater', 'crawl', 'crazy', 'cream', 'credit', 'creek', 'crew', 'cricket', 'crime', 'crisp', 'critic', 'crop', 'cross', 'crouch', 'crowd', 'crucial', 'cruel', 'cruise', 'crumble', 'crunch', 'crush', 'cry', 'crystal', 'cube', 'culture', 'cup', 'cupboard', 'curious', 'current', 'curtain', 'curve', 'cushion', 'custom', 'cute', 'cycle', 'dad', 'damage', 'damp', 'dance', 'danger', 'daring', 'dash', 'daughter', 'dawn', 'day', 'deal', 'debate', 'debris', 'decade', 'december', 'decide', 'decline', 'decorate', 'decrease', 'deer', 'defense', 'define', 'defy', 'degree', 'delay', 'deliver', 'demand', 'demise', 'denial', 'dentist', 'deny', 'depart', 'depend', 'deposit', 'depth', 'deputy', 'derive', 'describe', 'desert', 'design', 'desk', 'despair', 'destroy', 'detail', 'detect', 'develop', 'device', 'devote', 'diagram', 'dial', 'diamond', 'diary', 'dice', 'diesel', 'diet', 'differ', 'digital', 'dignity', 'dilemma', 'dinner', 'dinosaur', 'direct', 'dirt', 'disagree', 'discover', 'disease', 'dish', 'dismiss', 'disorder', 'display', 'distance', 'divert', 'divide', 'divorce', 'dizzy', 'doctor', 'document', 'dog', 'doll', 'dolphin', 'domain', 'donate', 'donkey', 'donor', 'door', 'dose', 'double', 'dove', 'draft', 'dragon', 'drama', 'drastic', 'draw', 'dream', 'dress', 'drift', 'drill', 'drink', 'drip', 'drive', 'drop', 'drum', 'dry', 'duck', 'dumb', 'dune', 'during', 'dust', 'dutch', 'duty', 'dwarf', 'dynamic', 'eager', 'eagle', 'early', 'earn', 'earth', 'easily', 'east', 'easy', 'echo', 'ecology', 'economy', 'edge', 'edit', 'educate', 'effort', 'egg', 'eight', 'either', 'elbow', 'elder', 'electric', 'elegant', 'element', 'elephant', 'elevator', 'elite', 'else', 'embark', 'embody', 'embrace', 'emerge', 'emotion', 'employ', 'empower', 'empty', 'enable', 'enact', 'end', 'endless', 'endorse', 'enemy', 'energy', 'enforce', 'engage', 'engine', 'enhance', 'enjoy', 'enlist', 'enough', 'enrich', 'enroll', 'ensure', 'enter', 'entire', 'entry', 'envelope', 'episode', 'equal', 'equip', 'era', 'erase', 'erode', 'erosion', 'error', 'erupt', 'escape', 'essay', 'essence', 'estate', 'eternal', 'ethics', 'evidence', 'evil', 'evoke', 'evolve', 'exact', 'example', 'excess', 'exchange', 'excite', 'exclude', 'excuse', 'execute', 'exercise', 'exhaust', 'exhibit', 'exile', 'exist', 'exit', 'exotic', 'expand', 'expect', 'expire', 'explain', 'expose', 'express', 'extend', 'extra', 'eye', 'eyebrow', 'fabric', 'face', 'faculty', 'fade', 'faint', 'faith', 'fall', 'false', 'fame', 'family', 'famous', 'fan', 'fancy', 'fantasy', 'farm', 'fashion', 'fat', 'fatal', 'father', 'fatigue', 'fault', 'favorite', 'feature', 'february', 'federal', 'fee', 'feed', 'feel', 'female', 'fence', 'festival', 'fetch', 'fever', 'few', 'fiber', 'fiction', 'field', 'figure', 'file', 'film', 'filter', 'final', 'find', 'fine', 'finger', 'finish', 'fire', 'firm', 'first', 'fiscal', 'fish', 'fit', 'fitness', 'fix', 'flag', 'flame', 'flash', 'flat', 'flavor', 'flee', 'flight', 'flip', 'float', 'flock', 'floor', 'flower', 'fluid', 'flush', 'fly', 'foam', 'focus', 'fog', 'foil', 'fold', 'follow', 'food', 'foot', 'force', 'forest', 'forget', 'fork', 'fortune', 'forum', 'forward', 'fossil', 'foster', 'found', 'fox', 'fragile', 'frame', 'frequent', 'fresh', 'friend', 'fringe', 'frog', 'front', 'frost', 'frown', 'frozen', 'fruit', 'fuel', 'fun', 'funny', 'furnace', 'fury', 'future', 'gadget', 'gain', 'galaxy', 'gallery', 'game', 'gap', 'garage', 'garbage', 'garden', 'garlic', 'garment', 'gas', 'gasp', 'gate', 'gather', 'gauge', 'gaze', 'general', 'genius', 'genre', 'gentle', 'genuine', 'gesture', 'ghost', 'giant', 'gift', 'giggle', 'ginger', 'giraffe', 'girl', 'give', 'glad', 'glance', 'glare', 'glass', 'glide', 'glimpse', 'globe', 'gloom', 'glory', 'glove', 'glow', 'glue', 'goat', 'goddess', 'gold', 'good', 'goose', 'gorilla', 'gospel', 'gossip', 'govern', 'gown', 'grab', 'grace', 'grain', 'grant', 'grape', 'grass', 'gravity', 'great', 'green', 'grid', 'grief', 'grit', 'grocery', 'group', 'grow', 'grunt', 'guard', 'guess', 'guide', 'guilt', 'guitar', 'gun', 'gym', 'habit', 'hair', 'half', 'hammer', 'hamster', 'hand', 'happy', 'harbor', 'hard', 'harsh', 'harvest', 'hat', 'have', 'hawk', 'hazard', 'head', 'health', 'heart', 'heavy', 'hedgehog', 'height', 'hello', 'helmet', 'help', 'hen', 'hero', 'hidden', 'high', 'hill', 'hint', 'hip', 'hire', 'history', 'hobby', 'hockey', 'hold', 'hole', 'holiday', 'hollow', 'home', 'honey', 'hood', 'hope', 'horn', 'horror', 'horse', 'hospital', 'host', 'hotel', 'hour', 'hover', 'hub', 'huge', 'human', 'humble', 'humor', 'hundred', 'hungry', 'hunt', 'hurdle', 'hurry', 'hurt', 'husband', 'hybrid', 'ice', 'icon', 'idea', 'identify', 'idle', 'ignore', 'ill', 'illegal', 'illness', 'image', 'imitate', 'immense', 'immune', 'impact', 'impose', 'improve', 'impulse', 'inch', 'include', 'income', 'increase', 'index', 'indicate', 'indoor', 'industry', 'infant', 'inflict', 'inform', 'inhale', 'inherit', 'initial', 'inject', 'injury', 'inmate', 'inner', 'innocent', 'input', 'inquiry', 'insane', 'insect', 'inside', 'inspire', 'install', 'intact', 'interest', 'into', 'invest', 'invite', 'involve', 'iron', 'island', 'isolate', 'issue', 'item', 'ivory', 'jacket', 'jaguar', 'jar', 'jazz', 'jealous', 'jeans', 'jelly', 'jewel', 'job', 'join', 'joke', 'journey', 'joy', 'judge', 'juice', 'jump', 'jungle', 'junior', 'junk', 'just', 'kangaroo', 'keen', 'keep', 'ketchup', 'key', 'kick', 'kid', 'kidney', 'kind', 'kingdom', 'kiss', 'kit', 'kitchen', 'kite', 'kitten', 'kiwi', 'knee', 'knife', 'knock', 'know', 'lab', 'label', 'labor', 'ladder', 'lady', 'lake', 'lamp', 'language', 'laptop', 'large', 'later', 'latin', 'laugh', 'laundry', 'lava', 'law', 'lawn', 'lawsuit', 'layer', 'lazy', 'leader', 'leaf', 'learn', 'leave', 'lecture', 'left', 'leg', 'legal', 'legend', 'leisure', 'lemon', 'lend', 'length', 'lens', 'leopard', 'lesson', 'letter', 'level', 'liar', 'liberty', 'library', 'license', 'life', 'lift', 'light', 'like', 'limb', 'limit', 'link', 'lion', 'liquid', 'list', 'little', 'live', 'lizard', 'load', 'loan', 'lobster', 'local', 'lock', 'logic', 'lonely', 'long', 'loop', 'lottery', 'loud', 'lounge', 'love', 'loyal', 'lucky', 'luggage', 'lumber', 'lunar', 'lunch', 'luxury', 'lyrics', 'machine', 'mad', 'magic', 'magnet', 'maid', 'mail', 'main', 'major', 'make', 'mammal', 'man', 'manage', 'mandate', 'mango', 'mansion', 'manual', 'maple', 'marble', 'march', 'margin', 'marine', 'market', 'marriage', 'mask', 'mass', 'master', 'match', 'material', 'math', 'matrix', 'matter', 'maximum', 'maze', 'meadow', 'mean', 'measure', 'meat', 'mechanic', 'medal', 'media', 'melody', 'melt', 'member', 'memory', 'mention', 'menu', 'mercy', 'merge', 'merit', 'merry', 'mesh', 'message', 'metal', 'method', 'middle', 'midnight', 'milk', 'million', 'mimic', 'mind', 'minimum', 'minor', 'minute', 'miracle', 'mirror', 'misery', 'miss', 'mistake', 'mix', 'mixed', 'mixture', 'mobile', 'model', 'modify', 'mom', 'moment', 'monitor', 'monkey', 'monster', 'month', 'moon', 'moral', 'more', 'morning', 'mosquito', 'mother', 'motion', 'motor', 'mountain', 'mouse', 'move', 'movie', 'much', 'muffin', 'mule', 'multiply', 'muscle', 'museum', 'mushroom', 'music', 'must', 'mutual', 'myself', 'mystery', 'myth', 'naive', 'name', 'napkin', 'narrow', 'nasty', 'nation', 'nature', 'near', 'neck', 'need', 'negative', 'neglect', 'neither', 'nephew', 'nerve', 'nest', 'net', 'network', 'neutral', 'never', 'news', 'next', 'nice', 'night', 'noble', 'noise', 'nominee', 'noodle', 'normal', 'north', 'nose', 'notable', 'note', 'nothing', 'notice', 'novel', 'now', 'nuclear', 'number', 'nurse', 'nut', 'oak', 'obey', 'object', 'oblige', 'obscure', 'observe', 'obtain', 'obvious', 'occur', 'ocean', 'october', 'odor', 'off', 'offer', 'office', 'often', 'oil', 'okay', 'old', 'olive', 'olympic', 'omit', 'once', 'one', 'onion', 'online', 'only', 'open', 'opera', 'opinion', 'oppose', 'option', 'orange', 'orbit', 'orchard', 'order', 'ordinary', 'organ', 'orient', 'original', 'orphan', 'ostrich', 'other', 'outdoor', 'outer', 'output', 'outside', 'oval', 'oven', 'over', 'own', 'owner', 'oxygen', 'oyster', 'ozone', 'pact', 'paddle', 'page', 'pair', 'palace', 'palm', 'panda', 'panel', 'panic', 'panther', 'paper', 'parade', 'parent', 'park', 'parrot', 'party', 'pass', 'patch', 'path', 'patient', 'patrol', 'pattern', 'pause', 'pave', 'payment', 'peace', 'peanut', 'pear', 'peasant', 'pelican', 'pen', 'penalty', 'pencil', 'people', 'pepper', 'perfect', 'permit', 'person', 'pet', 'phone', 'photo', 'phrase', 'physical', 'piano', 'picnic', 'picture', 'piece', 'pig', 'pigeon', 'pill', 'pilot', 'pink', 'pioneer', 'pipe', 'pistol', 'pitch', 'pizza', 'place', 'planet', 'plastic', 'plate', 'play', 'please', 'pledge', 'pluck', 'plug', 'plunge', 'poem', 'poet', 'point', 'polar', 'pole', 'police', 'pond', 'pony', 'pool', 'popular', 'portion', 'position', 'possible', 'post', 'potato', 'pottery', 'poverty', 'powder', 'power', 'practice', 'praise', 'predict', 'prefer', 'prepare', 'present', 'pretty', 'prevent', 'price', 'pride', 'primary', 'print', 'priority', 'prison', 'private', 'prize', 'problem', 'process', 'produce', 'profit', 'program', 'project', 'promote', 'proof', 'property', 'prosper', 'protect', 'proud', 'provide', 'public', 'pudding', 'pull', 'pulp', 'pulse', 'pumpkin', 'punch', 'pupil', 'puppy', 'purchase', 'purity', 'purpose', 'purse', 'push', 'put', 'puzzle', 'pyramid', 'quality', 'quantum', 'quarter', 'question', 'quick', 'quit', 'quiz', 'quote', 'rabbit', 'raccoon', 'race', 'rack', 'radar', 'radio', 'rail', 'rain', 'raise', 'rally', 'ramp', 'ranch', 'random', 'range', 'rapid', 'rare', 'rate', 'rather', 'raven', 'raw', 'razor', 'ready', 'real', 'reason', 'rebel', 'rebuild', 'recall', 'receive', 'recipe', 'record', 'recycle', 'reduce', 'reflect', 'reform', 'refuse', 'region', 'regret', 'regular', 'reject', 'relax', 'release', 'relief', 'rely', 'remain', 'remember', 'remind', 'remove', 'render', 'renew', 'rent', 'reopen', 'repair', 'repeat', 'replace', 'report', 'require', 'rescue', 'resemble', 'resist', 'resource', 'response', 'result', 'retire', 'retreat', 'return', 'reunion', 'reveal', 'review', 'reward', 'rhythm', 'rib', 'ribbon', 'rice', 'rich', 'ride', 'ridge', 'rifle', 'right', 'rigid', 'ring', 'riot', 'ripple', 'risk', 'ritual', 'rival', 'river', 'road', 'roast', 'robot', 'robust', 'rocket', 'romance', 'roof', 'rookie', 'room', 'rose', 'rotate', 'rough', 'round', 'route', 'royal', 'rubber', 'rude', 'rug', 'rule', 'run', 'runway', 'rural', 'sad', 'saddle', 'sadness', 'safe', 'sail', 'salad', 'salmon', 'salon', 'salt', 'salute', 'same', 'sample', 'sand', 'satisfy', 'satoshi', 'sauce', 'sausage', 'save', 'say', 'scale', 'scan', 'scare', 'scatter', 'scene', 'scheme', 'school', 'science', 'scissors', 'scorpion', 'scout', 'scrap', 'screen', 'script', 'scrub', 'sea', 'search', 'season', 'seat', 'second', 'secret', 'section', 'security', 'seed', 'seek', 'segment', 'select', 'sell', 'seminar', 'senior', 'sense', 'sentence', 'series', 'service', 'session', 'settle', 'setup', 'seven', 'shadow', 'shaft', 'shallow', 'share', 'shed', 'shell', 'sheriff', 'shield', 'shift', 'shine', 'ship', 'shiver', 'shock', 'shoe', 'shoot', 'shop', 'short', 'shoulder', 'shove', 'shrimp', 'shrug', 'shuffle', 'shy', 'sibling', 'sick', 'side', 'siege', 'sight', 'sign', 'silent', 'silk', 'silly', 'silver', 'similar', 'simple', 'since', 'sing', 'siren', 'sister', 'situate', 'six', 'size', 'skate', 'sketch', 'ski', 'skill', 'skin', 'skirt', 'skull', 'slab', 'slam', 'sleep', 'slender', 'slice', 'slide', 'slight', 'slim', 'slogan', 'slot', 'slow', 'slush', 'small', 'smart', 'smile', 'smoke', 'smooth', 'snack', 'snake', 'snap', 'sniff', 'snow', 'soap', 'soccer', 'social', 'sock', 'soda', 'soft', 'solar', 'soldier', 'solid', 'solution', 'solve', 'someone', 'song', 'soon', 'sorry', 'sort', 'soul', 'sound', 'soup', 'source', 'south', 'space', 'spare', 'spatial', 'spawn', 'speak', 'special', 'speed', 'spell', 'spend', 'sphere', 'spice', 'spider', 'spike', 'spin', 'spirit', 'split', 'spoil', 'sponsor', 'spoon', 'sport', 'spot', 'spray', 'spread', 'spring', 'spy', 'square', 'squeeze', 'squirrel', 'stable', 'stadium', 'staff', 'stage', 'stairs', 'stamp', 'stand', 'start', 'state', 'stay', 'steak', 'steel', 'stem', 'step', 'stereo', 'stick', 'still', 'sting', 'stock', 'stomach', 'stone', 'stool', 'story', 'stove', 'strategy', 'street', 'strike', 'strong', 'struggle', 'student', 'stuff', 'stumble', 'style', 'subject', 'submit', 'subway', 'success', 'such', 'sudden', 'suffer', 'sugar', 'suggest', 'suit', 'summer', 'sun', 'sunny', 'sunset', 'super', 'supply', 'supreme', 'sure', 'surface', 'surge', 'surprise', 'surround', 'survey', 'suspect', 'sustain', 'swallow', 'swamp', 'swap', 'swarm', 'swear', 'sweet', 'swift', 'swim', 'swing', 'switch', 'sword', 'symbol', 'symptom', 'syrup', 'system', 'table', 'tackle', 'tag', 'tail', 'talent', 'talk', 'tank', 'tape', 'target', 'task', 'taste', 'tattoo', 'taxi', 'teach', 'team', 'tell', 'ten', 'tenant', 'tennis', 'tent', 'term', 'test', 'text', 'thank', 'that', 'theme', 'then', 'theory', 'there', 'they', 'thing', 'this', 'thought', 'three', 'thrive', 'throw', 'thumb', 'thunder', 'ticket', 'tide', 'tiger', 'tilt', 'timber', 'time', 'tiny', 'tip', 'tired', 'tissue', 'title', 'toast', 'tobacco', 'today', 'toddler', 'toe', 'together', 'toilet', 'token', 'tomato', 'tomorrow', 'tone', 'tongue', 'tonight', 'tool', 'tooth', 'top', 'topic', 'topple', 'torch', 'tornado', 'tortoise', 'toss', 'total', 'tourist', 'toward', 'tower', 'town', 'toy', 'track', 'trade', 'traffic', 'tragic', 'train', 'transfer', 'trap', 'trash', 'travel', 'tray', 'treat', 'tree', 'trend', 'trial', 'tribe', 'trick', 'trigger', 'trim', 'trip', 'trophy', 'trouble', 'truck', 'true', 'truly', 'trumpet', 'trust', 'truth', 'try', 'tube', 'tuition', 'tumble', 'tuna', 'tunnel', 'turkey', 'turn', 'turtle', 'twelve', 'twenty', 'twice', 'twin', 'twist', 'two', 'type', 'typical', 'ugly', 'umbrella', 'unable', 'unaware', 'uncle', 'uncover', 'under', 'undo', 'unfair', 'unfold', 'unhappy', 'uniform', 'unique', 'unit', 'universe', 'unknown', 'unlock', 'until', 'unusual', 'unveil', 'update', 'upgrade', 'uphold', 'upon', 'upper', 'upset', 'urban', 'urge', 'usage', 'use', 'used', 'useful', 'useless', 'usual', 'utility', 'vacant', 'vacuum', 'vague', 'valid', 'valley', 'valve', 'van', 'vanish', 'vapor', 'various', 'vast', 'vault', 'vehicle', 'velvet', 'vendor', 'venture', 'venue', 'verb', 'verify', 'version', 'very', 'vessel', 'veteran', 'viable', 'vibrant', 'vicious', 'victory', 'video', 'view', 'village', 'vintage', 'violin', 'virtual', 'virus', 'visa', 'visit', 'visual', 'vital', 'vivid', 'vocal', 'voice', 'void', 'volcano', 'volume', 'vote', 'voyage', 'wage', 'wagon', 'wait', 'walk', 'wall', 'walnut', 'want', 'warfare', 'warm', 'warrior', 'wash', 'wasp', 'waste', 'water', 'wave', 'way', 'wealth', 'weapon', 'wear', 'weasel', 'weather', 'web', 'wedding', 'weekend', 'weird', 'welcome', 'west', 'wet', 'whale', 'what', 'wheat', 'wheel', 'when', 'where', 'whip', 'whisper', 'wide', 'width', 'wife', 'wild', 'will', 'win', 'window', 'wine', 'wing', 'wink', 'winner', 'winter', 'wire', 'wisdom', 'wise', 'wish', 'witness', 'wolf', 'woman', 'wonder', 'wood', 'wool', 'word', 'work', 'world', 'worry', 'worth', 'wrap', 'wreck', 'wrestle', 'wrist', 'write', 'wrong', 'yard', 'year', 'yellow', 'you', 'young', 'youth', 'zebra', 'zero', 'zone', 'zoo']; | |
module.exports = english; | |
},{}],94:[function(require,module,exports){ | |
'use strict'; | |
'use string'; | |
var french = ['abaisser', 'abandon', 'abdiquer', 'abeille', 'abolir', 'aborder', 'aboutir', 'aboyer', 'abrasif', 'abreuver', 'abriter', 'abroger', 'abrupt', 'absence', 'absolu', 'absurde', 'abusif', 'abyssal', 'académie', 'acajou', 'acarien', 'accabler', 'accepter', 'acclamer', 'accolade', 'accroche', 'accuser', 'acerbe', 'achat', 'acheter', 'aciduler', 'acier', 'acompte', 'acquérir', 'acronyme', 'acteur', 'actif', 'actuel', 'adepte', 'adéquat', 'adhésif', 'adjectif', 'adjuger', 'admettre', 'admirer', 'adopter', 'adorer', 'adoucir', 'adresse', 'adroit', 'adulte', 'adverbe', 'aérer', 'aéronef', 'affaire', 'affecter', 'affiche', 'affreux', 'affubler', 'agacer', 'agencer', 'agile', 'agiter', 'agrafer', 'agréable', 'agrume', 'aider', 'aiguille', 'ailier', 'aimable', 'aisance', 'ajouter', 'ajuster', 'alarmer', 'alchimie', 'alerte', 'algèbre', 'algue', 'aliéner', 'aliment', 'alléger', 'alliage', 'allouer', 'allumer', 'alourdir', 'alpaga', 'altesse', 'alvéole', 'amateur', 'ambigu', 'ambre', 'aménager', 'amertume', 'amidon', 'amiral', 'amorcer', 'amour', 'amovible', 'amphibie', 'ampleur', 'amusant', 'analyse', 'anaphore', 'anarchie', 'anatomie', 'ancien', 'anéantir', 'angle', 'angoisse', 'anguleux', 'animal', 'annexer', 'annonce', 'annuel', 'anodin', 'anomalie', 'anonyme', 'anormal', 'antenne', 'antidote', 'anxieux', 'apaiser', 'apéritif', 'aplanir', 'apologie', 'appareil', 'appeler', 'apporter', 'appuyer', 'aquarium', 'aqueduc', 'arbitre', 'arbuste', 'ardeur', 'ardoise', 'argent', 'arlequin', 'armature', 'armement', 'armoire', 'armure', 'arpenter', 'arracher', 'arriver', 'arroser', 'arsenic', 'artériel', 'article', 'aspect', 'asphalte', 'aspirer', 'assaut', 'asservir', 'assiette', 'associer', 'assurer', 'asticot', 'astre', 'astuce', 'atelier', 'atome', 'atrium', 'atroce', 'attaque', 'attentif', 'attirer', 'attraper', 'aubaine', 'auberge', 'audace', 'audible', 'augurer', 'aurore', 'automne', 'autruche', 'avaler', 'avancer', 'avarice', 'avenir', 'averse', 'aveugle', 'aviateur', 'avide', 'avion', 'aviser', 'avoine', 'avouer', 'avril', 'axial', 'axiome', 'badge', 'bafouer', 'bagage', 'baguette', 'baignade', 'balancer', 'balcon', 'baleine', 'balisage', 'bambin', 'bancaire', 'bandage', 'banlieue', 'bannière', 'banquier', 'barbier', 'baril', 'baron', 'barque', 'barrage', 'bassin', 'bastion', 'bataille', 'bateau', 'batterie', 'baudrier', 'bavarder', 'belette', 'bélier', 'belote', 'bénéfice', 'berceau', 'berger', 'berline', 'bermuda', 'besace', 'besogne', 'bétail', 'beurre', 'biberon', 'bicycle', 'bidule', 'bijou', 'bilan', 'bilingue', 'billard', 'binaire', 'biologie', 'biopsie', 'biotype', 'biscuit', 'bison', 'bistouri', 'bitume', 'bizarre', 'blafard', 'blague', 'blanchir', 'blessant', 'blinder', 'blond', 'bloquer', 'blouson', 'bobard', 'bobine', 'boire', 'boiser', 'bolide', 'bonbon', 'bondir', 'bonheur', 'bonifier', 'bonus', 'bordure', 'borne', 'botte', 'boucle', 'boueux', 'bougie', 'boulon', 'bouquin', 'bourse', 'boussole', 'boutique', 'boxeur', 'branche', 'brasier', 'brave', 'brebis', 'brèche', 'breuvage', 'bricoler', 'brigade', 'brillant', 'brioche', 'brique', 'brochure', 'broder', 'bronzer', 'brousse', 'broyeur', 'brume', 'brusque', 'brutal', 'bruyant', 'buffle', 'buisson', 'bulletin', 'bureau', 'burin', 'bustier', 'butiner', 'butoir', 'buvable', 'buvette', 'cabanon', 'cabine', 'cachette', 'cadeau', 'cadre', 'caféine', 'caillou', 'caisson', 'calculer', 'calepin', 'calibre', 'calmer', 'calomnie', 'calvaire', 'camarade', 'caméra', 'camion', 'campagne', 'canal', 'caneton', 'canon', 'cantine', 'canular', 'capable', 'caporal', 'caprice', 'capsule', 'capter', 'capuche', 'carabine', 'carbone', 'caresser', 'caribou', 'carnage', 'carotte', 'carreau', 'carton', 'cascade', 'casier', 'casque', 'cassure', 'causer', 'caution', 'cavalier', 'caverne', 'caviar', 'cédille', 'ceinture', 'céleste', 'cellule', 'cendrier', 'censurer', 'central', 'cercle', 'cérébral', 'cerise', 'cerner', 'cerveau', 'cesser', 'chagrin', 'chaise', 'chaleur', 'chambre', 'chance', 'chapitre', 'charbon', 'chasseur', 'chaton', 'chausson', 'chavirer', 'chemise', 'chenille', 'chéquier', 'chercher', 'cheval', 'chien', 'chiffre', 'chignon', 'chimère', 'chiot', 'chlorure', 'chocolat', 'choisir', 'chose', 'chouette', 'chrome', 'chute', 'cigare', 'cigogne', 'cimenter', 'cinéma', 'cintrer', 'circuler', 'cirer', 'cirque', 'citerne', 'citoyen', 'citron', 'civil', 'clairon', 'clameur', 'claquer', 'classe', 'clavier', 'client', 'cligner', 'climat', 'clivage', 'cloche', 'clonage', 'cloporte', 'cobalt', 'cobra', 'cocasse', 'cocotier', 'coder', 'codifier', 'coffre', 'cogner', 'cohésion', 'coiffer', 'coincer', 'colère', 'colibri', 'colline', 'colmater', 'colonel', 'combat', 'comédie', 'commande', 'compact', 'concert', 'conduire', 'confier', 'congeler', 'connoter', 'consonne', 'contact', 'convexe', 'copain', 'copie', 'corail', 'corbeau', 'cordage', 'corniche', 'corpus', 'correct', 'cortège', 'cosmique', 'costume', 'coton', 'coude', 'coupure', 'courage', 'couteau', 'couvrir', 'coyote', 'crabe', 'crainte', 'cravate', 'crayon', 'créature', 'créditer', 'crémeux', 'creuser', 'crevette', 'cribler', 'crier', 'cristal', 'critère', 'croire', 'croquer', 'crotale', 'crucial', 'cruel', 'crypter', 'cubique', 'cueillir', 'cuillère', 'cuisine', 'cuivre', 'culminer', 'cultiver', 'cumuler', 'cupide', 'curatif', 'curseur', 'cyanure', 'cycle', 'cylindre', 'cynique', 'daigner', 'damier', 'danger', 'danseur', 'dauphin', 'débattre', 'débiter', 'déborder', 'débrider', 'débutant', 'décaler', 'décembre', 'déchirer', 'décider', 'déclarer', 'décorer', 'décrire', 'décupler', 'dédale', 'déductif', 'déesse', 'défensif', 'défiler', 'défrayer', 'dégager', 'dégivrer', 'déglutir', 'dégrafer', 'déjeuner', 'délice', 'déloger', 'demander', 'demeurer', 'démolir', 'dénicher', 'dénouer', 'dentelle', 'dénuder', 'départ', 'dépenser', 'déphaser', 'déplacer', 'déposer', 'déranger', 'dérober', 'désastre', 'descente', 'désert', 'désigner', 'désobéir', 'dessiner', 'destrier', 'détacher', 'détester', 'détourer', 'détresse', 'devancer', 'devenir', 'deviner', 'devoir', 'diable', 'dialogue', 'diamant', 'dicter', 'différer', 'digérer', 'digital', 'digne', 'diluer', 'dimanche', 'diminuer', 'dioxyde', 'directif', 'diriger', 'discuter', 'disposer', 'dissiper', 'distance', 'divertir', 'diviser', 'docile', 'docteur', 'dogme', 'doigt', 'domaine', 'domicile', 'dompter', 'donateur', 'donjon', 'donner', 'dopamine', 'dortoir', 'dorure', 'dosage', 'doseur', 'dossier', 'dotation', 'douanier', 'double', 'douceur', 'douter', 'doyen', 'dragon', 'draper', 'dresser', 'dribbler', 'droiture', 'duperie', 'duplexe', 'durable', 'durcir', 'dynastie', 'éblouir', 'écarter', 'écharpe', 'échelle', 'éclairer', 'éclipse', 'éclore', 'écluse', 'école', 'économie', 'écorce', 'écouter', 'écraser', 'écrémer', 'écrivain', 'écrou', 'écume', 'écureuil', 'édifier', 'éduquer', 'effacer', 'effectif', 'effigie', 'effort', 'effrayer', 'effusion', 'égaliser', 'égarer', 'éjecter', 'élaborer', 'élargir', 'électron', 'élégant', 'éléphant', 'élève', 'éligible', 'élitisme', 'éloge', 'élucider', 'éluder', 'emballer', 'embellir', 'embryon', 'émeraude', 'émission', 'emmener', 'émotion', 'émouvoir', 'empereur', 'employer', 'emporter', 'emprise', 'émulsion', 'encadrer', 'enchère', 'enclave', 'encoche', 'endiguer', 'endosser', 'endroit', 'enduire', 'énergie', 'enfance', 'enfermer', 'enfouir', 'engager', 'engin', 'englober', 'énigme', 'enjamber', 'enjeu', 'enlever', 'ennemi', 'ennuyeux', 'enrichir', 'enrobage', 'enseigne', 'entasser', 'entendre', 'entier', 'entourer', 'entraver', 'énumérer', 'envahir', 'enviable', 'envoyer', 'enzyme', 'éolien', 'épaissir', 'épargne', 'épatant', 'épaule', 'épicerie', 'épidémie', 'épier', 'épilogue', 'épine', 'épisode', 'épitaphe', 'époque', 'épreuve', 'éprouver', 'épuisant', 'équerre', 'équipe', 'ériger', 'érosion', 'erreur', 'éruption', 'escalier', 'espadon', 'espèce', 'espiègle', 'espoir', 'esprit', 'esquiver', 'essayer', 'essence', 'essieu', 'essorer', 'estime', 'estomac', 'estrade', 'étagère', 'étaler', 'étanche', 'étatique', 'éteindre', 'étendoir', 'éternel', 'éthanol', 'éthique', 'ethnie', 'étirer', 'étoffer', 'étoile', 'étonnant', 'étourdir', 'étrange', 'étroit', 'étude', 'euphorie', 'évaluer', 'évasion', 'éventail', 'évidence', 'éviter', 'évolutif', 'évoquer', 'exact', 'exagérer', 'exaucer', 'exceller', 'excitant', 'exclusif', 'excuse', 'exécuter', 'exemple', 'exercer', 'exhaler', 'exhorter', 'exigence', 'exiler', 'exister', 'exotique', 'expédier', 'explorer', 'exposer', 'exprimer', 'exquis', 'extensif', 'extraire', 'exulter', 'fable', 'fabuleux', 'facette', 'facile', 'facture', 'faiblir', 'falaise', 'fameux', 'famille', 'farceur', 'farfelu', 'farine', 'farouche', 'fasciner', 'fatal', 'fatigue', 'faucon', 'fautif', 'faveur', 'favori', 'fébrile', 'féconder', 'fédérer', 'félin', 'femme', 'fémur', 'fendoir', 'féodal', 'fermer', 'féroce', 'ferveur', 'festival', 'feuille', 'feutre', 'février', 'fiasco', 'ficeler', 'fictif', 'fidèle', 'figure', 'filature', 'filetage', 'filière', 'filleul', 'filmer', 'filou', 'filtrer', 'financer', 'finir', 'fiole', 'firme', 'fissure', 'fixer', 'flairer', 'flamme', 'flasque', 'flatteur', 'fléau', 'flèche', 'fleur', 'flexion', 'flocon', 'flore', 'fluctuer', 'fluide', 'fluvial', 'folie', 'fonderie', 'fongible', 'fontaine', 'forcer', 'forgeron', 'formuler', 'fortune', 'fossile', 'foudre', 'fougère', 'fouiller', 'foulure', 'fourmi', 'fragile', 'fraise', 'franchir', 'frapper', 'frayeur', 'frégate', 'freiner', 'frelon', 'frémir', 'frénésie', 'frère', 'friable', 'friction', 'frisson', 'frivole', 'froid', 'fromage', 'frontal', 'frotter', 'fruit', 'fugitif', 'fuite', 'fureur', 'furieux', 'furtif', 'fusion', 'futur', 'gagner', 'galaxie', 'galerie', 'gambader', 'garantir', 'gardien', 'garnir', 'garrigue', 'gazelle', 'gazon', 'géant', 'gélatine', 'gélule', 'gendarme', 'général', 'génie', 'genou', 'gentil', 'géologie', 'géomètre', 'géranium', 'germe', 'gestuel', 'geyser', 'gibier', 'gicler', 'girafe', 'givre', 'glace', 'glaive', 'glisser', 'globe', 'gloire', 'glorieux', 'golfeur', 'gomme', 'gonfler', 'gorge', 'gorille', 'goudron', 'gouffre', 'goulot', 'goupille', 'gourmand', 'goutte', 'graduel', 'graffiti', 'graine', 'grand', 'grappin', 'gratuit', 'gravir', 'grenat', 'griffure', 'griller', 'grimper', 'grogner', 'gronder', 'grotte', 'groupe', 'gruger', 'grutier', 'gruyère', 'guépard', 'guerrier', 'guide', 'guimauve', 'guitare', 'gustatif', 'gymnaste', 'gyrostat', 'habitude', 'hachoir', 'halte', 'hameau', 'hangar', 'hanneton', 'haricot', 'harmonie', 'harpon', 'hasard', 'hélium', 'hématome', 'herbe', 'hérisson', 'hermine', 'héron', 'hésiter', 'heureux', 'hiberner', 'hibou', 'hilarant', 'histoire', 'hiver', 'homard', 'hommage', 'homogène', 'honneur', 'honorer', 'honteux', 'horde', 'horizon', 'horloge', 'hormone', 'horrible', 'houleux', 'housse', 'hublot', 'huileux', 'humain', 'humble', 'humide', 'humour', 'hurler', 'hydromel', 'hygiène', 'hymne', 'hypnose', 'idylle', 'ignorer', 'iguane', 'illicite', 'illusion', 'image', 'imbiber', 'imiter', 'immense', 'immobile', 'immuable', 'impact', 'impérial', 'implorer', 'imposer', 'imprimer', 'imputer', 'incarner', 'incendie', 'incident', 'incliner', 'incolore', 'indexer', 'indice', 'inductif', 'inédit', 'ineptie', 'inexact', 'infini', 'infliger', 'informer', 'infusion', 'ingérer', 'inhaler', 'inhiber', 'injecter', 'injure', 'innocent', 'inoculer', 'inonder', 'inscrire', 'insecte', 'insigne', 'insolite', 'inspirer', 'instinct', 'insulter', 'intact', 'intense', 'intime', 'intrigue', 'intuitif', 'inutile', 'invasion', 'inventer', 'inviter', 'invoquer', 'ironique', 'irradier', 'irréel', 'irriter', 'isoler', 'ivoire', 'ivresse', 'jaguar', 'jaillir', 'jambe', 'janvier', 'jardin', 'jauger', 'jaune', 'javelot', 'jetable', 'jeton', 'jeudi', 'jeunesse', 'joindre', 'joncher', 'jongler', 'joueur', 'jouissif', 'journal', 'jovial', 'joyau', 'joyeux', 'jubiler', 'jugement', 'junior', 'jupon', 'juriste', 'justice', 'juteux', 'juvénile', 'kayak', 'kimono', 'kiosque', 'label', 'labial', 'labourer', 'lacérer', 'lactose', 'lagune', 'laine', 'laisser', 'laitier', 'lambeau', 'lamelle', 'lampe', 'lanceur', 'langage', 'lanterne', 'lapin', 'largeur', 'larme', 'laurier', 'lavabo', 'lavoir', 'lecture', 'légal', 'léger', 'légume', 'lessive', 'lettre', 'levier', 'lexique', 'lézard', 'liasse', 'libérer', 'libre', 'licence', 'licorne', 'liège', 'lièvre', 'ligature', 'ligoter', 'ligue', 'limer', 'limite', 'limonade', 'limpide', 'linéaire', 'lingot', 'lionceau', 'liquide', 'lisière', 'lister', 'lithium', 'litige', 'littoral', 'livreur', 'logique', 'lointain', 'loisir', 'lombric', 'loterie', 'louer', 'lourd', 'loutre', 'louve', 'loyal', 'lubie', 'lucide', 'lucratif', 'lueur', 'lugubre', 'luisant', 'lumière', 'lunaire', 'lundi', 'luron', 'lutter', 'luxueux', 'machine', 'magasin', 'magenta', 'magique', 'maigre', 'maillon', 'maintien', 'mairie', 'maison', 'majorer', 'malaxer', 'maléfice', 'malheur', 'malice', 'mallette', 'mammouth', 'mandater', 'maniable', 'manquant', 'manteau', 'manuel', 'marathon', 'marbre', 'marchand', 'mardi', 'maritime', 'marqueur', 'marron', 'marteler', 'mascotte', 'massif', 'matériel', 'matière', 'matraque', 'maudire', 'maussade', 'mauve', 'maximal', 'méchant', 'méconnu', 'médaille', 'médecin', 'méditer', 'méduse', 'meilleur', 'mélange', 'mélodie', 'membre', 'mémoire', 'menacer', 'mener', 'menhir', 'mensonge', 'mentor', 'mercredi', 'mérite', 'merle', 'messager', 'mesure', 'métal', 'météore', 'méthode', 'métier', 'meuble', 'miauler', 'microbe', 'miette', 'mignon', 'migrer', 'milieu', 'million', 'mimique', 'mince', 'minéral', 'minimal', 'minorer', 'minute', 'miracle', 'miroiter', 'missile', 'mixte', 'mobile', 'moderne', 'moelleux', 'mondial', 'moniteur', 'monnaie', 'monotone', 'monstre', 'montagne', 'monument', 'moqueur', 'morceau', 'morsure', 'mortier', 'moteur', 'motif', 'mouche', 'moufle', 'moulin', 'mousson', 'mouton', 'mouvant', 'multiple', 'munition', 'muraille', 'murène', 'murmure', 'muscle', 'muséum', 'musicien', 'mutation', 'muter', 'mutuel', 'myriade', 'myrtille', 'mystère', 'mythique', 'nageur', 'nappe', 'narquois', 'narrer', 'natation', 'nation', 'nature', 'naufrage', 'nautique', 'navire', 'nébuleux', 'nectar', 'néfaste', 'négation', 'négliger', 'négocier', 'neige', 'nerveux', 'nettoyer', 'neurone', 'neutron', 'neveu', 'niche', 'nickel', 'nitrate', 'niveau', 'noble', 'nocif', 'nocturne', 'noirceur', 'noisette', 'nomade', 'nombreux', 'nommer', 'normatif', 'notable', 'notifier', 'notoire', 'nourrir', 'nouveau', 'novateur', 'novembre', 'novice', 'nuage', 'nuancer', 'nuire', 'nuisible', 'numéro', 'nuptial', 'nuque', 'nutritif', 'obéir', 'objectif', 'obliger', 'obscur', 'observer', 'obstacle', 'obtenir', 'obturer', 'occasion', 'occuper', 'océan', 'octobre', 'octroyer', 'octupler', 'oculaire', 'odeur', 'odorant', 'offenser', 'officier', 'offrir', 'ogive', 'oiseau', 'oisillon', 'olfactif', 'olivier', 'ombrage', 'omettre', 'onctueux', 'onduler', 'onéreux', 'onirique', 'opale', 'opaque', 'opérer', 'opinion', 'opportun', 'opprimer', 'opter', 'optique', 'orageux', 'orange', 'orbite', 'ordonner', 'oreille', 'organe', 'orgueil', 'orifice', 'ornement', 'orque', 'ortie', 'osciller', 'osmose', 'ossature', 'otarie', 'ouragan', 'ourson', 'outil', 'outrager', 'ouvrage', 'ovation', 'oxyde', 'oxygène', 'ozone', 'paisible', 'palace', 'palmarès', 'palourde', 'palper', 'panache', 'panda', 'pangolin', 'paniquer', 'panneau', 'panorama', 'pantalon', 'papaye', 'papier', 'papoter', 'papyrus', 'paradoxe', 'parcelle', 'paresse', 'parfumer', 'parler', 'parole', 'parrain', 'parsemer', 'partager', 'parure', 'parvenir', 'passion', 'pastèque', 'paternel', 'patience', 'patron', 'pavillon', 'pavoiser', 'payer', 'paysage', 'peigne', 'peintre', 'pelage', 'pélican', 'pelle', 'pelouse', 'peluche', 'pendule', 'pénétrer', 'pénible', 'pensif', 'pénurie', 'pépite', 'péplum', 'perdrix', 'perforer', 'période', 'permuter', 'perplexe', 'persil', 'perte', 'peser', 'pétale', 'petit', 'pétrir', 'peuple', 'pharaon', 'phobie', 'phoque', 'photon', 'phrase', 'physique', 'piano', 'pictural', 'pièce', 'pierre', 'pieuvre', 'pilote', 'pinceau', 'pipette', 'piquer', 'pirogue', 'piscine', 'piston', 'pivoter', 'pixel', 'pizza', 'placard', 'plafond', 'plaisir', 'planer', 'plaque', 'plastron', 'plateau', 'pleurer', 'plexus', 'pliage', 'plomb', 'plonger', 'pluie', 'plumage', 'pochette', 'poésie', 'poète', 'pointe', 'poirier', 'poisson', 'poivre', 'polaire', 'policier', 'pollen', 'polygone', 'pommade', 'pompier', 'ponctuel', 'pondérer', 'poney', 'portique', 'position', 'posséder', 'posture', 'potager', 'poteau', 'potion', 'pouce', 'poulain', 'poumon', 'pourpre', 'poussin', 'pouvoir', 'prairie', 'pratique', 'précieux', 'prédire', 'préfixe', 'prélude', 'prénom', 'présence', 'prétexte', 'prévoir', 'primitif', 'prince', 'prison', 'priver', 'problème', 'procéder', 'prodige', 'profond', 'progrès', 'proie', 'projeter', 'prologue', 'promener', 'propre', 'prospère', 'protéger', 'prouesse', 'proverbe', 'prudence', 'pruneau', 'psychose', 'public', 'puceron', 'puiser', 'pulpe', 'pulsar', 'punaise', 'punitif', 'pupitre', 'purifier', 'puzzle', 'pyramide', 'quasar', 'querelle', 'question', 'quiétude', 'quitter', 'quotient', 'racine', 'raconter', 'radieux', 'ragondin', 'raideur', 'raisin', 'ralentir', 'rallonge', 'ramasser', 'rapide', 'rasage', 'ratisser', 'ravager', 'ravin', 'rayonner', 'réactif', 'réagir', 'réaliser', 'réanimer', 'recevoir', 'réciter', 'réclamer', 'récolter', 'recruter', 'reculer', 'recycler', 'rédiger', 'redouter', 'refaire', 'réflexe', 'réformer', 'refrain', 'refuge', 'régalien', 'région', 'réglage', 'régulier', 'réitérer', 'rejeter', 'rejouer', 'relatif', 'relever', 'relief', 'remarque', 'remède', 'remise', 'remonter', 'remplir', 'remuer', 'renard', 'renfort', 'renifler', 'renoncer', 'rentrer', 'renvoi', 'replier', 'reporter', 'reprise', 'reptile', 'requin', 'réserve', 'résineux', 'résoudre', 'respect', 'rester', 'résultat', 'rétablir', 'retenir', 'réticule', 'retomber', 'retracer', 'réunion', 'réussir', 'revanche', 'revivre', 'révolte', 'révulsif', 'richesse', 'rideau', 'rieur', 'rigide', 'rigoler', 'rincer', 'riposter', 'risible', 'risque', 'rituel', 'rival', 'rivière', 'rocheux', 'romance', 'rompre', 'ronce', 'rondin', 'roseau', 'rosier', 'rotatif', 'rotor', 'rotule', 'rouge', 'rouille', 'rouleau', 'routine', 'royaume', 'ruban', 'rubis', 'ruche', 'ruelle', 'rugueux', 'ruiner', 'ruisseau', 'ruser', 'rustique', 'rythme', 'sabler', 'saboter', 'sabre', 'sacoche', 'safari', 'sagesse', 'saisir', 'salade', 'salive', 'salon', 'saluer', 'samedi', 'sanction', 'sanglier', 'sarcasme', 'sardine', 'saturer', 'saugrenu', 'saumon', 'sauter', 'sauvage', 'savant', 'savonner', 'scalpel', 'scandale', 'scélérat', 'scénario', 'sceptre', 'schéma', 'science', 'scinder', 'score', 'scrutin', 'sculpter', 'séance', 'sécable', 'sécher', 'secouer', 'sécréter', 'sédatif', 'séduire', 'seigneur', 'séjour', 'sélectif', 'semaine', 'sembler', 'semence', 'séminal', 'sénateur', 'sensible', 'sentence', 'séparer', 'séquence', 'serein', 'sergent', 'sérieux', 'serrure', 'sérum', 'service', 'sésame', 'sévir', 'sevrage', 'sextuple', 'sidéral', 'siècle', 'siéger', 'siffler', 'sigle', 'signal', 'silence', 'silicium', 'simple', 'sincère', 'sinistre', 'siphon', 'sirop', 'sismique', 'situer', 'skier', 'social', 'socle', 'sodium', 'soigneux', 'soldat', 'soleil', 'solitude', 'soluble', 'sombre', 'sommeil', 'somnoler', 'sonde', 'songeur', 'sonnette', 'sonore', 'sorcier', 'sortir', 'sosie', 'sottise', 'soucieux', 'soudure', 'souffle', 'soulever', 'soupape', 'source', 'soutirer', 'souvenir', 'spacieux', 'spatial', 'spécial', 'sphère', 'spiral', 'stable', 'station', 'sternum', 'stimulus', 'stipuler', 'strict', 'studieux', 'stupeur', 'styliste', 'sublime', 'substrat', 'subtil', 'subvenir', 'succès', 'sucre', 'suffixe', 'suggérer', 'suiveur', 'sulfate', 'superbe', 'supplier', 'surface', 'suricate', 'surmener', 'surprise', 'sursaut', 'survie', 'suspect', 'syllabe', 'symbole', 'symétrie', 'synapse', 'syntaxe', 'système', 'tabac', 'tablier', 'tactile', 'tailler', 'talent', 'talisman', 'talonner', 'tambour', 'tamiser', 'tangible', 'tapis', 'taquiner', 'tarder', 'tarif', 'tartine', 'tasse', 'tatami', 'tatouage', 'taupe', 'taureau', 'taxer', 'témoin', 'temporel', 'tenaille', 'tendre', 'teneur', 'tenir', 'tension', 'terminer', 'terne', 'terrible', 'tétine', 'texte', 'thème', 'théorie', 'thérapie', 'thorax', 'tibia', 'tiède', 'timide', 'tirelire', 'tiroir', 'tissu', 'titane', 'titre', 'tituber', 'toboggan', 'tolérant', 'tomate', 'tonique', 'tonneau', 'toponyme', 'torche', 'tordre', 'tornade', 'torpille', 'torrent', 'torse', 'tortue', 'totem', 'toucher', 'tournage', 'tousser', 'toxine', 'traction', 'trafic', 'tragique', 'trahir', 'train', 'trancher', 'travail', 'trèfle', 'tremper', 'trésor', 'treuil', 'triage', 'tribunal', 'tricoter', 'trilogie', 'triomphe', 'tripler', 'triturer', 'trivial', 'trombone', 'tronc', 'tropical', 'troupeau', 'tuile', 'tulipe', 'tumulte', 'tunnel', 'turbine', 'tuteur', 'tutoyer', 'tuyau', 'tympan', 'typhon', 'typique', 'tyran', 'ubuesque', 'ultime', 'ultrason', 'unanime', 'unifier', 'union', 'unique', 'unitaire', 'univers', 'uranium', 'urbain', 'urticant', 'usage', 'usine', 'usuel', 'usure', 'utile', 'utopie', 'vacarme', 'vaccin', 'vagabond', 'vague', 'vaillant', 'vaincre', 'vaisseau', 'valable', 'valise', 'vallon', 'valve', 'vampire', 'vanille', 'vapeur', 'varier', 'vaseux', 'vassal', 'vaste', 'vecteur', 'vedette', 'végétal', 'véhicule', 'veinard', 'véloce', 'vendredi', 'vénérer', 'venger', 'venimeux', 'ventouse', 'verdure', 'vérin', 'vernir', 'verrou', 'verser', 'vertu', 'veston', 'vétéran', 'vétuste', 'vexant', 'vexer', 'viaduc', 'viande', 'victoire', 'vidange', 'vidéo', 'vignette', 'vigueur', 'vilain', 'village', 'vinaigre', 'violon', 'vipère', 'virement', 'virtuose', 'virus', 'visage', 'viseur', 'vision', 'visqueux', 'visuel', 'vital', 'vitesse', 'viticole', 'vitrine', 'vivace', 'vivipare', 'vocation', 'voguer', 'voile', 'voisin', 'voiture', 'volaille', 'volcan', 'voltiger', 'volume', 'vorace', 'vortex', 'voter', 'vouloir', 'voyage', 'voyelle', 'wagon', 'xénon', 'yacht', 'zèbre', 'zénith', 'zeste', 'zoologie']; | |
module.exports = french; | |
},{}],95:[function(require,module,exports){ | |
'use strict'; | |
module.exports = { | |
'CHINESE': require('./chinese'), | |
'ENGLISH': require('./english'), | |
'FRENCH': require('./french'), | |
'ITALIAN': require('./italian'), | |
'JAPANESE': require('./japanese'), | |
'SPANISH': require('./spanish') | |
}; | |
},{"./chinese":92,"./english":93,"./french":94,"./italian":96,"./japanese":97,"./spanish":98}],96:[function(require,module,exports){ | |
'use strict'; | |
var italian = ['abaco', 'abbaglio', 'abbinato', 'abete', 'abisso', 'abolire', 'abrasivo', 'abrogato', 'accadere', 'accenno', 'accusato', 'acetone', 'achille', 'acido', 'acqua', 'acre', 'acrilico', 'acrobata', 'acuto', 'adagio', 'addebito', 'addome', 'adeguato', 'aderire', 'adipe', 'adottare', 'adulare', 'affabile', 'affetto', 'affisso', 'affranto', 'aforisma', 'afoso', 'africano', 'agave', 'agente', 'agevole', 'aggancio', 'agire', 'agitare', 'agonismo', 'agricolo', 'agrumeto', 'aguzzo', 'alabarda', 'alato', 'albatro', 'alberato', 'albo', 'albume', 'alce', 'alcolico', 'alettone', 'alfa', 'algebra', 'aliante', 'alibi', 'alimento', 'allagato', 'allegro', 'allievo', 'allodola', 'allusivo', 'almeno', 'alogeno', 'alpaca', 'alpestre', 'altalena', 'alterno', 'alticcio', 'altrove', 'alunno', 'alveolo', 'alzare', 'amalgama', 'amanita', 'amarena', 'ambito', 'ambrato', 'ameba', 'america', 'ametista', 'amico', 'ammasso', 'ammenda', 'ammirare', 'ammonito', 'amore', 'ampio', 'ampliare', 'amuleto', 'anacardo', 'anagrafe', 'analista', 'anarchia', 'anatra', 'anca', 'ancella', 'ancora', 'andare', 'andrea', 'anello', 'angelo', 'angolare', 'angusto', 'anima', 'annegare', 'annidato', 'anno', 'annuncio', 'anonimo', 'anticipo', 'anzi', 'apatico', 'apertura', 'apode', 'apparire', 'appetito', 'appoggio', 'approdo', 'appunto', 'aprile', 'arabica', 'arachide', 'aragosta', 'araldica', 'arancio', 'aratura', 'arazzo', 'arbitro', 'archivio', 'ardito', 'arenile', 'argento', 'argine', 'arguto', 'aria', 'armonia', 'arnese', 'arredato', 'arringa', 'arrosto', 'arsenico', 'arso', 'artefice', 'arzillo', 'asciutto', 'ascolto', 'asepsi', 'asettico', 'asfalto', 'asino', 'asola', 'aspirato', 'aspro', 'assaggio', 'asse', 'assoluto', 'assurdo', 'asta', 'astenuto', 'astice', 'astratto', 'atavico', 'ateismo', 'atomico', 'atono', 'attesa', 'attivare', 'attorno', 'attrito', 'attuale', 'ausilio', 'austria', 'autista', 'autonomo', 'autunno', 'avanzato', 'avere', 'avvenire', 'avviso', 'avvolgere', 'azione', 'azoto', 'azzimo', 'azzurro', 'babele', 'baccano', 'bacino', 'baco', 'badessa', 'badilata', 'bagnato', 'baita', 'balcone', 'baldo', 'balena', 'ballata', 'balzano', 'bambino', 'bandire', 'baraonda', 'barbaro', 'barca', 'baritono', 'barlume', 'barocco', 'basilico', 'basso', 'batosta', 'battuto', 'baule', 'bava', 'bavosa', 'becco', 'beffa', 'belgio', 'belva', 'benda', 'benevole', 'benigno', 'benzina', 'bere', 'berlina', 'beta', 'bibita', 'bici', 'bidone', 'bifido', 'biga', 'bilancia', 'bimbo', 'binocolo', 'biologo', 'bipede', 'bipolare', 'birbante', 'birra', 'biscotto', 'bisesto', 'bisnonno', 'bisonte', 'bisturi', 'bizzarro', 'blando', 'blatta', 'bollito', 'bonifico', 'bordo', 'bosco', 'botanico', 'bottino', 'bozzolo', 'braccio', 'bradipo', 'brama', 'branca', 'bravura', 'bretella', 'brevetto', 'brezza', 'briglia', 'brillante', 'brindare', 'broccolo', 'brodo', 'bronzina', 'brullo', 'bruno', 'bubbone', 'buca', 'budino', 'buffone', 'buio', 'bulbo', 'buono', 'burlone', 'burrasca', 'bussola', 'busta', 'cadetto', 'caduco', 'calamaro', 'calcolo', 'calesse', 'calibro', 'calmo', 'caloria', 'cambusa', 'camerata', 'camicia', 'cammino', 'camola', 'campale', 'canapa', 'candela', 'cane', 'canino', 'canotto', 'cantina', 'capace', 'capello', 'capitolo', 'capogiro', 'cappero', 'capra', 'capsula', 'carapace', 'carcassa', 'cardo', 'carisma', 'carovana', 'carretto', 'cartolina', 'casaccio', 'cascata', 'caserma', 'caso', 'cassone', 'castello', 'casuale', 'catasta', 'catena', 'catrame', 'cauto', 'cavillo', 'cedibile', 'cedrata', 'cefalo', 'celebre', 'cellulare', 'cena', 'cenone', 'centesimo', 'ceramica', 'cercare', 'certo', 'cerume', 'cervello', 'cesoia', 'cespo', 'ceto', 'chela', 'chiaro', 'chicca', 'chiedere', 'chimera', 'china', 'chirurgo', 'chitarra', 'ciao', 'ciclismo', 'cifrare', 'cigno', 'cilindro', 'ciottolo', 'circa', 'cirrosi', 'citrico', 'cittadino', 'ciuffo', 'civetta', 'civile', 'classico', 'clinica', 'cloro', 'cocco', 'codardo', 'codice', 'coerente', 'cognome', 'collare', 'colmato', 'colore', 'colposo', 'coltivato', 'colza', 'coma', 'cometa', 'commando', 'comodo', 'computer', 'comune', 'conciso', 'condurre', 'conferma', 'congelare', 'coniuge', 'connesso', 'conoscere', 'consumo', 'continuo', 'convegno', 'coperto', 'copione', 'coppia', 'copricapo', 'corazza', 'cordata', 'coricato', 'cornice', 'corolla', 'corpo', 'corredo', 'corsia', 'cortese', 'cosmico', 'costante', 'cottura', 'covato', 'cratere', 'cravatta', 'creato', 'credere', 'cremoso', 'crescita', 'creta', 'criceto', 'crinale', 'crisi', 'critico', 'croce', 'cronaca', 'crostata', 'cruciale', 'crusca', 'cucire', 'cuculo', 'cugino', 'cullato', 'cupola', 'curatore', 'cursore', 'curvo', 'cuscino', 'custode', 'dado', 'daino', 'dalmata', 'damerino', 'daniela', 'dannoso', 'danzare', 'datato', 'davanti', 'davvero', 'debutto', 'decennio', 'deciso', 'declino', 'decollo', 'decreto', 'dedicato', 'definito', 'deforme', 'degno', 'delegare', 'delfino', 'delirio', 'delta', 'demenza', 'denotato', 'dentro', 'deposito', 'derapata', 'derivare', 'deroga', 'descritto', 'deserto', 'desiderio', 'desumere', 'detersivo', 'devoto', 'diametro', 'dicembre', 'diedro', 'difeso', 'diffuso', 'digerire', 'digitale', 'diluvio', 'dinamico', 'dinnanzi', 'dipinto', 'diploma', 'dipolo', 'diradare', 'dire', 'dirotto', 'dirupo', 'disagio', 'discreto', 'disfare', 'disgelo', 'disposto', 'distanza', 'disumano', 'dito', 'divano', 'divelto', 'dividere', 'divorato', 'doblone', 'docente', 'doganale', 'dogma', 'dolce', 'domato', 'domenica', 'dominare', 'dondolo', 'dono', 'dormire', 'dote', 'dottore', 'dovuto', 'dozzina', 'drago', 'druido', 'dubbio', 'dubitare', 'ducale', 'duna', 'duomo', 'duplice', 'duraturo', 'ebano', 'eccesso', 'ecco', 'eclissi', 'economia', 'edera', 'edicola', 'edile', 'editoria', 'educare', 'egemonia', 'egli', 'egoismo', 'egregio', 'elaborato', 'elargire', 'elegante', 'elencato', 'eletto', 'elevare', 'elfico', 'elica', 'elmo', 'elsa', 'eluso', 'emanato', 'emblema', 'emesso', 'emiro', 'emotivo', 'emozione', 'empirico', 'emulo', 'endemico', 'enduro', 'energia', 'enfasi', 'enoteca', 'entrare', 'enzima', 'epatite', 'epilogo', 'episodio', 'epocale', 'eppure', 'equatore', 'erario', 'erba', 'erboso', 'erede', 'eremita', 'erigere', 'ermetico', 'eroe', 'erosivo', 'errante', 'esagono', 'esame', 'esanime', 'esaudire', 'esca', 'esempio', 'esercito', 'esibito', 'esigente', 'esistere', 'esito', 'esofago', 'esortato', 'esoso', 'espanso', 'espresso', 'essenza', 'esso', 'esteso', 'estimare', 'estonia', 'estroso', 'esultare', 'etilico', 'etnico', 'etrusco', 'etto', 'euclideo', 'europa', 'evaso', 'evidenza', 'evitato', 'evoluto', 'evviva', 'fabbrica', 'faccenda', 'fachiro', 'falco', 'famiglia', 'fanale', 'fanfara', 'fango', 'fantasma', 'fare', 'farfalla', 'farinoso', 'farmaco', 'fascia', 'fastoso', 'fasullo', 'faticare', 'fato', 'favoloso', 'febbre', 'fecola', 'fede', 'fegato', 'felpa', 'feltro', 'femmina', 'fendere', 'fenomeno', 'fermento', 'ferro', 'fertile', 'fessura', 'festivo', 'fetta', 'feudo', 'fiaba', 'fiducia', 'fifa', 'figurato', 'filo', 'finanza', 'finestra', 'finire', 'fiore', 'fiscale', 'fisico', 'fiume', 'flacone', 'flamenco', 'flebo', 'flemma', 'florido', 'fluente', 'fluoro', 'fobico', 'focaccia', 'focoso', 'foderato', 'foglio', 'folata', 'folclore', 'folgore', 'fondente', 'fonetico', 'fonia', 'fontana', 'forbito', 'forchetta', 'foresta', 'formica', 'fornaio', 'foro', 'fortezza', 'forzare', 'fosfato', 'fosso', 'fracasso', 'frana', 'frassino', 'fratello', 'freccetta', 'frenata', 'fresco', 'frigo', 'frollino', 'fronde', 'frugale', 'frutta', 'fucilata', 'fucsia', 'fuggente', 'fulmine', 'fulvo', 'fumante', 'fumetto', 'fumoso', 'fune', 'funzione', 'fuoco', 'furbo', 'furgone', 'furore', 'fuso', 'futile', 'gabbiano', 'gaffe', 'galateo', 'gallina', 'galoppo', 'gambero', 'gamma', 'garanzia', 'garbo', 'garofano', 'garzone', 'gasdotto', 'gasolio', 'gastrico', 'gatto', 'gaudio', 'gazebo', 'gazzella', 'geco', 'gelatina', 'gelso', 'gemello', 'gemmato', 'gene', 'genitore', 'gennaio', 'genotipo', 'gergo', 'ghepardo', 'ghiaccio', 'ghisa', 'giallo', 'gilda', 'ginepro', 'giocare', 'gioiello', 'giorno', 'giove', 'girato', 'girone', 'gittata', 'giudizio', 'giurato', 'giusto', 'globulo', 'glutine', 'gnomo', 'gobba', 'golf', 'gomito', 'gommone', 'gonfio', 'gonna', 'governo', 'gracile', 'grado', 'grafico', 'grammo', 'grande', 'grattare', 'gravoso', 'grazia', 'greca', 'gregge', 'grifone', 'grigio', 'grinza', 'grotta', 'gruppo', 'guadagno', 'guaio', 'guanto', 'guardare', 'gufo', 'guidare', 'ibernato', 'icona', 'identico', 'idillio', 'idolo', 'idra', 'idrico', 'idrogeno', 'igiene', 'ignaro', 'ignorato', 'ilare', 'illeso', 'illogico', 'illudere', 'imballo', 'imbevuto', 'imbocco', 'imbuto', 'immane', 'immerso', 'immolato', 'impacco', 'impeto', 'impiego', 'importo', 'impronta', 'inalare', 'inarcare', 'inattivo', 'incanto', 'incendio', 'inchino', 'incisivo', 'incluso', 'incontro', 'incrocio', 'incubo', 'indagine', 'india', 'indole', 'inedito', 'infatti', 'infilare', 'inflitto', 'ingaggio', 'ingegno', 'inglese', 'ingordo', 'ingrosso', 'innesco', 'inodore', 'inoltrare', 'inondato', 'insano', 'insetto', 'insieme', 'insonnia', 'insulina', 'intasato', 'intero', 'intonaco', 'intuito', 'inumidire', 'invalido', 'invece', 'invito', 'iperbole', 'ipnotico', 'ipotesi', 'ippica', 'iride', 'irlanda', 'ironico', 'irrigato', 'irrorare', 'isolato', 'isotopo', 'isterico', 'istituto', 'istrice', 'italia', 'iterare', 'labbro', 'labirinto', 'lacca', 'lacerato', 'lacrima', 'lacuna', 'laddove', 'lago', 'lampo', 'lancetta', 'lanterna', 'lardoso', 'larga', 'laringe', 'lastra', 'latenza', 'latino', 'lattuga', 'lavagna', 'lavoro', 'legale', 'leggero', 'lembo', 'lentezza', 'lenza', 'leone', 'lepre', 'lesivo', 'lessato', 'lesto', 'letterale', 'leva', 'levigato', 'libero', 'lido', 'lievito', 'lilla', 'limatura', 'limitare', 'limpido', 'lineare', 'lingua', 'liquido', 'lira', 'lirica', 'lisca', 'lite', 'litigio', 'livrea', 'locanda', 'lode', 'logica', 'lombare', 'londra', 'longevo', 'loquace', 'lorenzo', 'loto', 'lotteria', 'luce', 'lucidato', 'lumaca', 'luminoso', 'lungo', 'lupo', 'luppolo', 'lusinga', 'lusso', 'lutto', 'macabro', 'macchina', 'macero', 'macinato', 'madama', 'magico', 'maglia', 'magnete', 'magro', 'maiolica', 'malafede', 'malgrado', 'malinteso', 'malsano', 'malto', 'malumore', 'mana', 'mancia', 'mandorla', 'mangiare', 'manifesto', 'mannaro', 'manovra', 'mansarda', 'mantide', 'manubrio', 'mappa', 'maratona', 'marcire', 'maretta', 'marmo', 'marsupio', 'maschera', 'massaia', 'mastino', 'materasso', 'matricola', 'mattone', 'maturo', 'mazurca', 'meandro', 'meccanico', 'mecenate', 'medesimo', 'meditare', 'mega', 'melassa', 'melis', 'melodia', 'meninge', 'meno', 'mensola', 'mercurio', 'merenda', 'merlo', 'meschino', 'mese', 'messere', 'mestolo', 'metallo', 'metodo', 'mettere', 'miagolare', 'mica', 'micelio', 'michele', 'microbo', 'midollo', 'miele', 'migliore', 'milano', 'milite', 'mimosa', 'minerale', 'mini', 'minore', 'mirino', 'mirtillo', 'miscela', 'missiva', 'misto', 'misurare', 'mitezza', 'mitigare', 'mitra', 'mittente', 'mnemonico', 'modello', 'modifica', 'modulo', 'mogano', 'mogio', 'mole', 'molosso', 'monastero', 'monco', 'mondina', 'monetario', 'monile', 'monotono', 'monsone', 'montato', 'monviso', 'mora', 'mordere', 'morsicato', 'mostro', 'motivato', 'motosega', 'motto', 'movenza', 'movimento', 'mozzo', 'mucca', 'mucosa', 'muffa', 'mughetto', 'mugnaio', 'mulatto', 'mulinello', 'multiplo', 'mummia', 'munto', 'muovere', 'murale', 'musa', 'muscolo', 'musica', 'mutevole', 'muto', 'nababbo', 'nafta', 'nanometro', 'narciso', 'narice', 'narrato', 'nascere', 'nastrare', 'naturale', 'nautica', 'naviglio', 'nebulosa', 'necrosi', 'negativo', 'negozio', 'nemmeno', 'neofita', 'neretto', 'nervo', 'nessuno', 'nettuno', 'neutrale', 'neve', 'nevrotico', 'nicchia', 'ninfa', 'nitido', 'nobile', 'nocivo', 'nodo', 'nome', 'nomina', 'nordico', 'normale', 'norvegese', 'nostrano', 'notare', 'notizia', 'notturno', 'novella', 'nucleo', 'nulla', 'numero', 'nuovo', 'nutrire', 'nuvola', 'nuziale', 'oasi', 'obbedire', 'obbligo', 'obelisco', 'oblio', 'obolo', 'obsoleto', 'occasione', 'occhio', 'occidente', 'occorrere', 'occultare', 'ocra', 'oculato', 'odierno', 'odorare', 'offerta', 'offrire', 'offuscato', 'oggetto', 'oggi', 'ognuno', 'olandese', 'olfatto', 'oliato', 'oliva', 'ologramma', 'oltre', 'omaggio', 'ombelico', 'ombra', 'omega', 'omissione', 'ondoso', 'onere', 'onice', 'onnivoro', 'onorevole', 'onta', 'operato', 'opinione', 'opposto', 'oracolo', 'orafo', 'ordine', 'orecchino', 'orefice', 'orfano', 'organico', 'origine', 'orizzonte', 'orma', 'ormeggio', 'ornativo', 'orologio', 'orrendo', 'orribile', 'ortensia', 'ortica', 'orzata', 'orzo', 'osare', 'oscurare', 'osmosi', 'ospedale', 'ospite', 'ossa', 'ossidare', 'ostacolo', 'oste', 'otite', 'otre', 'ottagono', 'ottimo', 'ottobre', 'ovale', 'ovest', 'ovino', 'oviparo', 'ovocito', 'ovunque', 'ovviare', 'ozio', 'pacchetto', 'pace', 'pacifico', 'padella', 'padrone', 'paese', 'paga', 'pagina', 'palazzina', 'palesare', 'pallido', 'palo', 'palude', 'pandoro', 'pannello', 'paolo', 'paonazzo', 'paprica', 'parabola', 'parcella', 'parere', 'pargolo', 'pari', 'parlato', 'parola', 'partire', 'parvenza', 'parziale', 'passivo', 'pasticca', 'patacca', 'patologia', 'pattume', 'pavone', 'peccato', 'pedalare', 'pedonale', 'peggio', 'peloso', 'penare', 'pendice', 'penisola', 'pennuto', 'penombra', 'pensare', 'pentola', 'pepe', 'pepita', 'perbene', 'percorso', 'perdonato', 'perforare', 'pergamena', 'periodo', 'permesso', 'perno', 'perplesso', 'persuaso', 'pertugio', 'pervaso', 'pesatore', 'pesista', 'peso', 'pestifero', 'petalo', 'pettine', 'petulante', 'pezzo', 'piacere', 'pianta', 'piattino', 'piccino', 'picozza', 'piega', 'pietra', 'piffero', 'pigiama', 'pigolio', 'pigro', 'pila', 'pilifero', 'pillola', 'pilota', 'pimpante', 'pineta', 'pinna', 'pinolo', 'pioggia', 'piombo', 'piramide', 'piretico', 'pirite', 'pirolisi', 'pitone', 'pizzico', 'placebo', 'planare', 'plasma', 'platano', 'plenario', 'pochezza', 'poderoso', 'podismo', 'poesia', 'poggiare', 'polenta', 'poligono', 'pollice', 'polmonite', 'polpetta', 'polso', 'poltrona', 'polvere', 'pomice', 'pomodoro', 'ponte', 'popoloso', 'porfido', 'poroso', 'porpora', 'porre', 'portata', 'posa', 'positivo', 'possesso', 'postulato', 'potassio', 'potere', 'pranzo', 'prassi', 'pratica', 'precluso', 'predica', 'prefisso', 'pregiato', 'prelievo', 'premere', 'prenotare', 'preparato', 'presenza', 'pretesto', 'prevalso', 'prima', 'principe', 'privato', 'problema', 'procura', 'produrre', 'profumo', 'progetto', 'prolunga', 'promessa', 'pronome', 'proposta', 'proroga', 'proteso', 'prova', 'prudente', 'prugna', 'prurito', 'psiche', 'pubblico', 'pudica', 'pugilato', 'pugno', 'pulce', 'pulito', 'pulsante', 'puntare', 'pupazzo', 'pupilla', 'puro', 'quadro', 'qualcosa', 'quasi', 'querela', 'quota', 'raccolto', 'raddoppio', 'radicale', 'radunato', 'raffica', 'ragazzo', 'ragione', 'ragno', 'ramarro', 'ramingo', 'ramo', 'randagio', 'rantolare', 'rapato', 'rapina', 'rappreso', 'rasatura', 'raschiato', 'rasente', 'rassegna', 'rastrello', 'rata', 'ravveduto', 'reale', 'recepire', 'recinto', 'recluta', 'recondito', 'recupero', 'reddito', 'redimere', 'regalato', 'registro', 'regola', 'regresso', 'relazione', 'remare', 'remoto', 'renna', 'replica', 'reprimere', 'reputare', 'resa', 'residente', 'responso', 'restauro', 'rete', 'retina', 'retorica', 'rettifica', 'revocato', 'riassunto', 'ribadire', 'ribelle', 'ribrezzo', 'ricarica', 'ricco', 'ricevere', 'riciclato', 'ricordo', 'ricreduto', 'ridicolo', 'ridurre', 'rifasare', 'riflesso', 'riforma', 'rifugio', 'rigare', 'rigettato', 'righello', 'rilassato', 'rilevato', 'rimanere', 'rimbalzo', 'rimedio', 'rimorchio', 'rinascita', 'rincaro', 'rinforzo', 'rinnovo', 'rinomato', 'rinsavito', 'rintocco', 'rinuncia', 'rinvenire', 'riparato', 'ripetuto', 'ripieno', 'riportare', 'ripresa', 'ripulire', 'risata', 'rischio', 'riserva', 'risibile', 'riso', 'rispetto', 'ristoro', 'risultato', 'risvolto', 'ritardo', 'ritegno', 'ritmico', 'ritrovo', 'riunione', 'riva', 'riverso', 'rivincita', 'rivolto', 'rizoma', 'roba', 'robotico', 'robusto', 'roccia', 'roco', 'rodaggio', 'rodere', 'roditore', 'rogito', 'rollio', 'romantico', 'rompere', 'ronzio', 'rosolare', 'rospo', 'rotante', 'rotondo', 'rotula', 'rovescio', 'rubizzo', 'rubrica', 'ruga', 'rullino', 'rumine', 'rumoroso', 'ruolo', 'rupe', 'russare', 'rustico', 'sabato', 'sabbiare', 'sabotato', 'sagoma', 'salasso', 'saldatura', 'salgemma', 'salivare', 'salmone', 'salone', 'saltare', 'saluto', 'salvo', 'sapere', 'sapido', 'saporito', 'saraceno', 'sarcasmo', 'sarto', 'sassoso', 'satellite', 'satira', 'satollo', 'saturno', 'savana', 'savio', 'saziato', 'sbadiglio', 'sbalzo', 'sbancato', 'sbarra', 'sbattere', 'sbavare', 'sbendare', 'sbirciare', 'sbloccato', 'sbocciato', 'sbrinare', 'sbruffone', 'sbuffare', 'scabroso', 'scadenza', 'scala', 'scambiare', 'scandalo', 'scapola', 'scarso', 'scatenare', 'scavato', 'scelto', 'scenico', 'scettro', 'scheda', 'schiena', 'sciarpa', 'scienza', 'scindere', 'scippo', 'sciroppo', 'scivolo', 'sclerare', 'scodella', 'scolpito', 'scomparto', 'sconforto', 'scoprire', 'scorta', 'scossone', 'scozzese', 'scriba', 'scrollare', 'scrutinio', 'scuderia', 'scultore', 'scuola', 'scuro', 'scusare', 'sdebitare', 'sdoganare', 'seccatura', 'secondo', 'sedano', 'seggiola', 'segnalato', 'segregato', 'seguito', 'selciato', 'selettivo', 'sella', 'selvaggio', 'semaforo', 'sembrare', 'seme', 'seminato', 'sempre', 'senso', 'sentire', 'sepolto', 'sequenza', 'serata', 'serbato', 'sereno', 'serio', 'serpente', 'serraglio', 'servire', 'sestina', 'setola', 'settimana', 'sfacelo', 'sfaldare', 'sfamato', 'sfarzoso', 'sfaticato', 'sfera', 'sfida', 'sfilato', 'sfinge', 'sfocato', 'sfoderare', 'sfogo', 'sfoltire', 'sforzato', 'sfratto', 'sfruttato', 'sfuggito', 'sfumare', 'sfuso', 'sgabello', 'sgarbato', 'sgonfiare', 'sgorbio', 'sgrassato', 'sguardo', 'sibilo', 'siccome', 'sierra', 'sigla', 'signore', 'silenzio', 'sillaba', 'simbolo', 'simpatico', 'simulato', 'sinfonia', 'singolo', 'sinistro', 'sino', 'sintesi', 'sinusoide', 'sipario', 'sisma', 'sistole', 'situato', 'slitta', 'slogatura', 'sloveno', 'smarrito', 'smemorato', 'smentito', 'smeraldo', 'smilzo', 'smontare', 'smottato', 'smussato', 'snellire', 'snervato', 'snodo', 'sobbalzo', 'sobrio', 'soccorso', 'sociale', 'sodale', 'soffitto', 'sogno', 'soldato', 'solenne', 'solido', 'sollazzo', 'solo', 'solubile', 'solvente', 'somatico', 'somma', 'sonda', 'sonetto', 'sonnifero', 'sopire', 'soppeso', 'sopra', 'sorgere', 'sorpasso', 'sorriso', 'sorso', 'sorteggio', 'sorvolato', 'sospiro', 'sosta', 'sottile', 'spada', 'spalla', 'spargere', 'spatola', 'spavento', 'spazzola', 'specie', 'spedire', 'spegnere', 'spelatura', 'speranza', 'spessore', 'spettrale', 'spezzato', 'spia', 'spigoloso', 'spillato', 'spinoso', 'spirale', 'splendido', 'sportivo', 'sposo', 'spranga', 'sprecare', 'spronato', 'spruzzo', 'spuntino', 'squillo', 'sradicare', 'srotolato', 'stabile', 'stacco', 'staffa', 'stagnare', 'stampato', 'stantio', 'starnuto', 'stasera', 'statuto', 'stelo', 'steppa', 'sterzo', 'stiletto', 'stima', 'stirpe', 'stivale', 'stizzoso', 'stonato', 'storico', 'strappo', 'stregato', 'stridulo', 'strozzare', 'strutto', 'stuccare', 'stufo', 'stupendo', 'subentro', 'succoso', 'sudore', 'suggerito', 'sugo', 'sultano', 'suonare', 'superbo', 'supporto', 'surgelato', 'surrogato', 'sussurro', 'sutura', 'svagare', 'svedese', 'sveglio', 'svelare', 'svenuto', 'svezia', 'sviluppo', 'svista', 'svizzera', 'svolta', 'svuotare', 'tabacco', 'tabulato', 'tacciare', 'taciturno', 'tale', 'talismano', 'tampone', 'tannino', 'tara', 'tardivo', 'targato', 'tariffa', 'tarpare', 'tartaruga', 'tasto', 'tattico', 'taverna', 'tavolata', 'tazza', 'teca', 'tecnico', 'telefono', 'temerario', 'tempo', 'temuto', 'tendone', 'tenero', 'tensione', 'tentacolo', 'teorema', 'terme', 'terrazzo', 'terzetto', 'tesi', 'tesserato', 'testato', 'tetro', 'tettoia', 'tifare', 'tigella', 'timbro', 'tinto', 'tipico', 'tipografo', 'tiraggio', 'tiro', 'titanio', 'titolo', 'titubante', 'tizio', 'tizzone', 'toccare', 'tollerare', 'tolto', 'tombola', 'tomo', 'tonfo', 'tonsilla', 'topazio', 'topologia', 'toppa', 'torba', 'tornare', 'torrone', 'tortora', 'toscano', 'tossire', 'tostatura', 'totano', 'trabocco', 'trachea', 'trafila', 'tragedia', 'tralcio', 'tramonto', 'transito', 'trapano', 'trarre', 'trasloco', 'trattato', 'trave', 'treccia', 'tremolio', 'trespolo', 'tributo', 'tricheco', 'trifoglio', 'trillo', 'trincea', 'trio', 'tristezza', 'triturato', 'trivella', 'tromba', 'trono', 'troppo', 'trottola', 'trovare', 'truccato', 'tubatura', 'tuffato', 'tulipano', 'tumulto', 'tunisia', 'turbare', 'turchino', 'tuta', 'tutela', 'ubicato', 'uccello', 'uccisore', 'udire', 'uditivo', 'uffa', 'ufficio', 'uguale', 'ulisse', 'ultimato', 'umano', 'umile', 'umorismo', 'uncinetto', 'ungere', 'ungherese', 'unicorno', 'unificato', 'unisono', 'unitario', 'unte', 'uovo', 'upupa', 'uragano', 'urgenza', 'urlo', 'usanza', 'usato', 'uscito', 'usignolo', 'usuraio', 'utensile', 'utilizzo', 'utopia', 'vacante', 'vaccinato', 'vagabondo', 'vagliato', 'valanga', 'valgo', 'valico', 'valletta', 'valoroso', 'valutare', 'valvola', 'vampata', 'vangare', 'vanitoso', 'vano', 'vantaggio', 'vanvera', 'vapore', 'varano', 'varcato', 'variante', 'vasca', 'vedetta', 'vedova', 'veduto', 'vegetale', 'veicolo', 'velcro', 'velina', 'velluto', 'veloce', 'venato', 'vendemmia', 'vento', 'verace', 'verbale', 'vergogna', 'verifica', 'vero', 'verruca', 'verticale', 'vescica', 'vessillo', 'vestale', 'veterano', 'vetrina', 'vetusto', 'viandante', 'vibrante', 'vicenda', 'vichingo', 'vicinanza', 'vidimare', 'vigilia', 'vigneto', 'vigore', 'vile', 'villano', 'vimini', 'vincitore', 'viola', 'vipera', 'virgola', 'virologo', 'virulento', 'viscoso', 'visione', 'vispo', 'vissuto', 'visura', 'vita', 'vitello', 'vittima', 'vivanda', 'vivido', 'viziare', 'voce', 'voga', 'volatile', 'volere', 'volpe', 'voragine', 'vulcano', 'zampogna', 'zanna', 'zappato', 'zattera', 'zavorra', 'zefiro', 'zelante', 'zelo', 'zenzero', 'zerbino', 'zibetto', 'zinco', 'zircone', 'zitto', 'zolla', 'zotico', 'zucchero', 'zufolo', 'zulu', 'zuppa']; | |
module.exports = italian; | |
},{}],97:[function(require,module,exports){ | |
'use strict'; | |
var japanese = ['あいこくしん', 'あいさつ', 'あいだ', 'あおぞら', 'あかちゃん', 'あきる', 'あけがた', 'あける', 'あこがれる', 'あさい', 'あさひ', 'あしあと', 'あじわう', 'あずかる', 'あずき', 'あそぶ', 'あたえる', 'あたためる', 'あたりまえ', 'あたる', 'あつい', 'あつかう', 'あっしゅく', 'あつまり', 'あつめる', 'あてな', 'あてはまる', 'あひる', 'あぶら', 'あぶる', 'あふれる', 'あまい', 'あまど', 'あまやかす', 'あまり', 'あみもの', 'あめりか', 'あやまる', 'あゆむ', 'あらいぐま', 'あらし', 'あらすじ', 'あらためる', 'あらゆる', 'あらわす', 'ありがとう', 'あわせる', 'あわてる', 'あんい', 'あんがい', 'あんこ', 'あんぜん', 'あんてい', 'あんない', 'あんまり', 'いいだす', 'いおん', 'いがい', 'いがく', 'いきおい', 'いきなり', 'いきもの', 'いきる', 'いくじ', 'いくぶん', 'いけばな', 'いけん', 'いこう', 'いこく', 'いこつ', 'いさましい', 'いさん', 'いしき', 'いじゅう', 'いじょう', 'いじわる', 'いずみ', 'いずれ', 'いせい', 'いせえび', 'いせかい', 'いせき', 'いぜん', 'いそうろう', 'いそがしい', 'いだい', 'いだく', 'いたずら', 'いたみ', 'いたりあ', 'いちおう', 'いちじ', 'いちど', 'いちば', 'いちぶ', 'いちりゅう', 'いつか', 'いっしゅん', 'いっせい', 'いっそう', 'いったん', 'いっち', 'いってい', 'いっぽう', 'いてざ', 'いてん', 'いどう', 'いとこ', 'いない', 'いなか', 'いねむり', 'いのち', 'いのる', 'いはつ', 'いばる', 'いはん', 'いびき', 'いひん', 'いふく', 'いへん', 'いほう', 'いみん', 'いもうと', 'いもたれ', 'いもり', 'いやがる', 'いやす', 'いよかん', 'いよく', 'いらい', 'いらすと', 'いりぐち', 'いりょう', 'いれい', 'いれもの', 'いれる', 'いろえんぴつ', 'いわい', 'いわう', 'いわかん', 'いわば', 'いわゆる', 'いんげんまめ', 'いんさつ', 'いんしょう', 'いんよう', 'うえき', 'うえる', 'うおざ', 'うがい', 'うかぶ', 'うかべる', 'うきわ', 'うくらいな', 'うくれれ', 'うけたまわる', 'うけつけ', 'うけとる', 'うけもつ', 'うける', 'うごかす', 'うごく', 'うこん', 'うさぎ', 'うしなう', 'うしろがみ', 'うすい', 'うすぎ', 'うすぐらい', 'うすめる', 'うせつ', 'うちあわせ', 'うちがわ', 'うちき', 'うちゅう', 'うっかり', 'うつくしい', 'うったえる', 'うつる', 'うどん', 'うなぎ', 'うなじ', 'うなずく', 'うなる', 'うねる', 'うのう', 'うぶげ', 'うぶごえ', 'うまれる', 'うめる', 'うもう', 'うやまう', 'うよく', 'うらがえす', 'うらぐち', 'うらない', 'うりあげ', 'うりきれ', 'うるさい', 'うれしい', 'うれゆき', 'うれる', 'うろこ', 'うわき', 'うわさ', 'うんこう', 'うんちん', 'うんてん', 'うんどう', 'えいえん', 'えいが', 'えいきょう', 'えいご', 'えいせい', 'えいぶん', 'えいよう', 'えいわ', 'えおり', 'えがお', 'えがく', 'えきたい', 'えくせる', 'えしゃく', 'えすて', 'えつらん', 'えのぐ', 'えほうまき', 'えほん', 'えまき', 'えもじ', 'えもの', 'えらい', 'えらぶ', 'えりあ', 'えんえん', 'えんかい', 'えんぎ', 'えんげき', 'えんしゅう', 'えんぜつ', 'えんそく', 'えんちょう', 'えんとつ', 'おいかける', 'おいこす', 'おいしい', 'おいつく', 'おうえん', 'おうさま', 'おうじ', 'おうせつ', 'おうたい', 'おうふく', 'おうべい', 'おうよう', 'おえる', 'おおい', 'おおう', 'おおどおり', 'おおや', 'おおよそ', 'おかえり', 'おかず', 'おがむ', 'おかわり', 'おぎなう', 'おきる', 'おくさま', 'おくじょう', 'おくりがな', 'おくる', 'おくれる', 'おこす', 'おこなう', 'おこる', 'おさえる', 'おさない', 'おさめる', 'おしいれ', 'おしえる', 'おじぎ', 'おじさん', 'おしゃれ', 'おそらく', 'おそわる', 'おたがい', 'おたく', 'おだやか', 'おちつく', 'おっと', 'おつり', 'おでかけ', 'おとしもの', 'おとなしい', 'おどり', 'おどろかす', 'おばさん', 'おまいり', 'おめでとう', 'おもいで', 'おもう', 'おもたい', 'おもちゃ', 'おやつ', 'おやゆび', 'およぼす', 'おらんだ', 'おろす', 'おんがく', 'おんけい', 'おんしゃ', 'おんせん', 'おんだん', 'おんちゅう', 'おんどけい', 'かあつ', 'かいが', 'がいき', 'がいけん', 'がいこう', 'かいさつ', 'かいしゃ', 'かいすいよく', 'かいぜん', 'かいぞうど', 'かいつう', 'かいてん', 'かいとう', 'かいふく', 'がいへき', 'かいほう', 'かいよう', 'がいらい', 'かいわ', 'かえる', 'かおり', 'かかえる', 'かがく', 'かがし', 'かがみ', 'かくご', 'かくとく', 'かざる', 'がぞう', 'かたい', 'かたち', 'がちょう', 'がっきゅう', 'がっこう', 'がっさん', 'がっしょう', 'かなざわし', 'かのう', 'がはく', 'かぶか', 'かほう', 'かほご', 'かまう', 'かまぼこ', 'かめれおん', 'かゆい', 'かようび', 'からい', 'かるい', 'かろう', 'かわく', 'かわら', 'がんか', 'かんけい', 'かんこう', 'かんしゃ', 'かんそう', 'かんたん', 'かんち', 'がんばる', 'きあい', 'きあつ', 'きいろ', 'ぎいん', 'きうい', 'きうん', 'きえる', 'きおう', 'きおく', 'きおち', 'きおん', 'きかい', 'きかく', 'きかんしゃ', 'ききて', 'きくばり', 'きくらげ', 'きけんせい', 'きこう', 'きこえる', 'きこく', 'きさい', 'きさく', 'きさま', 'きさらぎ', 'ぎじかがく', 'ぎしき', 'ぎじたいけん', 'ぎじにってい', 'ぎじゅつしゃ', 'きすう', 'きせい', 'きせき', 'きせつ', 'きそう', 'きぞく', 'きぞん', 'きたえる', 'きちょう', 'きつえん', 'ぎっちり', 'きつつき', 'きつね', 'きてい', 'きどう', 'きどく', 'きない', 'きなが', 'きなこ', 'きぬごし', 'きねん', 'きのう', 'きのした', 'きはく', 'きびしい', 'きひん', 'きふく', 'きぶん', 'きぼう', 'きほん', 'きまる', 'きみつ', 'きむずかしい', 'きめる', 'きもだめし', 'きもち', 'きもの', 'きゃく', 'きやく', 'ぎゅうにく', 'きよう', 'きょうりゅう', 'きらい', 'きらく', 'きりん', 'きれい', 'きれつ', 'きろく', 'ぎろん', 'きわめる', 'ぎんいろ', 'きんかくじ', 'きんじょ', 'きんようび', 'ぐあい', 'くいず', 'くうかん', 'くうき', 'くうぐん', 'くうこう', 'ぐうせい', 'くうそう', 'ぐうたら', 'くうふく', 'くうぼ', 'くかん', 'くきょう', 'くげん', 'ぐこう', 'くさい', 'くさき', 'くさばな', 'くさる', 'くしゃみ', 'くしょう', 'くすのき', 'くすりゆび', 'くせげ', 'くせん', 'ぐたいてき', 'くださる', 'くたびれる', 'くちこみ', 'くちさき', 'くつした', 'ぐっすり', 'くつろぐ', 'くとうてん', 'くどく', 'くなん', 'くねくね', 'くのう', 'くふう', 'くみあわせ', 'くみたてる', 'くめる', 'くやくしょ', 'くらす', 'くらべる', 'くるま', 'くれる', 'くろう', 'くわしい', 'ぐんかん', 'ぐんしょく', 'ぐんたい', 'ぐんて', 'けあな', 'けいかく', 'けいけん', 'けいこ', 'けいさつ', 'げいじゅつ', 'けいたい', 'げいのうじん', 'けいれき', 'けいろ', 'けおとす', 'けおりもの', 'げきか', 'げきげん', 'げきだん', 'げきちん', 'げきとつ', 'げきは', 'げきやく', 'げこう', 'げこくじょう', 'げざい', 'けさき', 'げざん', 'けしき', 'けしごむ', 'けしょう', 'げすと', 'けたば', 'けちゃっぷ', 'けちらす', 'けつあつ', 'けつい', 'けつえき', 'けっこん', 'けつじょ', 'けっせき', 'けってい', 'けつまつ', 'げつようび', 'げつれい', 'けつろん', 'げどく', 'けとばす', 'けとる', 'けなげ', 'けなす', 'けなみ', 'けぬき', 'げねつ', 'けねん', 'けはい', 'げひん', 'けぶかい', 'げぼく', 'けまり', 'けみかる', 'けむし', 'けむり', 'けもの', 'けらい', 'けろけろ', 'けわしい', 'けんい', 'けんえつ', 'けんお', 'けんか', 'げんき', 'けんげん', 'けんこう', 'けんさく', 'けんしゅう', 'けんすう', 'げんそう', 'けんちく', 'けんてい', 'けんとう', 'けんない', 'けんにん', 'げんぶつ', 'けんま', 'けんみん', 'けんめい', 'けんらん', 'けんり', 'こあくま', 'こいぬ', 'こいびと', 'ごうい', 'こうえん', 'こうおん', 'こうかん', 'ごうきゅう', 'ごうけい', 'こうこう', 'こうさい', 'こうじ', 'こうすい', 'ごうせい', 'こうそく', 'こうたい', 'こうちゃ', 'こうつう', 'こうてい', 'こうどう', 'こうない', 'こうはい', 'ごうほう', 'ごうまん', 'こうもく', 'こうりつ', 'こえる', 'こおり', 'ごかい', 'ごがつ', 'ごかん', 'こくご', 'こくさい', 'こくとう', 'こくない', 'こくはく', 'こぐま', 'こけい', 'こける', 'ここのか', 'こころ', 'こさめ', 'こしつ', 'こすう', 'こせい', 'こせき', 'こぜん', 'こそだて', 'こたい', 'こたえる', 'こたつ', 'こちょう', 'こっか', 'こつこつ', 'こつばん', 'こつぶ', 'こてい', 'こてん', 'ことがら', 'ことし', 'ことば', 'ことり', 'こなごな', 'こねこね', 'このまま', 'このみ', 'このよ', 'ごはん', 'こひつじ', 'こふう', 'こふん', 'こぼれる', 'ごまあぶら', 'こまかい', 'ごますり', 'こまつな', 'こまる', 'こむぎこ', 'こもじ', 'こもち', 'こもの', 'こもん', 'こやく', 'こやま', 'こゆう', 'こゆび', 'こよい', 'こよう', 'こりる', 'これくしょん', 'ころっけ', 'こわもて', 'こわれる', 'こんいん', 'こんかい', 'こんき', 'こんしゅう', 'こんすい', 'こんだて', 'こんとん', 'こんなん', 'こんびに', 'こんぽん', 'こんまけ', 'こんや', 'こんれい', 'こんわく', 'ざいえき', 'さいかい', 'さいきん', 'ざいげん', 'ざいこ', 'さいしょ', 'さいせい', 'ざいたく', 'ざいちゅう', 'さいてき', 'ざいりょう', 'さうな', 'さかいし', 'さがす', 'さかな', 'さかみち', 'さがる', 'さぎょう', 'さくし', 'さくひん', 'さくら', 'さこく', 'さこつ', 'さずかる', 'ざせき', 'さたん', 'さつえい', 'ざつおん', 'ざっか', 'ざつがく', 'さっきょく', 'ざっし', 'さつじん', 'ざっそう', 'さつたば', 'さつまいも', 'さてい', 'さといも', 'さとう', 'さとおや', 'さとし', 'さとる', 'さのう', 'さばく', 'さびしい', 'さべつ', 'さほう', 'さほど', 'さます', 'さみしい', 'さみだれ', 'さむけ', 'さめる', 'さやえんどう', 'さゆう', 'さよう', 'さよく', 'さらだ', 'ざるそば', 'さわやか', 'さわる', 'さんいん', 'さんか', 'さんきゃく', 'さんこう', 'さんさい', 'ざんしょ', 'さんすう', 'さんせい', 'さんそ', 'さんち', 'さんま', 'さんみ', 'さんらん', 'しあい', 'しあげ', 'しあさって', 'しあわせ', 'しいく', 'しいん', 'しうち', 'しえい', 'しおけ', 'しかい', 'しかく', 'じかん', 'しごと', 'しすう', 'じだい', 'したうけ', 'したぎ', 'したて', 'したみ', 'しちょう', 'しちりん', 'しっかり', 'しつじ', 'しつもん', 'してい', 'してき', 'してつ', 'じてん', 'じどう', 'しなぎれ', 'しなもの', 'しなん', 'しねま', 'しねん', 'しのぐ', 'しのぶ', 'しはい', 'しばかり', 'しはつ', 'しはらい', 'しはん', 'しひょう', 'しふく', 'じぶん', 'しへい', 'しほう', 'しほん', 'しまう', 'しまる', 'しみん', 'しむける', 'じむしょ', 'しめい', 'しめる', 'しもん', 'しゃいん', 'しゃうん', 'しゃおん', 'じゃがいも', 'しやくしょ', 'しゃくほう', 'しゃけん', 'しゃこ', 'しゃざい', 'しゃしん', 'しゃせん', 'しゃそう', 'しゃたい', 'しゃちょう', 'しゃっきん', 'じゃま', 'しゃりん', 'しゃれい', 'じゆう', 'じゅうしょ', 'しゅくはく', 'じゅしん', 'しゅっせき', 'しゅみ', 'しゅらば', 'じゅんばん', 'しょうかい', 'しょくたく', 'しょっけん', 'しょどう', 'しょもつ', 'しらせる', 'しらべる', 'しんか', 'しんこう', 'じんじゃ', 'しんせいじ', 'しんちく', 'しんりん', 'すあげ', 'すあし', 'すあな', 'ずあん', 'すいえい', 'すいか', 'すいとう', 'ずいぶん', 'すいようび', 'すうがく', 'すうじつ', 'すうせん', 'すおどり', 'すきま', 'すくう', 'すくない', 'すける', 'すごい', 'すこし', 'ずさん', 'すずしい', 'すすむ', 'すすめる', 'すっかり', 'ずっしり', 'ずっと', 'すてき', 'すてる', 'すねる', 'すのこ', 'すはだ', 'すばらしい', 'ずひょう', 'ずぶぬれ', 'すぶり', 'すふれ', 'すべて', 'すべる', 'ずほう', 'すぼん', 'すまい', 'すめし', 'すもう', 'すやき', 'すらすら', 'するめ', 'すれちがう', 'すろっと', 'すわる', 'すんぜん', 'すんぽう', 'せあぶら', 'せいかつ', 'せいげん', 'せいじ', 'せいよう', 'せおう', 'せかいかん', 'せきにん', 'せきむ', 'せきゆ', 'せきらんうん', 'せけん', 'せこう', 'せすじ', 'せたい', 'せたけ', 'せっかく', 'せっきゃく', 'ぜっく', 'せっけん', 'せっこつ', 'せっさたくま', 'せつぞく', 'せつだん', 'せつでん', 'せっぱん', 'せつび', 'せつぶん', 'せつめい', 'せつりつ', 'せなか', 'せのび', 'せはば', 'せびろ', 'せぼね', 'せまい', 'せまる', 'せめる', 'せもたれ', 'せりふ', 'ぜんあく', 'せんい', 'せんえい', 'せんか', 'せんきょ', 'せんく', 'せんげん', 'ぜんご', 'せんさい', 'せんしゅ', 'せんすい', 'せんせい', 'せんぞ', 'せんたく', 'せんちょう', 'せんてい', 'せんとう', 'せんぬき', 'せんねん', 'せんぱい', 'ぜんぶ', 'ぜんぽう', 'せんむ', 'せんめんじょ', 'せんもん', 'せんやく', 'せんゆう', 'せんよう', 'ぜんら', 'ぜんりゃく', 'せんれい', 'せんろ', 'そあく', 'そいとげる', 'そいね', 'そうがんきょう', 'そうき', 'そうご', 'そうしん', 'そうだん', 'そうなん', 'そうび', 'そうめん', 'そうり', 'そえもの', 'そえん', 'そがい', 'そげき', 'そこう', 'そこそこ', 'そざい', 'そしな', 'そせい', 'そせん', 'そそぐ', 'そだてる', 'そつう', 'そつえん', 'そっかん', 'そつぎょう', 'そっけつ', 'そっこう', 'そっせん', 'そっと', 'そとがわ', 'そとづら', 'そなえる', 'そなた', 'そふぼ', 'そぼく', 'そぼろ', 'そまつ', 'そまる', 'そむく', 'そむりえ', 'そめる', 'そもそも', 'そよかぜ', 'そらまめ', 'そろう', 'そんかい', 'そんけい', 'そんざい', 'そんしつ', 'そんぞく', 'そんちょう', 'ぞんび', 'ぞんぶん', 'そんみん', 'たあい', 'たいいん', 'たいうん', 'たいえき', 'たいおう', 'だいがく', 'たいき', 'たいぐう', 'たいけん', 'たいこ', 'たいざい', 'だいじょうぶ', 'だいすき', 'たいせつ', 'たいそう', 'だいたい', 'たいちょう', 'たいてい', 'だいどころ', 'たいない', 'たいねつ', 'たいのう', 'たいはん', 'だいひょう', 'たいふう', 'たいへん', 'たいほ', 'たいまつばな', 'たいみんぐ', 'たいむ', 'たいめん', 'たいやき', 'たいよう', 'たいら', 'たいりょく', 'たいる', 'たいわん', 'たうえ', 'たえる', 'たおす', 'たおる', 'たおれる', 'たかい', 'たかね', 'たきび', 'たくさん', 'たこく', 'たこやき', 'たさい', 'たしざん', 'だじゃれ', 'たすける', 'たずさわる', 'たそがれ', 'たたかう', 'たたく', 'ただしい', 'たたみ', 'たちばな', 'だっかい', 'だっきゃく', 'だっこ', 'だっしゅつ', 'だったい', 'たてる', 'たとえる', 'たなばた', 'たにん', 'たぬき', 'たのしみ', 'たはつ', 'たぶん', 'たべる', 'たぼう', 'たまご', 'たまる', 'だむる', 'ためいき', 'ためす', 'ためる', 'たもつ', 'たやすい', 'たよる', 'たらす', 'たりきほんがん', 'たりょう', 'たりる', 'たると', 'たれる', 'たれんと', 'たろっと', 'たわむれる', 'だんあつ', 'たんい', 'たんおん', 'たんか', 'たんき', 'たんけん', 'たんご', 'たんさん', 'たんじょうび', 'だんせい', 'たんそく', 'たんたい', 'だんち', 'たんてい', 'たんとう', 'だんな', 'たんにん', 'だんねつ', 'たんのう', 'たんぴん', 'だんぼう', 'たんまつ', 'たんめい', 'だんれつ', 'だんろ', 'だんわ', 'ちあい', 'ちあん', 'ちいき', 'ちいさい', 'ちえん', 'ちかい', 'ちから', 'ちきゅう', 'ちきん', 'ちけいず', 'ちけん', 'ちこく', 'ちさい', 'ちしき', 'ちしりょう', 'ちせい', 'ちそう', 'ちたい', 'ちたん', 'ちちおや', 'ちつじょ', 'ちてき', 'ちてん', 'ちぬき', 'ちぬり', 'ちのう', 'ちひょう', 'ちへいせん', 'ちほう', 'ちまた', 'ちみつ', 'ちみどろ', 'ちめいど', 'ちゃんこなべ', 'ちゅうい', 'ちゆりょく', 'ちょうし', 'ちょさくけん', 'ちらし', 'ちらみ', 'ちりがみ', 'ちりょう', 'ちるど', 'ちわわ', 'ちんたい', 'ちんもく', 'ついか', 'ついたち', 'つうか', 'つうじょう', 'つうはん', 'つうわ', 'つかう', 'つかれる', 'つくね', 'つくる', 'つけね', 'つける', 'つごう', 'つたえる', 'つづく', 'つつじ', 'つつむ', 'つとめる', 'つながる', 'つなみ', 'つねづね', 'つのる', 'つぶす', 'つまらない', 'つまる', 'つみき', 'つめたい', 'つもり', 'つもる', 'つよい', 'つるぼ', 'つるみく', 'つわもの', 'つわり', 'てあし', 'てあて', 'てあみ', 'ていおん', 'ていか', 'ていき', 'ていけい', 'ていこく', 'ていさつ', 'ていし', 'ていせい', 'ていたい', 'ていど', 'ていねい', 'ていひょう', 'ていへん', 'ていぼう', 'てうち', 'ておくれ', 'てきとう', 'てくび', 'でこぼこ', 'てさぎょう', 'てさげ', 'てすり', 'てそう', 'てちがい', 'てちょう', 'てつがく', 'てつづき', 'でっぱ', 'てつぼう', 'てつや', 'でぬかえ', 'てぬき', 'てぬぐい', 'てのひら', 'てはい', 'てぶくろ', 'てふだ', 'てほどき', 'てほん', 'てまえ', 'てまきずし', 'てみじか', 'てみやげ', 'てらす', 'てれび', 'てわけ', 'てわたし', 'でんあつ', 'てんいん', 'てんかい', 'てんき', 'てんぐ', 'てんけん', 'てんごく', 'てんさい', 'てんし', 'てんすう', 'でんち', 'てんてき', 'てんとう', 'てんない', 'てんぷら', 'てんぼうだい', 'てんめつ', 'てんらんかい', 'でんりょく', 'でんわ', 'どあい', 'といれ', 'どうかん', 'とうきゅう', 'どうぐ', 'とうし', 'とうむぎ', 'とおい', 'とおか', 'とおく', 'とおす', 'とおる', 'とかい', 'とかす', 'ときおり', 'ときどき', 'とくい', 'とくしゅう', 'とくてん', 'とくに', 'とくべつ', 'とけい', 'とける', 'とこや', 'とさか', 'としょかん', 'とそう', 'とたん', 'とちゅう', 'とっきゅう', 'とっくん', 'とつぜん', 'とつにゅう', 'とどける', 'ととのえる', 'とない', 'となえる', 'となり', 'とのさま', 'とばす', 'どぶがわ', 'とほう', 'とまる', 'とめる', 'ともだち', 'ともる', 'どようび', 'とらえる', 'とんかつ', 'どんぶり', 'ないかく', 'ないこう', 'ないしょ', 'ないす', 'ないせん', 'ないそう', 'なおす', 'ながい', 'なくす', 'なげる', 'なこうど', 'なさけ', 'なたでここ', 'なっとう', 'なつやすみ', 'ななおし', 'なにごと', 'なにもの', 'なにわ', 'なのか', 'なふだ', 'なまいき', 'なまえ', 'なまみ', 'なみだ', 'なめらか', 'なめる', 'なやむ', 'ならう', 'ならび', 'ならぶ', 'なれる', 'なわとび', 'なわばり', 'にあう', 'にいがた', 'にうけ', 'におい', 'にかい', 'にがて', 'にきび', 'にくしみ', 'にくまん', 'にげる', 'にさんかたんそ', 'にしき', 'にせもの', 'にちじょう', 'にちようび', 'にっか', 'にっき', 'にっけい', 'にっこう', 'にっさん', 'にっしょく', 'にっすう', 'にっせき', 'にってい', 'になう', 'にほん', 'にまめ', 'にもつ', 'にやり', 'にゅういん', 'にりんしゃ', 'にわとり', 'にんい', 'にんか', 'にんき', 'にんげん', 'にんしき', 'にんずう', 'にんそう', 'にんたい', 'にんち', 'にんてい', 'にんにく', 'にんぷ', 'にんまり', 'にんむ', 'にんめい', 'にんよう', 'ぬいくぎ', 'ぬかす', 'ぬぐいとる', 'ぬぐう', 'ぬくもり', 'ぬすむ', 'ぬまえび', 'ぬめり', 'ぬらす', 'ぬんちゃく', 'ねあげ', 'ねいき', 'ねいる', 'ねいろ', 'ねぐせ', 'ねくたい', 'ねくら', 'ねこぜ', 'ねこむ', 'ねさげ', 'ねすごす', 'ねそべる', 'ねだん', 'ねつい', 'ねっしん', 'ねつぞう', 'ねったいぎょ', 'ねぶそく', 'ねふだ', 'ねぼう', 'ねほりはほり', 'ねまき', 'ねまわし', 'ねみみ', 'ねむい', 'ねむたい', 'ねもと', 'ねらう', 'ねわざ', 'ねんいり', 'ねんおし', 'ねんかん', 'ねんきん', 'ねんぐ', 'ねんざ', 'ねんし', 'ねんちゃく', 'ねんど', 'ねんぴ', 'ねんぶつ', 'ねんまつ', 'ねんりょう', 'ねんれい', 'のいず', 'のおづま', 'のがす', 'のきなみ', 'のこぎり', 'のこす', 'のこる', 'のせる', 'のぞく', 'のぞむ', 'のたまう', 'のちほど', 'のっく', 'のばす', 'のはら', 'のべる', 'のぼる', 'のみもの', 'のやま', 'のらいぬ', 'のらねこ', 'のりもの', 'のりゆき', 'のれん', 'のんき', 'ばあい', 'はあく', 'ばあさん', 'ばいか', 'ばいく', 'はいけん', 'はいご', 'はいしん', 'はいすい', 'はいせん', 'はいそう', 'はいち', 'ばいばい', 'はいれつ', 'はえる', 'はおる', 'はかい', 'ばかり', 'はかる', 'はくしゅ', 'はけん', 'はこぶ', 'はさみ', 'はさん', 'はしご', 'ばしょ', 'はしる', 'はせる', 'ぱそこん', 'はそん', 'はたん', 'はちみつ', 'はつおん', 'はっかく', 'はづき', 'はっきり', 'はっくつ', 'はっけん', 'はっこう', 'はっさん', 'はっしん', 'はったつ', 'はっちゅう', 'はってん', 'はっぴょう', 'はっぽう', 'はなす', 'はなび', 'はにかむ', 'はぶらし', 'はみがき', 'はむかう', 'はめつ', 'はやい', 'はやし', 'はらう', 'はろうぃん', 'はわい', 'はんい', 'はんえい', 'はんおん', 'はんかく', 'はんきょう', 'ばんぐみ', 'はんこ', 'はんしゃ', 'はんすう', 'はんだん', 'ぱんち', 'ぱんつ', 'はんてい', 'はんとし', 'はんのう', 'はんぱ', 'はんぶん', 'はんぺん', 'はんぼうき', 'はんめい', 'はんらん', 'はんろん', 'ひいき', 'ひうん', 'ひえる', 'ひかく', 'ひかり', 'ひかる', 'ひかん', 'ひくい', 'ひけつ', 'ひこうき', 'ひこく', 'ひさい', 'ひさしぶり', 'ひさん', 'びじゅつかん', 'ひしょ', 'ひそか', 'ひそむ', 'ひたむき', 'ひだり', 'ひたる', 'ひつぎ', 'ひっこし', 'ひっし', 'ひつじゅひん', 'ひっす', 'ひつぜん', 'ぴったり', 'ぴっちり', 'ひつよう', 'ひてい', 'ひとごみ', 'ひなまつり', 'ひなん', 'ひねる', 'ひはん', 'ひびく', 'ひひょう', 'ひほう', 'ひまわり', 'ひまん', 'ひみつ', 'ひめい', 'ひめじし', 'ひやけ', 'ひやす', 'ひよう', 'びょうき', 'ひらがな', 'ひらく', 'ひりつ', 'ひりょう', 'ひるま', 'ひるやすみ', 'ひれい', 'ひろい', 'ひろう', 'ひろき', 'ひろゆき', 'ひんかく', 'ひんけつ', 'ひんこん', 'ひんしゅ', 'ひんそう', 'ぴんち', 'ひんぱん', 'びんぼう', 'ふあん', 'ふいうち', 'ふうけい', 'ふうせん', 'ぷうたろう', 'ふうとう', 'ふうふ', 'ふえる', 'ふおん', 'ふかい', 'ふきん', 'ふくざつ', 'ふくぶくろ', 'ふこう', 'ふさい', 'ふしぎ', 'ふじみ', 'ふすま', 'ふせい', 'ふせぐ', 'ふそく', 'ぶたにく', 'ふたん', 'ふちょう', 'ふつう', 'ふつか', 'ふっかつ', 'ふっき', 'ふっこく', 'ぶどう', 'ふとる', 'ふとん', 'ふのう', 'ふはい', 'ふひょう', 'ふへん', 'ふまん', 'ふみん', 'ふめつ', 'ふめん', 'ふよう', 'ふりこ', 'ふりる', 'ふるい', 'ふんいき', 'ぶんがく', 'ぶんぐ', 'ふんしつ', 'ぶんせき', 'ふんそう', 'ぶんぽう', 'へいあん', 'へいおん', 'へいがい', 'へいき', 'へいげん', 'へいこう', 'へいさ', 'へいしゃ', 'へいせつ', 'へいそ', 'へいたく', 'へいてん', 'へいねつ', 'へいわ', 'へきが', 'へこむ', 'べにいろ', 'べにしょうが', 'へらす', 'へんかん', 'べんきょう', 'べんごし', 'へんさい', 'へんたい', 'べんり', 'ほあん', 'ほいく', 'ぼうぎょ', 'ほうこく', 'ほうそう', 'ほうほう', 'ほうもん', 'ほうりつ', 'ほえる', 'ほおん', 'ほかん', 'ほきょう', 'ぼきん', 'ほくろ', 'ほけつ', 'ほけん', 'ほこう', 'ほこる', 'ほしい', 'ほしつ', 'ほしゅ', 'ほしょう', 'ほせい', 'ほそい', 'ほそく', 'ほたて', 'ほたる', 'ぽちぶくろ', 'ほっきょく', 'ほっさ', 'ほったん', 'ほとんど', 'ほめる', 'ほんい', 'ほんき', 'ほんけ', 'ほんしつ', 'ほんやく', 'まいにち', 'まかい', 'まかせる', 'まがる', 'まける', 'まこと', 'まさつ', 'まじめ', 'ますく', 'まぜる', 'まつり', 'まとめ', 'まなぶ', 'まぬけ', 'まねく', 'まほう', 'まもる', 'まゆげ', 'まよう', 'まろやか', 'まわす', 'まわり', 'まわる', 'まんが', 'まんきつ', 'まんぞく', 'まんなか', 'みいら', 'みうち', 'みえる', 'みがく', 'みかた', 'みかん', 'みけん', 'みこん', 'みじかい', 'みすい', 'みすえる', 'みせる', 'みっか', 'みつかる', 'みつける', 'みてい', 'みとめる', 'みなと', 'みなみかさい', 'みねらる', 'みのう', 'みのがす', 'みほん', 'みもと', 'みやげ', 'みらい', 'みりょく', 'みわく', 'みんか', 'みんぞく', 'むいか', 'むえき', 'むえん', 'むかい', 'むかう', 'むかえ', 'むかし', 'むぎちゃ', 'むける', 'むげん', 'むさぼる', 'むしあつい', 'むしば', 'むじゅん', 'むしろ', 'むすう', 'むすこ', 'むすぶ', 'むすめ', 'むせる', 'むせん', 'むちゅう', 'むなしい', 'むのう', 'むやみ', 'むよう', 'むらさき', 'むりょう', 'むろん', 'めいあん', 'めいうん', 'めいえん', 'めいかく', 'めいきょく', 'めいさい', 'めいし', 'めいそう', 'めいぶつ', 'めいれい', 'めいわく', 'めぐまれる', 'めざす', 'めした', 'めずらしい', 'めだつ', 'めまい', 'めやす', 'めんきょ', 'めんせき', 'めんどう', 'もうしあげる', 'もうどうけん', 'もえる', 'もくし', 'もくてき', 'もくようび', 'もちろん', 'もどる', 'もらう', 'もんく', 'もんだい', 'やおや', 'やける', 'やさい', 'やさしい', 'やすい', 'やすたろう', 'やすみ', 'やせる', 'やそう', 'やたい', 'やちん', 'やっと', 'やっぱり', 'やぶる', 'やめる', 'ややこしい', 'やよい', 'やわらかい', 'ゆうき', 'ゆうびんきょく', 'ゆうべ', 'ゆうめい', 'ゆけつ', 'ゆしゅつ', 'ゆせん', 'ゆそう', 'ゆたか', 'ゆちゃく', 'ゆでる', 'ゆにゅう', 'ゆびわ', 'ゆらい', 'ゆれる', 'ようい', 'ようか', 'ようきゅう', 'ようじ', 'ようす', 'ようちえん', 'よかぜ', 'よかん', 'よきん', 'よくせい', 'よくぼう', 'よけい', 'よごれる', 'よさん', 'よしゅう', 'よそう', 'よそく', 'よっか', 'よてい', 'よどがわく', 'よねつ', 'よやく', 'よゆう', 'よろこぶ', 'よろしい', 'らいう', 'らくがき', 'らくご', 'らくさつ', 'らくだ', 'らしんばん', 'らせん', 'らぞく', 'らたい', 'らっか', 'られつ', 'りえき', 'りかい', 'りきさく', 'りきせつ', 'りくぐん', 'りくつ', 'りけん', 'りこう', 'りせい', 'りそう', 'りそく', 'りてん', 'りねん', 'りゆう', 'りゅうがく', 'りよう', 'りょうり', 'りょかん', 'りょくちゃ', 'りょこう', 'りりく', 'りれき', 'りろん', 'りんご', 'るいけい', 'るいさい', 'るいじ', 'るいせき', 'るすばん', 'るりがわら', 'れいかん', 'れいぎ', 'れいせい', 'れいぞうこ', 'れいとう', 'れいぼう', 'れきし', 'れきだい', 'れんあい', 'れんけい', 'れんこん', 'れんさい', 'れんしゅう', 'れんぞく', 'れんらく', 'ろうか', 'ろうご', 'ろうじん', 'ろうそく', 'ろくが', 'ろこつ', 'ろじうら', 'ろしゅつ', 'ろせん', 'ろてん', 'ろめん', 'ろれつ', 'ろんぎ', 'ろんぱ', 'ろんぶん', 'ろんり', 'わかす', 'わかめ', 'わかやま', 'わかれる', 'わしつ', 'わじまし', 'わすれもの', 'わらう', 'われる']; | |
module.exports = japanese; | |
},{}],98:[function(require,module,exports){ | |
'use strict'; | |
var spanish = ['ábaco', 'abdomen', 'abeja', 'abierto', 'abogado', 'abono', 'aborto', 'abrazo', 'abrir', 'abuelo', 'abuso', 'acabar', 'academia', 'acceso', 'acción', 'aceite', 'acelga', 'acento', 'aceptar', 'ácido', 'aclarar', 'acné', 'acoger', 'acoso', 'activo', 'acto', 'actriz', 'actuar', 'acudir', 'acuerdo', 'acusar', 'adicto', 'admitir', 'adoptar', 'adorno', 'aduana', 'adulto', 'aéreo', 'afectar', 'afición', 'afinar', 'afirmar', 'ágil', 'agitar', 'agonía', 'agosto', 'agotar', 'agregar', 'agrio', 'agua', 'agudo', 'águila', 'aguja', 'ahogo', 'ahorro', 'aire', 'aislar', 'ajedrez', 'ajeno', 'ajuste', 'alacrán', 'alambre', 'alarma', 'alba', 'álbum', 'alcalde', 'aldea', 'alegre', 'alejar', 'alerta', 'aleta', 'alfiler', 'alga', 'algodón', 'aliado', 'aliento', 'alivio', 'alma', 'almeja', 'almíbar', 'altar', 'alteza', 'altivo', 'alto', 'altura', 'alumno', 'alzar', 'amable', 'amante', 'amapola', 'amargo', 'amasar', 'ámbar', 'ámbito', 'ameno', 'amigo', 'amistad', 'amor', 'amparo', 'amplio', 'ancho', 'anciano', 'ancla', 'andar', 'andén', 'anemia', 'ángulo', 'anillo', 'ánimo', 'anís', 'anotar', 'antena', 'antiguo', 'antojo', 'anual', 'anular', 'anuncio', 'añadir', 'añejo', 'año', 'apagar', 'aparato', 'apetito', 'apio', 'aplicar', 'apodo', 'aporte', 'apoyo', 'aprender', 'aprobar', 'apuesta', 'apuro', 'arado', 'araña', 'arar', 'árbitro', 'árbol', 'arbusto', 'archivo', 'arco', 'arder', 'ardilla', 'arduo', 'área', 'árido', 'aries', 'armonía', 'arnés', 'aroma', 'arpa', 'arpón', 'arreglo', 'arroz', 'arruga', 'arte', 'artista', 'asa', 'asado', 'asalto', 'ascenso', 'asegurar', 'aseo', 'asesor', 'asiento', 'asilo', 'asistir', 'asno', 'asombro', 'áspero', 'astilla', 'astro', 'astuto', 'asumir', 'asunto', 'atajo', 'ataque', 'atar', 'atento', 'ateo', 'ático', 'atleta', 'átomo', 'atraer', 'atroz', 'atún', 'audaz', 'audio', 'auge', 'aula', 'aumento', 'ausente', 'autor', 'aval', 'avance', 'avaro', 'ave', 'avellana', 'avena', 'avestruz', 'avión', 'aviso', 'ayer', 'ayuda', 'ayuno', 'azafrán', 'azar', 'azote', 'azúcar', 'azufre', 'azul', 'baba', 'babor', 'bache', 'bahía', 'baile', 'bajar', 'balanza', 'balcón', 'balde', 'bambú', 'banco', 'banda', 'baño', 'barba', 'barco', 'barniz', 'barro', 'báscula', 'bastón', 'basura', 'batalla', 'batería', 'batir', 'batuta', 'baúl', 'bazar', 'bebé', 'bebida', 'bello', 'besar', 'beso', 'bestia', 'bicho', 'bien', 'bingo', 'blanco', 'bloque', 'blusa', 'boa', 'bobina', 'bobo', 'boca', 'bocina', 'boda', 'bodega', 'boina', 'bola', 'bolero', 'bolsa', 'bomba', 'bondad', 'bonito', 'bono', 'bonsái', 'borde', 'borrar', 'bosque', 'bote', 'botín', 'bóveda', 'bozal', 'bravo', 'brazo', 'brecha', 'breve', 'brillo', 'brinco', 'brisa', 'broca', 'broma', 'bronce', 'brote', 'bruja', 'brusco', 'bruto', 'buceo', 'bucle', 'bueno', 'buey', 'bufanda', 'bufón', 'búho', 'buitre', 'bulto', 'burbuja', 'burla', 'burro', 'buscar', 'butaca', 'buzón', 'caballo', 'cabeza', 'cabina', 'cabra', 'cacao', 'cadáver', 'cadena', 'caer', 'café', 'caída', 'caimán', 'caja', 'cajón', 'cal', 'calamar', 'calcio', 'caldo', 'calidad', 'calle', 'calma', 'calor', 'calvo', 'cama', 'cambio', 'camello', 'camino', 'campo', 'cáncer', 'candil', 'canela', 'canguro', 'canica', 'canto', 'caña', 'cañón', 'caoba', 'caos', 'capaz', 'capitán', 'capote', 'captar', 'capucha', 'cara', 'carbón', 'cárcel', 'careta', 'carga', 'cariño', 'carne', 'carpeta', 'carro', 'carta', 'casa', 'casco', 'casero', 'caspa', 'castor', 'catorce', 'catre', 'caudal', 'causa', 'cazo', 'cebolla', 'ceder', 'cedro', 'celda', 'célebre', 'celoso', 'célula', 'cemento', 'ceniza', 'centro', 'cerca', 'cerdo', 'cereza', 'cero', 'cerrar', 'certeza', 'césped', 'cetro', 'chacal', 'chaleco', 'champú', 'chancla', 'chapa', 'charla', 'chico', 'chiste', 'chivo', 'choque', 'choza', 'chuleta', 'chupar', 'ciclón', 'ciego', 'cielo', 'cien', 'cierto', 'cifra', 'cigarro', 'cima', 'cinco', 'cine', 'cinta', 'ciprés', 'circo', 'ciruela', 'cisne', 'cita', 'ciudad', 'clamor', 'clan', 'claro', 'clase', 'clave', 'cliente', 'clima', 'clínica', 'cobre', 'cocción', 'cochino', 'cocina', 'coco', 'código', 'codo', 'cofre', 'coger', 'cohete', 'cojín', 'cojo', 'cola', 'colcha', 'colegio', 'colgar', 'colina', 'collar', 'colmo', 'columna', 'combate', 'comer', 'comida', 'cómodo', 'compra', 'conde', 'conejo', 'conga', 'conocer', 'consejo', 'contar', 'copa', 'copia', 'corazón', 'corbata', 'corcho', 'cordón', 'corona', 'correr', 'coser', 'cosmos', 'costa', 'cráneo', 'cráter', 'crear', 'crecer', 'creído', 'crema', 'cría', 'crimen', 'cripta', 'crisis', 'cromo', 'crónica', 'croqueta', 'crudo', 'cruz', 'cuadro', 'cuarto', 'cuatro', 'cubo', 'cubrir', 'cuchara', 'cuello', 'cuento', 'cuerda', 'cuesta', 'cueva', 'cuidar', 'culebra', 'culpa', 'culto', 'cumbre', 'cumplir', 'cuna', 'cuneta', 'cuota', 'cupón', 'cúpula', 'curar', 'curioso', 'curso', 'curva', 'cutis', 'dama', 'danza', 'dar', 'dardo', 'dátil', 'deber', 'débil', 'década', 'decir', 'dedo', 'defensa', 'definir', 'dejar', 'delfín', 'delgado', 'delito', 'demora', 'denso', 'dental', 'deporte', 'derecho', 'derrota', 'desayuno', 'deseo', 'desfile', 'desnudo', 'destino', 'desvío', 'detalle', 'detener', 'deuda', 'día', 'diablo', 'diadema', 'diamante', 'diana', 'diario', 'dibujo', 'dictar', 'diente', 'dieta', 'diez', 'difícil', 'digno', 'dilema', 'diluir', 'dinero', 'directo', 'dirigir', 'disco', 'diseño', 'disfraz', 'diva', 'divino', 'doble', 'doce', 'dolor', 'domingo', 'don', 'donar', 'dorado', 'dormir', 'dorso', 'dos', 'dosis', 'dragón', 'droga', 'ducha', 'duda', 'duelo', 'dueño', 'dulce', 'dúo', 'duque', 'durar', 'dureza', 'duro', 'ébano', 'ebrio', 'echar', 'eco', 'ecuador', 'edad', 'edición', 'edificio', 'editor', 'educar', 'efecto', 'eficaz', 'eje', 'ejemplo', 'elefante', 'elegir', 'elemento', 'elevar', 'elipse', 'élite', 'elixir', 'elogio', 'eludir', 'embudo', 'emitir', 'emoción', 'empate', 'empeño', 'empleo', 'empresa', 'enano', 'encargo', 'enchufe', 'encía', 'enemigo', 'enero', 'enfado', 'enfermo', 'engaño', 'enigma', 'enlace', 'enorme', 'enredo', 'ensayo', 'enseñar', 'entero', 'entrar', 'envase', 'envío', 'época', 'equipo', 'erizo', 'escala', 'escena', 'escolar', 'escribir', 'escudo', 'esencia', 'esfera', 'esfuerzo', 'espada', 'espejo', 'espía', 'esposa', 'espuma', 'esquí', 'estar', 'este', 'estilo', 'estufa', 'etapa', 'eterno', 'ética', 'etnia', 'evadir', 'evaluar', 'evento', 'evitar', 'exacto', 'examen', 'exceso', 'excusa', 'exento', 'exigir', 'exilio', 'existir', 'éxito', 'experto', 'explicar', 'exponer', 'extremo', 'fábrica', 'fábula', 'fachada', 'fácil', 'factor', 'faena', 'faja', 'falda', 'fallo', 'falso', 'faltar', 'fama', 'familia', 'famoso', 'faraón', 'farmacia', 'farol', 'farsa', 'fase', 'fatiga', 'fauna', 'favor', 'fax', 'febrero', 'fecha', 'feliz', 'feo', 'feria', 'feroz', 'fértil', 'fervor', 'festín', 'fiable', 'fianza', 'fiar', 'fibra', 'ficción', 'ficha', 'fideo', 'fiebre', 'fiel', 'fiera', 'fiesta', 'figura', 'fijar', 'fijo', 'fila', 'filete', 'filial', 'filtro', 'fin', 'finca', 'fingir', 'finito', 'firma', 'flaco', 'flauta', 'flecha', 'flor', 'flota', 'fluir', 'flujo', 'flúor', 'fobia', 'foca', 'fogata', 'fogón', 'folio', 'folleto', 'fondo', 'forma', 'forro', 'fortuna', 'forzar', 'fosa', 'foto', 'fracaso', 'frágil', 'franja', 'frase', 'fraude', 'freír', 'freno', 'fresa', 'frío', 'frito', 'fruta', 'fuego', 'fuente', 'fuerza', 'fuga', 'fumar', 'función', 'funda', 'furgón', 'furia', 'fusil', 'fútbol', 'futuro', 'gacela', 'gafas', 'gaita', 'gajo', 'gala', 'galería', 'gallo', 'gamba', 'ganar', 'gancho', 'ganga', 'ganso', 'garaje', 'garza', 'gasolina', 'gastar', 'gato', 'gavilán', 'gemelo', 'gemir', 'gen', 'género', 'genio', 'gente', 'geranio', 'gerente', 'germen', 'gesto', 'gigante', 'gimnasio', 'girar', 'giro', 'glaciar', 'globo', 'gloria', 'gol', 'golfo', 'goloso', 'golpe', 'goma', 'gordo', 'gorila', 'gorra', 'gota', 'goteo', 'gozar', 'grada', 'gráfico', 'grano', 'grasa', 'gratis', 'grave', 'grieta', 'grillo', 'gripe', 'gris', 'grito', 'grosor', 'grúa', 'grueso', 'grumo', 'grupo', 'guante', 'guapo', 'guardia', 'guerra', 'guía', 'guiño', 'guion', 'guiso', 'guitarra', 'gusano', 'gustar', 'haber', 'hábil', 'hablar', 'hacer', 'hacha', 'hada', 'hallar', 'hamaca', 'harina', 'haz', 'hazaña', 'hebilla', 'hebra', 'hecho', 'helado', 'helio', 'hembra', 'herir', 'hermano', 'héroe', 'hervir', 'hielo', 'hierro', 'hígado', 'higiene', 'hijo', 'himno', 'historia', 'hocico', 'hogar', 'hoguera', 'hoja', 'hombre', 'hongo', 'honor', 'honra', 'hora', 'hormiga', 'horno', 'hostil', 'hoyo', 'hueco', 'huelga', 'huerta', 'hueso', 'huevo', 'huida', 'huir', 'humano', 'húmedo', 'humilde', 'humo', 'hundir', 'huracán', 'hurto', 'icono', 'ideal', 'idioma', 'ídolo', 'iglesia', 'iglú', 'igual', 'ilegal', 'ilusión', 'imagen', 'imán', 'imitar', 'impar', 'imperio', 'imponer', 'impulso', 'incapaz', 'índice', 'inerte', 'infiel', 'informe', 'ingenio', 'inicio', 'inmenso', 'inmune', 'innato', 'insecto', 'instante', 'interés', 'íntimo', 'intuir', 'inútil', 'invierno', 'ira', 'iris', 'ironía', 'isla', 'islote', 'jabalí', 'jabón', 'jamón', 'jarabe', 'jardín', 'jarra', 'jaula', 'jazmín', 'jefe', 'jeringa', 'jinete', 'jornada', 'joroba', 'joven', 'joya', 'juerga', 'jueves', 'juez', 'jugador', 'jugo', 'juguete', 'juicio', 'junco', 'jungla', 'junio', 'juntar', 'júpiter', 'jurar', 'justo', 'juvenil', 'juzgar', 'kilo', 'koala', 'labio', 'lacio', 'lacra', 'lado', 'ladrón', 'lagarto', 'lágrima', 'laguna', 'laico', 'lamer', 'lámina', 'lámpara', 'lana', 'lancha', 'langosta', 'lanza', 'lápiz', 'largo', 'larva', 'lástima', 'lata', 'látex', 'latir', 'laurel', 'lavar', 'lazo', 'leal', 'lección', 'leche', 'lector', 'leer', 'legión', 'legumbre', 'lejano', 'lengua', 'lento', 'leña', 'león', 'leopardo', 'lesión', 'letal', 'letra', 'leve', 'leyenda', 'libertad', 'libro', 'licor', 'líder', 'lidiar', 'lienzo', 'liga', 'ligero', 'lima', 'límite', 'limón', 'limpio', 'lince', 'lindo', 'línea', 'lingote', 'lino', 'linterna', 'líquido', 'liso', 'lista', 'litera', 'litio', 'litro', 'llaga', 'llama', 'llanto', 'llave', 'llegar', 'llenar', 'llevar', 'llorar', 'llover', 'lluvia', 'lobo', 'loción', 'loco', 'locura', 'lógica', 'logro', 'lombriz', 'lomo', 'lonja', 'lote', 'lucha', 'lucir', 'lugar', 'lujo', 'luna', 'lunes', 'lupa', 'lustro', 'luto', 'luz', 'maceta', 'macho', 'madera', 'madre', 'maduro', 'maestro', 'mafia', 'magia', 'mago', 'maíz', 'maldad', 'maleta', 'malla', 'malo', 'mamá', 'mambo', 'mamut', 'manco', 'mando', 'manejar', 'manga', 'maniquí', 'manjar', 'mano', 'manso', 'manta', 'mañana', 'mapa', 'máquina', 'mar', 'marco', 'marea', 'marfil', 'margen', 'marido', 'mármol', 'marrón', 'martes', 'marzo', 'masa', 'máscara', 'masivo', 'matar', 'materia', 'matiz', 'matriz', 'máximo', 'mayor', 'mazorca', 'mecha', 'medalla', 'medio', 'médula', 'mejilla', 'mejor', 'melena', 'melón', 'memoria', 'menor', 'mensaje', 'mente', 'menú', 'mercado', 'merengue', 'mérito', 'mes', 'mesón', 'meta', 'meter', 'método', 'metro', 'mezcla', 'miedo', 'miel', 'miembro', 'miga', 'mil', 'milagro', 'militar', 'millón', 'mimo', 'mina', 'minero', 'mínimo', 'minuto', 'miope', 'mirar', 'misa', 'miseria', 'misil', 'mismo', 'mitad', 'mito', 'mochila', 'moción', 'moda', 'modelo', 'moho', 'mojar', 'molde', 'moler', 'molino', 'momento', 'momia', 'monarca', 'moneda', 'monja', 'monto', 'moño', 'morada', 'morder', 'moreno', 'morir', 'morro', 'morsa', 'mortal', 'mosca', 'mostrar', 'motivo', 'mover', 'móvil', 'mozo', 'mucho', 'mudar', 'mueble', 'muela', 'muerte', 'muestra', 'mugre', 'mujer', 'mula', 'muleta', 'multa', 'mundo', 'muñeca', 'mural', 'muro', 'músculo', 'museo', 'musgo', 'música', 'muslo', 'nácar', 'nación', 'nadar', 'naipe', 'naranja', 'nariz', 'narrar', 'nasal', 'natal', 'nativo', 'natural', 'náusea', 'naval', 'nave', 'navidad', 'necio', 'néctar', 'negar', 'negocio', 'negro', 'neón', 'nervio', 'neto', 'neutro', 'nevar', 'nevera', 'nicho', 'nido', 'niebla', 'nieto', 'niñez', 'niño', 'nítido', 'nivel', 'nobleza', 'noche', 'nómina', 'noria', 'norma', 'norte', 'nota', 'noticia', 'novato', 'novela', 'novio', 'nube', 'nuca', 'núcleo', 'nudillo', 'nudo', 'nuera', 'nueve', 'nuez', 'nulo', 'número', 'nutria', 'oasis', 'obeso', 'obispo', 'objeto', 'obra', 'obrero', 'observar', 'obtener', 'obvio', 'oca', 'ocaso', 'océano', 'ochenta', 'ocho', 'ocio', 'ocre', 'octavo', 'octubre', 'oculto', 'ocupar', 'ocurrir', 'odiar', 'odio', 'odisea', 'oeste', 'ofensa', 'oferta', 'oficio', 'ofrecer', 'ogro', 'oído', 'oír', 'ojo', 'ola', 'oleada', 'olfato', 'olivo', 'olla', 'olmo', 'olor', 'olvido', 'ombligo', 'onda', 'onza', 'opaco', 'opción', 'ópera', 'opinar', 'oponer', 'optar', 'óptica', 'opuesto', 'oración', 'orador', 'oral', 'órbita', 'orca', 'orden', 'oreja', 'órgano', 'orgía', 'orgullo', 'oriente', 'origen', 'orilla', 'oro', 'orquesta', 'oruga', 'osadía', 'oscuro', 'osezno', 'oso', 'ostra', 'otoño', 'otro', 'oveja', 'óvulo', 'óxido', 'oxígeno', 'oyente', 'ozono', 'pacto', 'padre', 'paella', 'página', 'pago', 'país', 'pájaro', 'palabra', 'palco', 'paleta', 'pálido', 'palma', 'paloma', 'palpar', 'pan', 'panal', 'pánico', 'pantera', 'pañuelo', 'papá', 'papel', 'papilla', 'paquete', 'parar', 'parcela', 'pared', 'parir', 'paro', 'párpado', 'parque', 'párrafo', 'parte', 'pasar', 'paseo', 'pasión', 'paso', 'pasta', 'pata', 'patio', 'patria', 'pausa', 'pauta', 'pavo', 'payaso', 'peatón', 'pecado', 'pecera', 'pecho', 'pedal', 'pedir', 'pegar', 'peine', 'pelar', 'peldaño', 'pelea', 'peligro', 'pellejo', 'pelo', 'peluca', 'pena', 'pensar', 'peñón', 'peón', 'peor', 'pepino', 'pequeño', 'pera', 'percha', 'perder', 'pereza', 'perfil', 'perico', 'perla', 'permiso', 'perro', 'persona', 'pesa', 'pesca', 'pésimo', 'pestaña', 'pétalo', 'petróleo', 'pez', 'pezuña', 'picar', 'pichón', 'pie', 'piedra', 'pierna', 'pieza', 'pijama', 'pilar', 'piloto', 'pimienta', 'pino', 'pintor', 'pinza', 'piña', 'piojo', 'pipa', 'pirata', 'pisar', 'piscina', 'piso', 'pista', 'pitón', 'pizca', 'placa', 'plan', 'plata', 'playa', 'plaza', 'pleito', 'pleno', 'plomo', 'pluma', 'plural', 'pobre', 'poco', 'poder', 'podio', 'poema', 'poesía', 'poeta', 'polen', 'policía', 'pollo', 'polvo', 'pomada', 'pomelo', 'pomo', 'pompa', 'poner', 'porción', 'portal', 'posada', 'poseer', 'posible', 'poste', 'potencia', 'potro', 'pozo', 'prado', 'precoz', 'pregunta', 'premio', 'prensa', 'preso', 'previo', 'primo', 'príncipe', 'prisión', 'privar', 'proa', 'probar', 'proceso', 'producto', 'proeza', 'profesor', 'programa', 'prole', 'promesa', 'pronto', 'propio', 'próximo', 'prueba', 'público', 'puchero', 'pudor', 'pueblo', 'puerta', 'puesto', 'pulga', 'pulir', 'pulmón', 'pulpo', 'pulso', 'puma', 'punto', 'puñal', 'puño', 'pupa', 'pupila', 'puré', 'quedar', 'queja', 'quemar', 'querer', 'queso', 'quieto', 'química', 'quince', 'quitar', 'rábano', 'rabia', 'rabo', 'ración', 'radical', 'raíz', 'rama', 'rampa', 'rancho', 'rango', 'rapaz', 'rápido', 'rapto', 'rasgo', 'raspa', 'rato', 'rayo', 'raza', 'razón', 'reacción', 'realidad', 'rebaño', 'rebote', 'recaer', 'receta', 'rechazo', 'recoger', 'recreo', 'recto', 'recurso', 'red', 'redondo', 'reducir', 'reflejo', 'reforma', 'refrán', 'refugio', 'regalo', 'regir', 'regla', 'regreso', 'rehén', 'reino', 'reír', 'reja', 'relato', 'relevo', 'relieve', 'relleno', 'reloj', 'remar', 'remedio', 'remo', 'rencor', 'rendir', 'renta', 'reparto', 'repetir', 'reposo', 'reptil', 'res', 'rescate', 'resina', 'respeto', 'resto', 'resumen', 'retiro', 'retorno', 'retrato', 'reunir', 'revés', 'revista', 'rey', 'rezar', 'rico', 'riego', 'rienda', 'riesgo', 'rifa', 'rígido', 'rigor', 'rincón', 'riñón', 'río', 'riqueza', 'risa', 'ritmo', 'rito', 'rizo', 'roble', 'roce', 'rociar', 'rodar', 'rodeo', 'rodilla', 'roer', 'rojizo', 'rojo', 'romero', 'romper', 'ron', 'ronco', 'ronda', 'ropa', 'ropero', 'rosa', 'rosca', 'rostro', 'rotar', 'rubí', 'rubor', 'rudo', 'rueda', 'rugir', 'ruido', 'ruina', 'ruleta', 'rulo', 'rumbo', 'rumor', 'ruptura', 'ruta', 'rutina', 'sábado', 'saber', 'sabio', 'sable', 'sacar', 'sagaz', 'sagrado', 'sala', 'saldo', 'salero', 'salir', 'salmón', 'salón', 'salsa', 'salto', 'salud', 'salvar', 'samba', 'sanción', 'sandía', 'sanear', 'sangre', 'sanidad', 'sano', 'santo', 'sapo', 'saque', 'sardina', 'sartén', 'sastre', 'satán', 'sauna', 'saxofón', 'sección', 'seco', 'secreto', 'secta', 'sed', 'seguir', 'seis', 'sello', 'selva', 'semana', 'semilla', 'senda', 'sensor', 'señal', 'señor', 'separar', 'sepia', 'sequía', 'ser', 'serie', 'sermón', 'servir', 'sesenta', 'sesión', 'seta', 'setenta', 'severo', 'sexo', 'sexto', 'sidra', 'siesta', 'siete', 'siglo', 'signo', 'sílaba', 'silbar', 'silencio', 'silla', 'símbolo', 'simio', 'sirena', 'sistema', 'sitio', 'situar', 'sobre', 'socio', 'sodio', 'sol', 'solapa', 'soldado', 'soledad', 'sólido', 'soltar', 'solución', 'sombra', 'sondeo', 'sonido', 'sonoro', 'sonrisa', 'sopa', 'soplar', 'soporte', 'sordo', 'sorpresa', 'sorteo', 'sostén', 'sótano', 'suave', 'subir', 'suceso', 'sudor', 'suegra', 'suelo', 'sueño', 'suerte', 'sufrir', 'sujeto', 'sultán', 'sumar', 'superar', 'suplir', 'suponer', 'supremo', 'sur', 'surco', 'sureño', 'surgir', 'susto', 'sutil', 'tabaco', 'tabique', 'tabla', 'tabú', 'taco', 'tacto', 'tajo', 'talar', 'talco', 'talento', 'talla', 'talón', 'tamaño', 'tambor', 'tango', 'tanque', 'tapa', 'tapete', 'tapia', 'tapón', 'taquilla', 'tarde', 'tarea', 'tarifa', 'tarjeta', 'tarot', 'tarro', 'tarta', 'tatuaje', 'tauro', 'taza', 'tazón', 'teatro', 'techo', 'tecla', 'técnica', 'tejado', 'tejer', 'tejido', 'tela', 'teléfono', 'tema', 'temor', 'templo', 'tenaz', 'tender', 'tener', 'tenis', 'tenso', 'teoría', 'terapia', 'terco', 'término', 'ternura', 'terror', 'tesis', 'tesoro', 'testigo', 'tetera', 'texto', 'tez', 'tibio', 'tiburón', 'tiempo', 'tienda', 'tierra', 'tieso', 'tigre', 'tijera', 'tilde', 'timbre', 'tímido', 'timo', 'tinta', 'tío', 'típico', 'tipo', 'tira', 'tirón', 'titán', 'títere', 'título', 'tiza', 'toalla', 'tobillo', 'tocar', 'tocino', 'todo', 'toga', 'toldo', 'tomar', 'tono', 'tonto', 'topar', 'tope', 'toque', 'tórax', 'torero', 'tormenta', 'torneo', 'toro', 'torpedo', 'torre', 'torso', 'tortuga', 'tos', 'tosco', 'toser', 'tóxico', 'trabajo', 'tractor', 'traer', 'tráfico', 'trago', 'traje', 'tramo', 'trance', 'trato', 'trauma', 'trazar', 'trébol', 'tregua', 'treinta', 'tren', 'trepar', 'tres', 'tribu', 'trigo', 'tripa', 'triste', 'triunfo', 'trofeo', 'trompa', 'tronco', 'tropa', 'trote', 'trozo', 'truco', 'trueno', 'trufa', 'tubería', 'tubo', 'tuerto', 'tumba', 'tumor', 'túnel', 'túnica', 'turbina', 'turismo', 'turno', 'tutor', 'ubicar', 'úlcera', 'umbral', 'unidad', 'unir', 'universo', 'uno', 'untar', 'uña', 'urbano', 'urbe', 'urgente', 'urna', 'usar', 'usuario', 'útil', 'utopía', 'uva', 'vaca', 'vacío', 'vacuna', 'vagar', 'vago', 'vaina', 'vajilla', 'vale', 'válido', 'valle', 'valor', 'válvula', 'vampiro', 'vara', 'variar', 'varón', 'vaso', 'vecino', 'vector', 'vehículo', 'veinte', 'vejez', 'vela', 'velero', 'veloz', 'vena', 'vencer', 'venda', 'veneno', 'vengar', 'venir', 'venta', 'venus', 'ver', 'verano', 'verbo', 'verde', 'vereda', 'verja', 'verso', 'verter', 'vía', 'viaje', 'vibrar', 'vicio', 'víctima', 'vida', 'vídeo', 'vidrio', 'viejo', 'viernes', 'vigor', 'vil', 'villa', 'vinagre', 'vino', 'viñedo', 'violín', 'viral', 'virgo', 'virtud', 'visor', 'víspera', 'vista', 'vitamina', 'viudo', 'vivaz', 'vivero', 'vivir', 'vivo', 'volcán', 'volumen', 'volver', 'voraz', 'votar', 'voto', 'voz', 'vuelo', 'vulgar', 'yacer', 'yate', 'yegua', 'yema', 'yerno', 'yeso', 'yodo', 'yoga', 'yogur', 'zafiro', 'zanja', 'zapato', 'zarza', 'zona', 'zorro', 'zumo', 'zurdo']; | |
module.exports = spanish; | |
},{}],99:[function(require,module,exports){ | |
'use strict'; | |
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; | |
(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() {}; | |
TempCtor.prototype = superCtor.prototype; | |
ctor.prototype = new TempCtor(); | |
ctor.prototype.constructor = ctor; | |
} | |
// BN | |
function BN(number, base, endian) { | |
if (BN.isBN(number)) { | |
return number; | |
} | |
this.negative = 0; | |
this.words = null; | |
this.length = 0; | |
// Reduction context | |
this.red = null; | |
if (number !== null) { | |
if (base === 'le' || base === 'be') { | |
endian = base; | |
base = 10; | |
} | |
this._init(number || 0, base || 10, endian || 'be'); | |
} | |
} | |
if ((typeof module === 'undefined' ? 'undefined' : _typeof(module)) === 'object') { | |
module.exports = BN; | |
} else { | |
exports.BN = BN; | |
} | |
BN.BN = BN; | |
BN.wordSize = 26; | |
var Buffer; | |
try { | |
Buffer = require('buffer').Buffer; | |
} catch (e) {} | |
BN.isBN = function isBN(num) { | |
if (num instanceof BN) { | |
return true; | |
} | |
return num !== null && (typeof num === 'undefined' ? 'undefined' : _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; | |
}; | |
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); | |
} | |
if ((typeof number === 'undefined' ? 'undefined' : _typeof(number)) === 'object') { | |
return this._initArray(number, base, endian); | |
} | |
if (base === 'hex') { | |
base = 16; | |
} | |
assert(base === (base | 0) && base >= 2 && base <= 36); | |
number = number.toString().replace(/\s+/g, ''); | |
var start = 0; | |
if (number[0] === '-') { | |
start++; | |
} | |
if (base === 16) { | |
this._parseHex(number, start); | |
} else { | |
this._parseBase(number, base, start); | |
} | |
if (number[0] === '-') { | |
this.negative = 1; | |
} | |
this.strip(); | |
if (endian !== 'le') return; | |
this._initArray(this.toArray(), base, endian); | |
}; | |
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; | |
} | |
if (endian !== 'le') return; | |
// 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 parseHex(str, start, end) { | |
var r = 0; | |
var len = Math.min(str.length, end); | |
for (var i = start; i < len; i++) { | |
var c = str.charCodeAt(i) - 48; | |
r <<= 4; | |
// 'a' - 'f' | |
if (c >= 49 && c <= 54) { | |
r |= c - 49 + 0xa; | |
// 'A' - 'F' | |
} else if (c >= 17 && c <= 22) { | |
r |= c - 17 + 0xa; | |
// '0' - '9' | |
} else { | |
r |= c & 0xf; | |
} | |
} | |
return r; | |
} | |
BN.prototype._parseHex = function _parseHex(number, start) { | |
// 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; | |
} | |
var j, w; | |
// Scan 24-bit chunks and add them to the number | |
var off = 0; | |
for (i = number.length - 6, j = 0; i >= start; i -= 6) { | |
w = parseHex(number, i, i + 6); | |
this.words[j] |= w << off & 0x3ffffff; | |
// NOTE: `0x3fffff` is intentional here, 26bits max shift + 24bit hex limb | |
this.words[j + 1] |= w >>> 26 - off & 0x3fffff; | |
off += 24; | |
if (off >= 26) { | |
off -= 26; | |
j++; | |
} | |
} | |
if (i + 6 !== start) { | |
w = parseHex(number, start, i + 6); | |
this.words[j] |= w << off & 0x3ffffff; | |
this.words[j + 1] |= w >>> 26 - off & 0x3fffff; | |
} | |
this.strip(); | |
}; | |
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; | |
r *= mul; | |
// 'a' | |
if (c >= 49) { | |
r += c - 49 + 0xa; | |
// 'A' | |
} else if (c >= 17) { | |
r += c - 17 + 0xa; | |
// '0' - '9' | |
} else { | |
r += c; | |
} | |
} | |
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++; | |
} | |
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); | |
} | |
} | |
if (mod !== 0) { | |
var pow = 1; | |
word = parseBase(number, i, number.length, base); | |
for (i = 0; i < mod; i++) { | |
pow *= base; | |
} | |
this.imuln(pow); | |
if (this.words[0] + word < 0x4000000) { | |
this.words[0] += word; | |
} else { | |
this._iaddn(word); | |
} | |
} | |
}; | |
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; | |
}; | |
BN.prototype._expand = function _expand(size) { | |
while (this.length < size) { | |
this.words[this.length++] = 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._normSign = function _normSign() { | |
// -0 = 0 | |
if (this.length === 1 && this.words[0] === 0) { | |
this.negative = 0; | |
} | |
return this; | |
}; | |
BN.prototype.inspect = function inspect() { | |
return (this.red ? '<BN-R: ' : '<BN: ') + this.toString(16) + '>'; | |
}; | |
/* | |
var zeros = []; | |
var groupSizes = []; | |
var groupBases = []; | |
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; | |
} | |
*/ | |
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; | |
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; | |
} | |
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; | |
} | |
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; | |
}; | |
BN.prototype.toJSON = function toJSON() { | |
return this.toString(16); | |
}; | |
BN.prototype.toBuffer = function toBuffer(endian, length) { | |
assert(typeof Buffer !== 'undefined'); | |
return this.toArrayLike(Buffer, endian, length); | |
}; | |
BN.prototype.toArray = function toArray(endian, length) { | |
return this.toArrayLike(Array, endian, length); | |
}; | |
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'); | |
this.strip(); | |
var littleEndian = endian === 'le'; | |
var res = new ArrayType(reqLength); | |
var b, i; | |
var q = this.clone(); | |
if (!littleEndian) { | |
// Assume big-endian | |
for (i = 0; i < reqLength - byteLength; i++) { | |
res[i] = 0; | |
} | |
for (i = 0; !q.isZero(); i++) { | |
b = q.andln(0xff); | |
q.iushrn(8); | |
res[reqLength - i - 1] = b; | |
} | |
} else { | |
for (i = 0; !q.isZero(); i++) { | |
b = q.andln(0xff); | |
q.iushrn(8); | |
res[i] = b; | |
} | |
for (; i < reqLength; i++) { | |
res[i] = 0; | |
} | |
} | |
return res; | |
}; | |
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; | |
}; | |
} | |
BN.prototype._zeroBits = function _zeroBits(w) { | |
// Short-cut | |
if (w === 0) return 26; | |
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; | |
}; | |
// 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; | |
}; | |
function toBitArray(num) { | |
var w = new Array(num.bitLength()); | |
for (var bit = 0; bit < w.length; bit++) { | |
var off = bit / 26 | 0; | |
var wbit = bit % 26; | |
w[bit] = (num.words[off] & 1 << wbit) >>> wbit; | |
} | |
return w; | |
} | |
// 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; | |
}; | |
BN.prototype.byteLength = function byteLength() { | |
return Math.ceil(this.bitLength() / 8); | |
}; | |
BN.prototype.toTwos = function toTwos(width) { | |
if (this.negative !== 0) { | |
return this.abs().inotn(width).iaddn(1); | |
} | |
return this.clone(); | |
}; | |
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; | |
}; | |
// 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; | |
} | |
for (var i = 0; i < num.length; i++) { | |
this.words[i] = this.words[i] | num.words[i]; | |
} | |
return this.strip(); | |
}; | |
BN.prototype.ior = function ior(num) { | |
assert((this.negative | num.negative) === 0); | |
return this.iuor(num); | |
}; | |
// 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); | |
}; | |
BN.prototype.uor = function uor(num) { | |
if (this.length > num.length) return this.clone().iuor(num); | |
return num.clone().iuor(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; | |
} | |
for (var i = 0; i < b.length; i++) { | |
this.words[i] = this.words[i] & num.words[i]; | |
} | |
this.length = b.length; | |
return this.strip(); | |
}; | |
BN.prototype.iand = function iand(num) { | |
assert((this.negative | num.negative) === 0); | |
return this.iuand(num); | |
}; | |
// 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); | |
}; | |
BN.prototype.uand = function uand(num) { | |
if (this.length > num.length) return this.clone().iuand(num); | |
return num.clone().iuand(this); | |
}; | |
// 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 (var i = 0; i < b.length; i++) { | |
this.words[i] = a.words[i] ^ b.words[i]; | |
} | |
if (this !== a) { | |
for (; i < a.length; i++) { | |
this.words[i] = a.words[i]; | |
} | |
} | |
this.length = a.length; | |
return this.strip(); | |
}; | |
BN.prototype.ixor = function ixor(num) { | |
assert((this.negative | num.negative) === 0); | |
return this.iuxor(num); | |
}; | |
// 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); | |
}; | |
BN.prototype.uxor = function uxor(num) { | |
if (this.length > num.length) return this.clone().iuxor(num); | |
return num.clone().iuxor(this); | |
}; | |
// 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; | |
// Extend the buffer with leading zeroes | |
this._expand(bytesNeeded); | |
if (bitsLeft > 0) { | |
bytesNeeded--; | |
} | |
// Handle complete words | |
for (var i = 0; i < bytesNeeded; i++) { | |
this.words[i] = ~this.words[i] & 0x3ffffff; | |
} | |
// Handle the residue | |
if (bitsLeft > 0) { | |
this.words[i] = ~this.words[i] & 0x3ffffff >> 26 - bitsLeft; | |
} | |
// And remove leading zeroes | |
return this.strip(); | |
}; | |
BN.prototype.notn = function notn(width) { | |
return this.clone().inotn(width); | |
}; | |
// Set `bit` of `this` | |
BN.prototype.setn = function setn(bit, val) { | |
assert(typeof bit === 'number' && bit >= 0); | |
var off = bit / 26 | 0; | |
var wbit = bit % 26; | |
this._expand(off + 1); | |
if (val) { | |
this.words[off] = this.words[off] | 1 << wbit; | |
} else { | |
this.words[off] = this.words[off] & ~(1 << wbit); | |
} | |
return this.strip(); | |
}; | |
// Add `num` to `this` in-place | |
BN.prototype.iadd = function iadd(num) { | |
var r; | |
// negative + positive | |
if (this.negative !== 0 && num.negative === 0) { | |
this.negative = 0; | |
r = this.isub(num); | |
this.negative ^= 1; | |
return this._normSign(); | |
// positive + negative | |
} else if (this.negative === 0 && num.negative !== 0) { | |
num.negative = 0; | |
r = this.isub(num); | |
num.negative = 1; | |
return r._normSign(); | |
} | |
// a.length > b.length | |
var a, b; | |
if (this.length > num.length) { | |
a = this; | |
b = num; | |
} else { | |
a = num; | |
b = 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; | |
} | |
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]; | |
} | |
} | |
return this; | |
}; | |
// 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; | |
} | |
if (this.length > num.length) return this.clone().iadd(num); | |
return num.clone().iadd(this); | |
}; | |
// 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(); | |
// -this - num = -(this + num) | |
} else if (this.negative !== 0) { | |
this.negative = 0; | |
this.iadd(num); | |
this.negative = 1; | |
return this._normSign(); | |
} | |
// 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; | |
} | |
// a > b | |
var a, b; | |
if (cmp > 0) { | |
a = this; | |
b = num; | |
} else { | |
a = num; | |
b = this; | |
} | |
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); | |
if (a !== this) { | |
this.negative = 1; | |
} | |
return this.strip(); | |
}; | |
// Subtract `num` from `this` | |
BN.prototype.sub = function sub(num) { | |
return this.clone().isub(num); | |
}; | |
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; | |
// 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; | |
var lo = r & 0x3ffffff; | |
var carry = r / 0x4000000 | 0; | |
out.words[0] = lo; | |
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--; | |
} | |
return out.strip(); | |
} | |
// 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; | |
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; | |
} | |
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; | |
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.strip(); | |
} | |
function jumboMulTo(self, num, out) { | |
var fftm = new FFTM(); | |
return fftm.mulp(self, num, out); | |
} | |
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); | |
} | |
return res; | |
}; | |
// Cooley-Tukey algorithm for FFT | |
// slightly revisited to rely on looping instead of recursion | |
function FFTM(x, y) { | |
this.x = x; | |
this.y = y; | |
} | |
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; | |
}; | |
// 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; | |
} | |
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]]; | |
} | |
}; | |
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; | |
/* jshint maxdepth : false */ | |
if (j !== l) { | |
rx = rtwdf * rtwdf_ - itwdf * itwdf_; | |
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++; | |
} | |
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]; | |
rws[i] = rws[N - i - 1]; | |
rws[N - i - 1] = t; | |
t = iws[i]; | |
iws[i] = -iws[N - i - 1]; | |
iws[N - i - 1] = -t; | |
} | |
}; | |
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; | |
if (w < 0x4000000) { | |
carry = 0; | |
} else { | |
carry = w / 0x4000000 | 0; | |
} | |
} | |
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; | |
} | |
// Pad with zeroes | |
for (i = 2 * len; i < N; ++i) { | |
rws[i] = 0; | |
} | |
assert(carry === 0); | |
assert((carry & ~0x1fff) === 0); | |
}; | |
FFTM.prototype.stub = function stub(N) { | |
var ph = new Array(N); | |
for (var i = 0; i < N; i++) { | |
ph[i] = 0; | |
} | |
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; | |
this.convert13b(x.words, x.length, rws, N); | |
this.convert13b(y.words, y.length, nrws, N); | |
this.transform(rws, _, rwst, iwst, N, rbt); | |
this.transform(nrws, _, nrwst, niwst, N, rbt); | |
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; | |
} | |
this.conjugate(rwst, iwst, N); | |
this.transform(rwst, iwst, rmws, _, N, rbt); | |
this.conjugate(rmws, _, N); | |
this.normalize13b(rmws, N); | |
out.negative = x.negative ^ y.negative; | |
out.length = x.length + y.length; | |
return out.strip(); | |
}; | |
// 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); | |
}; | |
// 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); | |
}; | |
// 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); | |
// 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 (carry !== 0) { | |
this.words[i] = carry; | |
this.length++; | |
} | |
return this; | |
}; | |
BN.prototype.muln = function muln(num) { | |
return this.clone().imuln(num); | |
}; | |
// `this` * `this` | |
BN.prototype.sqr = function sqr() { | |
return this.mul(this); | |
}; | |
// `this` * `this` in-place | |
BN.prototype.isqr = function isqr() { | |
return this.imul(this.clone()); | |
}; | |
// 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; | |
} | |
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); | |
} | |
} | |
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 (s !== 0) { | |
for (i = this.length - 1; i >= 0; i--) { | |
this.words[i + s] = this.words[i]; | |
} | |
for (i = 0; i < s; i++) { | |
this.words[i] = 0; | |
} | |
this.length += s; | |
} | |
return this.strip(); | |
}; | |
BN.prototype.ishln = function ishln(bits) { | |
// TODO(indutny): implement me | |
assert(this.negative === 0); | |
return this.iushln(bits); | |
}; | |
// 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; | |
} | |
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); | |
// Extended mode, copy masked part | |
if (maskedWords) { | |
for (var i = 0; i < s; i++) { | |
maskedWords.words[i] = this.words[i]; | |
} | |
maskedWords.length = s; | |
} | |
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 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; | |
} | |
// 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; | |
} | |
return this.strip(); | |
}; | |
BN.prototype.ishrn = function ishrn(bits, hint, extended) { | |
// TODO(indutny): implement me | |
assert(this.negative === 0); | |
return this.iushrn(bits, hint, extended); | |
}; | |
// Shift-left | |
BN.prototype.shln = function shln(bits) { | |
return this.clone().ishln(bits); | |
}; | |
BN.prototype.ushln = function ushln(bits) { | |
return this.clone().iushln(bits); | |
}; | |
// 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'); | |
if (this.length <= s) { | |
return this; | |
} | |
if (r !== 0) { | |
s++; | |
} | |
this.length = Math.min(s, this.length); | |
if (r !== 0) { | |
var mask = 0x3ffffff ^ 0x3ffffff >>> r << r; | |
this.words[this.length - 1] &= mask; | |
} | |
return this.strip(); | |
}; | |
// Return only lowers bits of number | |
BN.prototype.maskn = function maskn(bits) { | |
return this.clone().imaskn(bits); | |
}; | |
// 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); | |
// 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.negative = 0; | |
this.isubn(num); | |
this.negative = 1; | |
return this; | |
} | |
// 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); | |
return this; | |
}; | |
// 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; | |
} | |
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; | |
} | |
} | |
return this.strip(); | |
}; | |
BN.prototype.addn = function addn(num) { | |
return this.clone().iaddn(num); | |
}; | |
BN.prototype.subn = function subn(num) { | |
return this.clone().isubn(num); | |
}; | |
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; | |
} | |
if (carry === 0) return this.strip(); | |
// 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(); | |
}; | |
BN.prototype._wordDiv = function _wordDiv(num, mode) { | |
var shift = this.length - num.length; | |
var a = this.clone(); | |
var b = num; | |
// 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; | |
} | |
// Initialize quotient | |
var m = a.length - b.length; | |
var q; | |
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 diff = a.clone()._ishlnsubmul(b, 1, m); | |
if (diff.negative === 0) { | |
a = diff; | |
if (q) { | |
q.words[m] = 1; | |
} | |
} | |
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; | |
} | |
} | |
if (q) { | |
q.words[j] = qj; | |
} | |
} | |
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 (mode !== 'div') { | |
mod = res.mod.neg(); | |
if (positive && mod.negative !== 0) { | |
mod.iadd(num); | |
} | |
} | |
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(); | |
} | |
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); | |
} | |
} | |
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 | |
}; | |
} | |
// Very short reduction | |
if (num.length === 1) { | |
if (mode === 'div') { | |
return { | |
div: this.divn(num.words[0]), | |
mod: null | |
}; | |
} | |
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])) | |
}; | |
} | |
return this._wordDiv(num, mode); | |
}; | |
// Find `this` / `num` | |
BN.prototype.div = function div(num) { | |
return this.divmod(num, 'div', false).div; | |
}; | |
// Find `this` % `num` | |
BN.prototype.mod = function mod(num) { | |
return this.divmod(num, 'mod', false).mod; | |
}; | |
BN.prototype.umod = function umod(num) { | |
return this.divmod(num, 'mod', true).mod; | |
}; | |
// Find Round(`this` / `num`) | |
BN.prototype.divRound = function divRound(num) { | |
var dm = this.divmod(num); | |
// Fast case - exact division | |
if (dm.mod.isZero()) return dm.div; | |
var mod = dm.div.negative !== 0 ? dm.mod.isub(num) : dm.mod; | |
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; | |
// 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; | |
} | |
return acc; | |
}; | |
// In-place division by number | |
BN.prototype.idivn = function idivn(num) { | |
assert(num <= 0x3ffffff); | |
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; | |
} | |
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 (x.negative !== 0) { | |
x = x.umod(p); | |
} else { | |
x = x.clone(); | |
} | |
// 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; | |
} | |
var yp = y.clone(); | |
var xp = x.clone(); | |
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); | |
} | |
A.iushrn(1); | |
B.iushrn(1); | |
} | |
} | |
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); | |
} | |
C.iushrn(1); | |
D.iushrn(1); | |
} | |
} | |
if (x.cmp(y) >= 0) { | |
x.isub(y); | |
A.isub(C); | |
B.isub(D); | |
} else { | |
y.isub(x); | |
C.isub(A); | |
D.isub(B); | |
} | |
} | |
return { | |
a: C, | |
b: D, | |
gcd: y.iushln(g) | |
}; | |
}; | |
// 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()); | |
var a = this; | |
var b = p.clone(); | |
if (a.negative !== 0) { | |
a = a.umod(p); | |
} else { | |
a = a.clone(); | |
} | |
var x1 = new BN(1); | |
var x2 = new BN(0); | |
var delta = b.clone(); | |
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); | |
} | |
x1.iushrn(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); | |
} | |
x2.iushrn(1); | |
} | |
} | |
if (a.cmp(b) >= 0) { | |
a.isub(b); | |
x1.isub(x2); | |
} else { | |
b.isub(a); | |
x2.isub(x1); | |
} | |
} | |
var res; | |
if (a.cmpn(1) === 0) { | |
res = x1; | |
} else { | |
res = x2; | |
} | |
if (res.cmpn(0) < 0) { | |
res.iadd(p); | |
} | |
return res; | |
}; | |
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); | |
} | |
do { | |
while (a.isEven()) { | |
a.iushrn(1); | |
} | |
while (b.isEven()) { | |
b.iushrn(1); | |
} | |
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; | |
} | |
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; | |
}; | |
BN.prototype.isOdd = function isOdd() { | |
return (this.words[0] & 1) === 1; | |
}; | |
// And first word and num | |
BN.prototype.andln = function andln(num) { | |
return this.words[0] & num; | |
}; | |
// 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; | |
} | |
// 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; | |
}; | |
BN.prototype.isZero = function isZero() { | |
return this.length === 1 && this.words[0] === 0; | |
}; | |
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(); | |
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 (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; | |
var res = this.ucmp(num); | |
if (this.negative !== 0) return -res | 0; | |
return res; | |
}; | |
// 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; | |
if (a === b) continue; | |
if (a < b) { | |
res = -1; | |
} else if (a > b) { | |
res = 1; | |
} | |
break; | |
} | |
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); | |
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 { | |
r.strip(); | |
} | |
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]; | |
} | |
output.length = outLen; | |
if (input.length <= 9) { | |
input.words[0] = 0; | |
input.length = 1; | |
return; | |
} | |
// 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; | |
} | |
prev >>>= 22; | |
input.words[i - 10] = prev; | |
if (prev === 0 && input.length > 10) { | |
input.length -= 10; | |
} else { | |
input.length -= 9; | |
} | |
}; | |
K256.prototype.imulK = function imulK(num) { | |
// K = 0x1000003d1 = [ 0x40, 0x3d1 ] | |
num.words[num.length] = 0; | |
num.words[num.length + 1] = 0; | |
num.length += 2; | |
// 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); | |
} | |
// Fast length reduction | |
if (num.words[num.length - 1] === 0) { | |
num.length--; | |
if (num.words[num.length - 1] === 0) { | |
num.length--; | |
} | |
} | |
return num; | |
}; | |
function P224() { | |
MPrime.call(this, 'p224', 'ffffffff ffffffff ffffffff ffffffff 00000000 00000000 00000001'); | |
} | |
inherits(P224, MPrime); | |
function P192() { | |
MPrime.call(this, 'p192', 'ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff'); | |
} | |
inherits(P192, MPrime); | |
function P25519() { | |
// 2 ^ 255 - 19 | |
MPrime.call(this, '25519', '7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed'); | |
} | |
inherits(P25519, MPrime); | |
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; | |
num.words[i] = lo; | |
carry = hi; | |
} | |
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(); | |
} 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; | |
} | |
} | |
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); | |
return a.umod(this.m)._forceRed(this); | |
}; | |
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, undefined); | |
},{"buffer":101}],100:[function(require,module,exports){ | |
'use strict'; | |
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; | |
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 === 'undefined' ? 'undefined' : _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 === 'undefined' ? 'undefined' : _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":101}],101:[function(require,module,exports){ | |
"use strict"; | |
},{}],102:[function(require,module,exports){ | |
'use strict'; | |
// 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; | |
} | |
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]; | |
} | |
// 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; | |
} | |
} | |
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; | |
// Compute multiplication | |
var x2 = d[x]; | |
var x4 = d[x2]; | |
var x8 = d[x4]; | |
// 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; | |
// 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 (x === 0) { | |
x = xi = 1; | |
} else { | |
x = x2 ^ d[d[d[x8 ^ x2]]]; | |
xi ^= d[d[xi]]; | |
} | |
} | |
return { | |
SBOX: SBOX, | |
INV_SBOX: INV_SBOX, | |
SUB_MIX: SUB_MIX, | |
INV_SUB_MIX: INV_SUB_MIX | |
}; | |
}(); | |
function AES(key) { | |
this._key = asUInt32Array(key); | |
this._reset(); | |
} | |
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 keySchedule = []; | |
for (var k = 0; k < keySize; k++) { | |
keySchedule[k] = keyWords[k]; | |
} | |
for (k = keySize; k < ksRows; k++) { | |
var t = keySchedule[k - 1]; | |
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]; | |
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]; | |
} | |
keySchedule[k] = keySchedule[k - keySize] ^ t; | |
} | |
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]]; | |
} | |
} | |
this._nRounds = nRounds; | |
this._keySchedule = keySchedule; | |
this._invKeySchedule = invKeySchedule; | |
}; | |
AES.prototype.encryptBlockRaw = function (M) { | |
M = asUInt32Array(M); | |
return cryptBlock(M, this._keySchedule, G.SUB_MIX, G.SBOX, this._nRounds); | |
}; | |
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; | |
}; | |
AES.prototype.decryptBlock = function (M) { | |
M = asUInt32Array(M); | |
// swap | |
var m1 = M[1]; | |
M[1] = M[3]; | |
M[3] = m1; | |
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; | |
}; | |
AES.prototype.scrub = function () { | |
scrubVec(this._keySchedule); | |
scrubVec(this._invKeySchedule); | |
scrubVec(this._key); | |
}; | |
module.exports.AES = AES; | |
},{"safe-buffer":314}],103:[function(require,module,exports){ | |
'use strict'; | |
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]; | |
} | |
return out; | |
} | |
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); | |
var h = Buffer.alloc(4, 0); | |
this._cipher = new aes.AES(key); | |
var ck = this._cipher.encryptBlock(h); | |
this._ghash = new GHASH(ck); | |
iv = calcIv(this, iv, ck); | |
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; | |
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); | |
} | |
} | |
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; | |
}; | |
StreamCipher.prototype._final = function () { | |
if (this._decrypt && !this._authTag) throw new Error('Unsupported state or unable to authenticate data'); | |
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'); | |
this._authTag = tag; | |
this._cipher.scrub(); | |
}; | |
StreamCipher.prototype.getAuthTag = function getAuthTag() { | |
if (this._decrypt || !Buffer.isBuffer(this._authTag)) throw new Error('Attempting to get auth tag in unsupported state'); | |
return this._authTag; | |
}; | |
StreamCipher.prototype.setAuthTag = function setAuthTag(tag) { | |
if (!this._decrypt) throw new Error('Attempting to set auth tag in unsupported state'); | |
this._authTag = tag; | |
}; | |
StreamCipher.prototype.setAAD = function setAAD(buf) { | |
if (this._called) throw new Error('Attempting to set AAD in unsupported state'); | |
this._ghash.update(buf); | |
this._alen += buf.length; | |
}; | |
module.exports = StreamCipher; | |
},{"./aes":102,"./ghash":107,"./incr32":108,"buffer-xor":147,"cipher-base":149,"inherits":256,"safe-buffer":314}],104:[function(require,module,exports){ | |
'use strict'; | |
var ciphers = require('./encrypter'); | |
var deciphers = require('./decrypter'); | |
var modes = require('./modes/list.json'); | |
function getCiphers() { | |
return Object.keys(modes); | |
} | |
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; | |
},{"./decrypter":105,"./encrypter":106,"./modes/list.json":116}],105:[function(require,module,exports){ | |
'use strict'; | |
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'); | |
function Decipher(mode, key, iv) { | |
Transform.call(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; | |
} | |
inherits(Decipher, Transform); | |
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); | |
}; | |
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'); | |
} | |
}; | |
Decipher.prototype.setAutoPadding = function (setTo) { | |
this._autopadding = !!setTo; | |
return this; | |
}; | |
function Splitter() { | |
this.cache = Buffer.allocUnsafe(0); | |
} | |
Splitter.prototype.add = function (data) { | |
this.cache = Buffer.concat([this.cache, data]); | |
}; | |
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; | |
} | |
} | |
return null; | |
}; | |
Splitter.prototype.flush = function () { | |
if (this.cache.length) return this.cache; | |
}; | |
function unpad(last) { | |
var padded = last[15]; | |
var i = -1; | |
while (++i < padded) { | |
if (last[i + (16 - padded)] !== padded) { | |
throw new Error('unable to decrypt data'); | |
} | |
} | |
if (padded === 16) return; | |
return last.slice(0, 16 - padded); | |
} | |
function createDecipheriv(suite, password, iv) { | |
var config = MODES[suite.toLowerCase()]; | |
if (!config) throw new TypeError('invalid suite type'); | |
if (typeof iv === 'string') iv = Buffer.from(iv); | |
if (config.mode !== 'GCM' && iv.length !== config.iv) throw new TypeError('invalid iv length ' + iv.length); | |
if (typeof password === 'string') password = Buffer.from(password); | |
if (password.length !== config.key / 8) throw new TypeError('invalid key length ' + password.length); | |
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); | |
} | |
return new Decipher(config.module, password, iv); | |
} | |
function createDecipher(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 createDecipheriv(suite, keys.key, keys.iv); | |
} | |
exports.createDecipher = createDecipher; | |
exports.createDecipheriv = createDecipheriv; | |
},{"./aes":102,"./authCipher":103,"./modes":115,"./streamCipher":118,"cipher-base":149,"evp_bytestokey":238,"inherits":256,"safe-buffer":314}],106:[function(require,module,exports){ | |
'use strict'; | |
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'); | |
function Cipher(mode, key, iv) { | |
Transform.call(this); | |
this._cache = new Splitter(); | |
this._cipher = new aes.AES(key); | |
this._prev = Buffer.from(iv); | |
this._mode = mode; | |
this._autopadding = true; | |
} | |
inherits(Cipher, Transform); | |
Cipher.prototype._update = function (data) { | |
this._cache.add(data); | |
var chunk; | |
var thing; | |
var out = []; | |
while (chunk = this._cache.get()) { | |
thing = this._mode.encrypt(this, chunk); | |
out.push(thing); | |
} | |
return Buffer.concat(out); | |
}; | |
var PADDING = Buffer.alloc(16, 0x10); | |
Cipher.prototype._final = function () { | |
var chunk = this._cache.flush(); | |
if (this._autopadding) { | |
chunk = this._mode.encrypt(this, chunk); | |
this._cipher.scrub(); | |
return chunk; | |
} | |
if (!chunk.equals(PADDING)) { | |
this._cipher.scrub(); | |
throw new Error('data not multiple of block length'); | |
} | |
}; | |
Cipher.prototype.setAutoPadding = function (setTo) { | |
this._autopadding = !!setTo; | |
return this; | |
}; | |
function Splitter() { | |
this.cache = Buffer.allocUnsafe(0); | |
} | |
Splitter.prototype.add = function (data) { | |
this.cache = Buffer.concat([this.cache, data]); | |
}; | |
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; | |
}; | |
Splitter.prototype.flush = function () { | |
var len = 16 - this.cache.length; | |
var padBuff = Buffer.allocUnsafe(len); | |
var i = -1; | |
while (++i < len) { | |
padBuff.writeUInt8(len, i); | |
} | |
return Buffer.concat([this.cache, padBuff]); | |
}; | |
function createCipheriv(suite, password, iv) { | |
var config = MODES[suite.toLowerCase()]; | |
if (!config) throw new TypeError('invalid suite type'); | |
if (typeof password === 'string') password = Buffer.from(password); | |
if (password.length !== config.key / 8) throw new TypeError('invalid key length ' + password.length); | |
if (typeof iv === 'string') iv = Buffer.from(iv); | |
if (config.mode !== 'GCM' && iv.length !== config.iv) throw new TypeError('invalid iv length ' + iv.length); | |
if (config.type === 'stream') { | |
return new StreamCipher(config.module, password, iv); | |
} else if (config.type === 'auth') { | |
return new AuthCipher(config.module, password, iv); | |
} | |
return new Cipher(config.module, password, iv); | |
} | |
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":102,"./authCipher":103,"./modes":115,"./streamCipher":118,"cipher-base":149,"evp_bytestokey":238,"inherits":256,"safe-buffer":314}],107:[function(require,module,exports){ | |
'use strict'; | |
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]; | |
} | |
// 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; | |
// 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); | |
}; | |
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); | |
} | |
}; | |
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":314}],108:[function(require,module,exports){ | |
"use strict"; | |
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; | |
},{}],109:[function(require,module,exports){ | |
'use strict'; | |
var xor = require('buffer-xor'); | |
exports.encrypt = function (self, block) { | |
var data = xor(block, self._prev); | |
self._prev = self._cipher.encryptBlock(data); | |
return self._prev; | |
}; | |
exports.decrypt = function (self, block) { | |
var pad = self._prev; | |
self._prev = block; | |
var out = self._cipher.decryptBlock(block); | |
return xor(out, pad); | |
}; | |
},{"buffer-xor":147}],110:[function(require,module,exports){ | |
'use strict'; | |
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 (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; | |
} | |
} | |
return out; | |
}; | |
},{"buffer-xor":147,"safe-buffer":314}],111:[function(require,module,exports){ | |
'use strict'; | |
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; | |
} | |
function shiftIn(buffer, value) { | |
var len = buffer.length; | |
var i = -1; | |
var out = Buffer.allocUnsafe(buffer.length); | |
buffer = Buffer.concat([buffer, Buffer.from([value])]); | |
while (++i < len) { | |
out[i] = buffer[i] << 1 | buffer[i + 1] >> 7; | |
} | |
return out; | |
} | |
exports.encrypt = function (self, chunk, decrypt) { | |
var len = chunk.length; | |
var out = Buffer.allocUnsafe(len); | |
var i = -1; | |
while (++i < len) { | |
out[i] = encryptByte(self, chunk[i], decrypt); | |
} | |
return out; | |
}; | |
},{"safe-buffer":314}],112:[function(require,module,exports){ | |
'use strict'; | |
var Buffer = require('safe-buffer').Buffer; | |
function encryptByte(self, byteParam, decrypt) { | |
var pad = self._cipher.encryptBlock(self._prev); | |
var out = pad[0] ^ byteParam; | |
self._prev = Buffer.concat([self._prev.slice(1), Buffer.from([decrypt ? byteParam : out])]); | |
return out; | |
} | |
exports.encrypt = function (self, chunk, decrypt) { | |
var len = chunk.length; | |
var out = Buffer.allocUnsafe(len); | |
var i = -1; | |
while (++i < len) { | |
out[i] = encryptByte(self, chunk[i], decrypt); | |
} | |
return out; | |
}; | |
},{"safe-buffer":314}],113:[function(require,module,exports){ | |
'use strict'; | |
var xor = require('buffer-xor'); | |
var Buffer = require('safe-buffer').Buffer; | |
var incr32 = require('../incr32'); | |
function getBlock(self) { | |
var out = self._cipher.encryptBlockRaw(self._prev); | |
incr32(self._prev); | |
return out; | |
} | |
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); | |
}; | |
},{"../incr32":108,"buffer-xor":147,"safe-buffer":314}],114:[function(require,module,exports){ | |
"use strict"; | |
exports.encrypt = function (self, block) { | |
return self._cipher.encryptBlock(block); | |
}; | |
exports.decrypt = function (self, block) { | |
return self._cipher.decryptBlock(block); | |
}; | |
},{}],115:[function(require,module,exports){ | |
'use strict'; | |
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 modes = require('./list.json'); | |
for (var key in modes) { | |
modes[key].module = modeModules[modes[key].mode]; | |
} | |
module.exports = modes; | |
},{"./cbc":109,"./cfb":110,"./cfb1":111,"./cfb8":112,"./ctr":113,"./ecb":114,"./list.json":116,"./ofb":117}],116:[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" | |
} | |
} | |
},{}],117:[function(require,module,exports){ | |
(function (Buffer){ | |
'use strict'; | |
var xor = require('buffer-xor'); | |
function getBlock(self) { | |
self._prev = self._cipher.encryptBlock(self._prev); | |
return self._prev; | |
} | |
exports.encrypt = function (self, chunk) { | |
while (self._cache.length < chunk.length) { | |
self._cache = Buffer.concat([self._cache, getBlock(self)]); | |
} | |
var pad = self._cache.slice(0, chunk.length); | |
self._cache = self._cache.slice(chunk.length); | |
return xor(chunk, pad); | |
}; | |
}).call(this,require("buffer").Buffer) | |
},{"buffer":148,"buffer-xor":147}],118:[function(require,module,exports){ | |
'use strict'; | |
var aes = require('./aes'); | |
var Buffer = require('safe-buffer').Buffer; | |
var Transform = require('cipher-base'); | |
var inherits = require('inherits'); | |
function StreamCipher(mode, key, iv, decrypt) { | |
Transform.call(this); | |
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; | |
} | |
inherits(StreamCipher, Transform); | |
StreamCipher.prototype._update = function (chunk) { | |
return this._mode.encrypt(this, chunk, this._decrypt); | |
}; | |
StreamCipher.prototype._final = function () { | |
this._cipher.scrub(); | |
}; | |
module.exports = StreamCipher; | |
},{"./aes":102,"cipher-base":149,"inherits":256,"safe-buffer":314}],119:[function(require,module,exports){ | |
'use strict'; | |
var ebtk = require('evp_bytestokey'); | |
var aes = require('browserify-aes/browser'); | |
var DES = require('browserify-des'); | |
var desModes = require('browserify-des/modes'); | |
var aesModes = require('browserify-aes/modes'); | |
function createCipher(suite, password) { | |
var keyLen, ivLen; | |
suite = suite.toLowerCase(); | |
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'); | |
} | |
var keys = ebtk(password, false, keyLen, ivLen); | |
return createCipheriv(suite, keys.key, keys.iv); | |
} | |
function createDecipher(suite, password) { | |
var keyLen, ivLen; | |
suite = suite.toLowerCase(); | |
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'); | |
} | |
var keys = ebtk(password, false, keyLen, ivLen); | |
return createDecipheriv(suite, keys.key, keys.iv); | |
} | |
function createCipheriv(suite, key, iv) { | |
suite = suite.toLowerCase(); | |
if (aesModes[suite]) { | |
return aes.createCipheriv(suite, key, iv); | |
} else if (desModes[suite]) { | |
return new DES({ | |
key: key, | |
iv: iv, | |
mode: suite | |
}); | |
} else { | |
throw new TypeError('invalid suite type'); | |
} | |
} | |
function createDecipheriv(suite, key, iv) { | |
suite = suite.toLowerCase(); | |
if (aesModes[suite]) { | |
return aes.createDecipheriv(suite, key, iv); | |
} else if (desModes[suite]) { | |
return new DES({ | |
key: key, | |
iv: iv, | |
mode: suite, | |
decrypt: true | |
}); | |
} else { | |
throw new TypeError('invalid suite type'); | |
} | |
} | |
exports.createCipher = exports.Cipher = createCipher; | |
exports.createCipheriv = exports.Cipheriv = createCipheriv; | |
exports.createDecipher = exports.Decipher = createDecipher; | |
exports.createDecipheriv = exports.Decipheriv = createDecipheriv; | |
function getCiphers() { | |
return Object.keys(desModes).concat(aes.getCiphers()); | |
} | |
exports.listCiphers = exports.getCiphers = getCiphers; | |
},{"browserify-aes/browser":104,"browserify-aes/modes":115,"browserify-des":120,"browserify-des/modes":121,"evp_bytestokey":238}],120:[function(require,module,exports){ | |
(function (Buffer){ | |
'use strict'; | |
var CipherBase = require('cipher-base'); | |
var des = require('des.js'); | |
var inherits = require('inherits'); | |
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 (modeName === 'des-ede' || modeName === 'des-ede-cbc') { | |
key = Buffer.concat([key, key.slice(0, 8)]); | |
} | |
var iv = opts.iv; | |
this._des = mode.create({ | |
key: key, | |
iv: iv, | |
type: type | |
}); | |
} | |
DES.prototype._update = function (data) { | |
return new Buffer(this._des.update(data)); | |
}; | |
DES.prototype._final = function () { | |
return new Buffer(this._des.final()); | |
}; | |
}).call(this,require("buffer").Buffer) | |
},{"buffer":148,"cipher-base":149,"des.js":208,"inherits":256}],121:[function(require,module,exports){ | |
'use strict'; | |
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 | |
}; | |
},{}],122:[function(require,module,exports){ | |
(function (Buffer){ | |
'use strict'; | |
var bn = require('bn.js'); | |
var randomBytes = require('randombytes'); | |
module.exports = crt; | |
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) | |
}; | |
} | |
function crt(msg, priv) { | |
var blinds = blind(priv); | |
var len = priv.modulus.byteLength(); | |
var mod = bn.mont(priv.modulus); | |
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); | |
var m2 = c2.redPow(priv.exponent2); | |
m1 = m1.fromRed(); | |
m2 = m2.fromRed(); | |
var h = m1.isub(m2).imul(qinv).umod(p); | |
h.imul(q); | |
m2.iadd(h); | |
return new Buffer(m2.imul(blinds.unblinder).umod(priv.modulus).toArray(false, len)); | |
} | |
crt.getr = getr; | |
function getr(priv) { | |
var len = priv.modulus.byteLength(); | |
var r = new bn(randomBytes(len)); | |
while (r.cmp(priv.modulus) >= 0 || !r.umod(priv.prime1) || !r.umod(priv.prime2)) { | |
r = new bn(randomBytes(len)); | |
} | |
return r; | |
} | |
}).call(this,require("buffer").Buffer) | |
},{"bn.js":99,"buffer":148,"randombytes":295}],123:[function(require,module,exports){ | |
'use strict'; | |
module.exports = require('./browser/algorithms.json'); | |
},{"./browser/algorithms.json":124}],124:[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" | |
} | |
} | |
},{}],125:[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" | |
} | |
},{}],126:[function(require,module,exports){ | |
(function (Buffer){ | |
'use strict'; | |
var createHash = require('create-hash'); | |
var stream = require('stream'); | |
var inherits = require('inherits'); | |
var sign = require('./sign'); | |
var verify = require('./verify'); | |
var algorithms = require('./algorithms.json'); | |
Object.keys(algorithms).forEach(function (key) { | |
algorithms[key].id = new Buffer(algorithms[key].id, 'hex'); | |
algorithms[key.toLowerCase()] = algorithms[key]; | |
}); | |
function Sign(algorithm) { | |
stream.Writable.call(this); | |
var data = algorithms[algorithm]; | |
if (!data) throw new Error('Unknown message digest'); | |
this._hashType = data.hash; | |
this._hash = createHash(data.hash); | |
this._tag = data.id; | |
this._signType = data.sign; | |
} | |
inherits(Sign, stream.Writable); | |
Sign.prototype._write = function _write(data, _, done) { | |
this._hash.update(data); | |
done(); | |
}; | |
Sign.prototype.update = function update(data, enc) { | |
if (typeof data === 'string') data = new Buffer(data, enc); | |
this._hash.update(data); | |
return this; | |
}; | |
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); | |
return enc ? sig.toString(enc) : sig; | |
}; | |
function Verify(algorithm) { | |
stream.Writable.call(this); | |
var data = algorithms[algorithm]; | |
if (!data) throw new Error('Unknown message digest'); | |
this._hash = createHash(data.hash); | |
this._tag = data.id; | |
this._signType = data.sign; | |
} | |
inherits(Verify, stream.Writable); | |
Verify.prototype._write = function _write(data, _, done) { | |
this._hash.update(data); | |
done(); | |
}; | |
Verify.prototype.update = function update(data, enc) { | |
if (typeof data === 'string') data = new Buffer(data, enc); | |
this._hash.update(data); | |
return this; | |
}; | |
Verify.prototype.verify = function verifyMethod(key, sig, enc) { | |
if (typeof sig === 'string') sig = new Buffer(sig, enc); | |
this.end(); | |
var hash = this._hash.digest(); | |
return verify(sig, hash, key, this._signType, this._tag); | |
}; | |
function createSign(algorithm) { | |
return new Sign(algorithm); | |
} | |
function createVerify(algorithm) { | |
return new Verify(algorithm); | |
} | |
module.exports = { | |
Sign: createSign, | |
Verify: createVerify, | |
createSign: createSign, | |
createVerify: createVerify | |
}; | |
}).call(this,require("buffer").Buffer) | |
},{"./algorithms.json":124,"./sign":127,"./verify":128,"buffer":148,"create-hash":168,"inherits":256,"stream":346}],127:[function(require,module,exports){ | |
(function (Buffer){ | |
'use strict'; | |
// much of this based on https://github.com/indutny/self-signed/blob/gh-pages/lib/rsa.js | |
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 out = crt(pad, priv); | |
return out; | |
} | |
function ecSign(hash, priv) { | |
var curveId = curves[priv.curve.join('.')]; | |
if (!curveId) throw new Error('unknown curve ' + priv.curve.join('.')); | |
var curve = new EC(curveId); | |
var key = curve.keyFromPrivate(priv.privateKey); | |
var out = key.sign(hash); | |
return new Buffer(out.toDER()); | |
} | |
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); | |
} | |
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 new Buffer(res); | |
} | |
function getKey(x, q, hash, algo) { | |
x = new Buffer(x.toArray()); | |
if (x.length < q.byteLength()) { | |
var zeros = new Buffer(q.byteLength() - x.length); | |
zeros.fill(0); | |
x = Buffer.concat([zeros, x]); | |
} | |
var hlen = hash.length; | |
var hbits = bits2octets(hash, q); | |
var v = new Buffer(hlen); | |
v.fill(1); | |
var k = new Buffer(hlen); | |
k.fill(0); | |
k = createHmac(algo, k).update(v).update(new Buffer([0])).update(x).update(hbits).digest(); | |
v = createHmac(algo, k).update(v).digest(); | |
k = createHmac(algo, k).update(v).update(new Buffer([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 bits |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment