diff --git a/bitcore.js b/bitcore.js index bb92336ae..4a6af689a 100644 --- a/bitcore.js +++ b/bitcore.js @@ -10,8 +10,16 @@ var requireWhenAccessed = function(name, file) { Object.defineProperty(module.exports, name, {get: function() {return require(file)}}); }; -requireWhenAccessed('bignum', 'bignum'); -requireWhenAccessed('base58', 'base58-native'); +requireWhenAccessed('Bignum', './lib/Bignum'); +Object.defineProperty(module.exports, 'bignum', {get: function() { + console.log('bignum (with a lower-case "b") is deprecated. Use bitcore.Bignum (capital "B") instead.'); + return require('./lib/Bignum'); +}}); +requireWhenAccessed('Base58', './lib/Base58'); +Object.defineProperty(module.exports, 'base58', {get: function() { + console.log('base58 (with a lower-case "b") is deprecated. Use bitcore.Base58 (capital "B") instead.'); + return require('./lib/Base58'); +}}); requireWhenAccessed('bufferput', 'bufferput'); requireWhenAccessed('buffertools', 'buffertools'); requireWhenAccessed('Buffers.monkey', './patches/Buffers.monkey'); @@ -56,6 +64,6 @@ module.exports.Buffer = Buffer; if (typeof process.versions === 'undefined') { // Browser specific - module.exports.bignum.config({EXPONENTIAL_AT: 9999999, DECIMAL_PLACES: 0, ROUNDING_MODE: 1}); + module.exports.Bignum.config({EXPONENTIAL_AT: 9999999, DECIMAL_PLACES: 0, ROUNDING_MODE: 1}); } diff --git a/browser/bignum_config.js b/browser/bignum_config.js deleted file mode 100644 index 1710d22be..000000000 --- a/browser/bignum_config.js +++ /dev/null @@ -1,6 +0,0 @@ -require('bignum').config({ - EXPONENTIAL_AT: 9999999, - DECIMAL_PLACES: 0, - ROUNDING_MODE: 1, -}); - diff --git a/browser/build.js b/browser/build.js index 0b8b59f40..61f7ada0b 100644 --- a/browser/build.js +++ b/browser/build.js @@ -24,6 +24,8 @@ var pack = function (params) { var modules = [ 'lib/Address', + 'lib/Base58', + 'lib/Bignum', 'lib/BIP32', 'lib/Block', 'lib/Bloom', @@ -94,18 +96,12 @@ var createBitcore = function(opts) { }; var b = browserify(bopts); - b.require(opts.dir + 'browserify-bignum/bignumber.js', { - expose: 'bignum' - }); b.require(opts.dir + 'browserify-buffertools/buffertools.js', { expose: 'buffertools' }); b.require(opts.dir + 'bufferput', { expose: 'bufferput' }); - b.require(opts.dir + 'base58-native', { - expose: 'base58-native' - }); b.require(opts.dir + 'buffers', { expose: 'buffers' }); diff --git a/lib/BIP32.js b/lib/BIP32.js index 6484af02e..ba9699e34 100644 --- a/lib/BIP32.js +++ b/lib/BIP32.js @@ -1,11 +1,10 @@ var imports = require('soop').imports(); -var base58 = imports.base58 || require('base58-native').base58; +var base58 = imports.base58 || require('./Base58').base58; var coinUtil = imports.coinUtil || require('../util'); var Key = imports.Key || require('./Key'); var Point = imports.Point || require('./Point'); var SecureRandom = imports.SecureRandom || require('./SecureRandom'); -var bignum = imports.bignum || require('bignum'); -var crypto = require('crypto'); +var bignum = imports.bignum || require('./Bignum'); var networks = require('../networks'); var secp256k1_n = new bignum("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141", 16); diff --git a/lib/Base58.js b/lib/Base58.js new file mode 100644 index 000000000..71f1c2311 --- /dev/null +++ b/lib/Base58.js @@ -0,0 +1,116 @@ +var crypto = require('crypto'); +var bignum = require('./Bignum'); + +var globalBuffer = new Buffer(1024); +var zerobuf = new Buffer(0); +var ALPHABET = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'; +var ALPHABET_ZERO = ALPHABET[0]; +var ALPHABET_BUF = new Buffer(ALPHABET, 'ascii'); +var ALPHABET_INV = {}; +for(var i=0; i < ALPHABET.length; i++) { + ALPHABET_INV[ALPHABET[i]] = i; +}; + +// Vanilla Base58 Encoding +var base58 = { + encode: function(buf) { + var str; + var x = bignum.fromBuffer(buf); + var r; + + if(buf.length < 512) { + str = globalBuffer; + } else { + str = new Buffer(buf.length << 1); + } + var i = str.length - 1; + while(x.gt(0)) { + r = x.mod(58); + x = x.div(58); + str[i] = ALPHABET_BUF[r.toNumber()]; + i--; + } + + // deal with leading zeros + var j=0; + while(buf[j] == 0) { + str[i] = ALPHABET_BUF[0]; + j++; i--; + } + + return str.slice(i+1,str.length).toString('ascii'); + }, + + decode: function(str) { + if(str.length == 0) return zerobuf; + var answer = bignum(0); + for(var i=0; i 0) { + var zb = new Buffer(i); + zb.fill(0); + if(i == str.length) return zb; + answer = answer.toBuffer(); + return Buffer.concat([zb, answer], i+answer.length); + } else { + return answer.toBuffer(); + } + }, +}; + +// Base58Check Encoding +function sha256(data) { + return new Buffer(crypto.createHash('sha256').update(data).digest('binary'), 'binary'); +}; + +function doubleSHA256(data) { + return sha256(sha256(data)); +}; + +var base58Check = { + encode: function(buf) { + var checkedBuf = new Buffer(buf.length + 4); + var hash = doubleSHA256(buf); + buf.copy(checkedBuf); + hash.copy(checkedBuf, buf.length); + return base58.encode(checkedBuf); + }, + + decode: function(s) { + var buf = base58.decode(s); + if (buf.length < 4) { + throw new Error("invalid input: too short"); + } + + var data = buf.slice(0, -4); + var csum = buf.slice(-4); + + var hash = doubleSHA256(data); + var hash4 = hash.slice(0, 4); + + if (csum.toString() != hash4.toString()) { + throw new Error("checksum mismatch"); + } + + return data; + }, +}; + +// if you frequently do base58 encodings with data larger +// than 512 bytes, you can use this method to expand the +// size of the reusable buffer +exports.setBuffer = function(buf) { + globalBuffer = buf; +}; + +exports.base58 = base58; +exports.base58Check = base58Check; +exports.encode = base58.encode; +exports.decode = base58.decode; diff --git a/lib/Bignum.js b/lib/Bignum.js new file mode 100644 index 000000000..274b28de2 --- /dev/null +++ b/lib/Bignum.js @@ -0,0 +1,5 @@ +if (process.versions) { + module.exports = require('bignum'); + return; +} +module.exports = require('./browser/Bignum'); diff --git a/lib/Block.js b/lib/Block.js index 57c6d4869..63f84c5ef 100644 --- a/lib/Block.js +++ b/lib/Block.js @@ -3,7 +3,7 @@ var imports = require('soop').imports(); var util = imports.util || require('../util'); var Debug1 = imports.Debug1 || function() {}; var Script = imports.Script || require('./Script'); -var Bignum = imports.Bignum || require('bignum'); +var Bignum = imports.Bignum || require('./Bignum'); var Binary = imports.Binary || require('binary'); var Step = imports.Step || require('step'); var buffertools = imports.buffertools || require('buffertools'); diff --git a/lib/Curve.js b/lib/Curve.js index f2d140d4a..e5ec4fb1e 100644 --- a/lib/Curve.js +++ b/lib/Curve.js @@ -1,6 +1,6 @@ "use strict"; var imports = require('soop'); -var bignum = imports.bignum || require('bignum'); +var bignum = imports.bignum || require('./Bignum'); var Point = imports.Point || require('./Point'); var n = bignum.fromBuffer(new Buffer("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141", 'hex'), {size: 32}); diff --git a/lib/Electrum.js b/lib/Electrum.js index 02457798f..284c3d4d6 100644 --- a/lib/Electrum.js +++ b/lib/Electrum.js @@ -2,7 +2,7 @@ var Key = require('./Key'), Point = require('./Point'), twoSha256 = require('../util').twoSha256, buffertools = require('buffertools'), - bignum = require('bignum'); + bignum = require('./Bignum'); /** * Pre-BIP32 Electrum public key derivation (electrum <2.0) diff --git a/lib/ScriptInterpreter.js b/lib/ScriptInterpreter.js index 41bd90bee..51e0f7d7a 100644 --- a/lib/ScriptInterpreter.js +++ b/lib/ScriptInterpreter.js @@ -4,7 +4,7 @@ var log = imports.log || require('../util/log'); var util = imports.util || require('../util'); var Opcode = imports.Opcode || require('./Opcode'); var buffertools = imports.buffertools || require('buffertools'); -var bignum = imports.bignum || require('bignum'); +var bignum = imports.bignum || require('./Bignum'); var Util = imports.Util || require('../util'); var Script = require('./Script'); var Key = require('./Key'); diff --git a/lib/Transaction.js b/lib/Transaction.js index d79b62780..35931120b 100644 --- a/lib/Transaction.js +++ b/lib/Transaction.js @@ -5,7 +5,7 @@ var Address = imports.Address || require('./Address'); var Script = imports.Script || require('./Script'); var ScriptInterpreter = imports.ScriptInterpreter || require('./ScriptInterpreter'); var util = imports.util || require('../util'); -var bignum = imports.bignum || require('bignum'); +var bignum = imports.bignum || require('./Bignum'); var Put = imports.Put || require('bufferput'); var Parser = imports.Parser || require('../util/BinaryParser'); var Step = imports.Step || require('step'); diff --git a/lib/TransactionBuilder.js b/lib/TransactionBuilder.js index cf6f2edc1..bebc32218 100644 --- a/lib/TransactionBuilder.js +++ b/lib/TransactionBuilder.js @@ -54,7 +54,7 @@ var imports = require('soop').imports(); var Address = imports.Address || require('./Address'); var Script = imports.Script || require('./Script'); var util = imports.util || require('../util'); -var bignum = imports.bignum || require('bignum'); +var bignum = imports.bignum || require('./Bignum'); var buffertools = imports.buffertools || require('buffertools'); var networks = imports.networks || require('../networks'); var WalletKey = imports.WalletKey || require('./WalletKey'); diff --git a/lib/browser/Bignum.js b/lib/browser/Bignum.js new file mode 100644 index 000000000..9a947d96e --- /dev/null +++ b/lib/browser/Bignum.js @@ -0,0 +1,2121 @@ +/* bignumber.js v1.3.0 https://github.com/MikeMcl/bignumber.js/LICENCE */ + +/*jslint bitwise: true, eqeq: true, plusplus: true, sub: true, white: true, maxerr: 500 */ +/*global module */ + +/* + bignumber.js v1.3.0 + A JavaScript library for arbitrary-precision arithmetic. + https://github.com/MikeMcl/bignumber.js + Copyright (c) 2012 Michael Mclaughlin + MIT Expat Licence +*/ + +/*********************************** DEFAULTS ************************************/ + +/* + * The default values below must be integers within the stated ranges (inclusive). + * Most of these values can be changed during run-time using BigNumber.config(). + */ + +/* + * The limit on the value of DECIMAL_PLACES, TO_EXP_NEG, TO_EXP_POS, MIN_EXP, + * MAX_EXP, and the argument to toFixed, toPrecision and toExponential, beyond + * which an exception is thrown (if ERRORS is true). + */ +var MAX = 1E9, // 0 to 1e+9 + + // Limit of magnitude of exponent argument to toPower. + MAX_POWER = 1E6, // 1 to 1e+6 + + // 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 toFixed, toPrecision and toExponential, 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 = -MAX, // -1 to -MAX + + // The maximum exponent value, above which overflow to Infinity occurs. + // Number type: 308 (1.7976931348623157e+308) + MAX_EXP = MAX, // 1 to MAX + + // Whether BigNumber Errors are ever thrown. + // CHANGE parseInt to parseFloat if changing ERRORS to false. + ERRORS = true, // true or false + parse = parseInt, // parseInt or parseFloat + +/***********************************************************************************/ + + P = BigNumber.prototype, + DIGITS = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_', + outOfRange, + id = 0, + isValid = /^-?(\d+(\.\d*)?|\.\d+)(e[+-]?\d+)?$/i, + trim = String.prototype.trim || function () {return this.replace(/^\s+|\s+$/g, '')}, + ONE = BigNumber(1); + + +// CONSTRUCTOR + + +/* + * The 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 e, i, isNum, digits, valid, orig, + x = this; + + // Enable constructor usage without new. + if ( !(x instanceof BigNumber) ) { + return new BigNumber( n, b ) + } + + // Duplicate. + if ( n instanceof BigNumber ) { + id = 0; + + // e is undefined. + if ( b !== e ) { + n += '' + } else { + x['s'] = n['s']; + x['e'] = n['e']; + x['c'] = ( n = n['c'] ) ? n.slice() : n; + return; + } + } + + // Accept empty string as zero + if (n === '') n = 0; + + // If number, check if minus zero. + if ( typeof n != 'string' ) { + n = ( isNum = typeof n == 'number' || + Object.prototype.toString.call(n) == '[object Number]' ) && + n === 0 && 1 / n < 0 ? '-0' : n + ''; + } + + orig = n; + + if ( b === e && isValid.test(n) ) { + + // Determine sign. + x['s'] = n.charAt(0) == '-' ? ( n = n.slice(1), -1 ) : 1; + + // Either n is not a valid BigNumber or a base has been specified. + } else { + + // Enable exponential notation to be used with base 10 argument. + // Ensure return value is rounded to DECIMAL_PLACES as with other bases. + if ( b == 10 ) { + + return setMode( n, DECIMAL_PLACES, ROUNDING_MODE ); + } + + n = trim.call(n).replace( /^\+(?!-)/, '' ); + + x['s'] = n.charAt(0) == '-' ? ( n = n.replace( /^-(?!-)/, '' ), -1 ) : 1; + + if ( b != null ) { + + if ( ( b == (b | 0) || !ERRORS ) && + !( outOfRange = !( b >= 2 && b < 65 ) ) ) { + + digits = '[' + DIGITS.slice( 0, b = b | 0 ) + ']+'; + + // Before non-decimal number validity test and base conversion + // remove the `.` from e.g. '1.', and replace e.g. '.1' with '0.1'. + n = n.replace( /\.$/, '' ).replace( /^\./, '0.' ); + + // Any number in exponential form will fail due to the e+/-. + if ( valid = new RegExp( + '^' + digits + '(?:\\.' + digits + ')?$', b < 37 ? 'i' : '' ).test(n) ) { + + if ( isNum ) { + + if ( n.replace( /^0\.0*|\./, '' ).length > 15 ) { + + // 'new BigNumber() number type has more than 15 significant digits: {n}' + ifExceptionsThrow( orig, 0 ); + } + + // Prevent later check for length on converted number. + isNum = !isNum; + } + n = convert( n, 10, b, x['s'] ); + + } else if ( n != 'Infinity' && n != 'NaN' ) { + + // 'new BigNumber() not a base {b} number: {n}' + ifExceptionsThrow( orig, 1, b ); + n = 'NaN'; + } + } else { + + // 'new BigNumber() base not an integer: {b}' + // 'new BigNumber() base out of range: {b}' + ifExceptionsThrow( b, 2 ); + + // Ignore base. + valid = isValid.test(n); + } + } else { + valid = isValid.test(n); + } + + if ( !valid ) { + + // Infinity/NaN + x['c'] = x['e'] = null; + + // NaN + if ( n != 'Infinity' ) { + + // No exception on NaN. + if ( n != 'NaN' ) { + + // 'new BigNumber() not a number: {n}' + ifExceptionsThrow( orig, 3 ); + } + x['s'] = null; + } + id = 0; + + return; + } + } + + // Decimal point? + if ( ( e = n.indexOf('.') ) > -1 ) { + n = n.replace( '.', '' ); + } + + // Exponential form? + if ( ( i = n.search( /e/i ) ) > 0 ) { + + // Determine exponent. + if ( e < 0 ) { + e = i; + } + e += +n.slice( i + 1 ); + n = n.substring( 0, i ); + + } else if ( e < 0 ) { + + // Integer. + e = n.length; + } + + // Determine leading zeros. + for ( i = 0; n.charAt(i) == '0'; i++ ) { + } + + b = n.length; + + // Disallow numbers with over 15 significant digits if number type. + if ( isNum && b > 15 && n.slice(i).length > 15 ) { + + // 'new BigNumber() number type has more than 15 significant digits: {n}' + ifExceptionsThrow( orig, 0 ); + } + id = 0; + + // Overflow? + if ( ( e -= i + 1 ) > MAX_EXP ) { + + // Infinity. + x['c'] = x['e'] = null; + + // Zero or underflow? + } else if ( i == b || e < MIN_EXP ) { + + // Zero. + x['c'] = [ x['e'] = 0 ]; + } else { + + // Determine trailing zeros. + for ( ; n.charAt(--b) == '0'; ) { + } + + x['e'] = e; + x['c'] = []; + + // Convert string to array of digits (without leading and trailing zeros). + for ( e = 0; i <= b; x['c'][e++] = +n.charAt(i++) ) { + } + } +} + + +// CONSTRUCTOR PROPERTIES/METHODS + + +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; + +/* + * Create an instance from a Buffer + */ +BigNumber['fromBuffer'] = function (buf, opts) { + + if (!opts) opts = {}; + + var endian = { 1 : 'big', '-1' : 'little' }[opts.endian] + || opts.endian || 'big' + ; + + var size = opts.size === 'auto' ? Math.ceil(buf.length) : (opts.size || 1); + + if (buf.length % size !== 0) { + throw new RangeError('Buffer length (' + buf.length + ')' + + ' must be a multiple of size (' + size + ')' + ); + } + + var hex = []; + for (var i = 0; i < buf.length; i += size) { + var chunk = []; + for (var j = 0; j < size; j++) { + chunk.push(buf[ + i + (endian === 'big' ? j : (size - j - 1)) + ]); + } + + hex.push(chunk + .map(function (c) { + return (c < 16 ? '0' : '') + c.toString(16); + }) + .join('') + ); + } + + return BigNumber(hex.join(''), 16); + +}; + +/* + * 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 [, ROUNDING_MODE [, EXPONENTIAL_AT [, RANGE [, ERRORS ]]]]] + * + * 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], + c = 'config', + inRange = function ( n, lo, hi ) { + return !( ( outOfRange = n < lo || n > hi ) || + parse(n) != n && n !== 0 ); + }, + has = o && 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. + if ( has( p = 'DECIMAL_PLACES' ) ) { + + if ( inRange( v, 0, MAX ) ) { + DECIMAL_PLACES = v | 0; + } else { + + // 'config() DECIMAL_PLACES not an integer: {v}' + // 'config() DECIMAL_PLACES out of range: {v}' + ifExceptionsThrow( v, p, c ); + } + } + r[p] = DECIMAL_PLACES; + + // [ROUNDING_MODE] {number} Integer, 0 to 8 inclusive. + if ( has( p = 'ROUNDING_MODE' ) ) { + + if ( inRange( v, 0, 8 ) ) { + ROUNDING_MODE = v | 0; + } else { + + // 'config() ROUNDING_MODE not an integer: {v}' + // 'config() ROUNDING_MODE out of range: {v}' + ifExceptionsThrow( v, p, c ); + } + } + r[p] = ROUNDING_MODE; + + /* + * [EXPONENTIAL_AT] {number|number[]} Integer, -MAX to MAX inclusive or + * [ integer -MAX to 0 inclusive, 0 to MAX inclusive ]. + */ + if ( has( p = 'EXPONENTIAL_AT' ) ) { + + if ( inRange( v, -MAX, MAX ) ) { + TO_EXP_NEG = -( TO_EXP_POS = ~~( v < 0 ? -v : +v ) ); + } else if ( !outOfRange && v && inRange( v[0], -MAX, 0 ) && + inRange( v[1], 0, MAX ) ) { + TO_EXP_NEG = ~~v[0]; + TO_EXP_POS = ~~v[1]; + } else { + + // 'config() EXPONENTIAL_AT not an integer or not [integer, integer]: {v}' + // 'config() EXPONENTIAL_AT out of range or not [negative, positive: {v}' + ifExceptionsThrow( v, p, c, 1 ); + } + } + 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 ]. + */ + if ( has( p = 'RANGE' ) ) { + + if ( inRange( v, -MAX, MAX ) && ~~v ) { + MIN_EXP = -( MAX_EXP = ~~( v < 0 ? -v : +v ) ); + } else if ( !outOfRange && v && inRange( v[0], -MAX, -1 ) && + inRange( v[1], 1, MAX ) ) { + MIN_EXP = ~~v[0], MAX_EXP = ~~v[1]; + } else { + + // 'config() RANGE not a non-zero integer or not [integer, integer]: {v}' + // 'config() RANGE out of range or not [negative, positive: {v}' + ifExceptionsThrow( v, p, c, 1, 1 ); + } + } + r[p] = [ MIN_EXP, MAX_EXP ]; + + // [ERRORS] {boolean|number} true, false, 1 or 0. + if ( has( p = 'ERRORS' ) ) { + + if ( v === !!v || v === 1 || v === 0 ) { + parse = ( outOfRange = id = 0, ERRORS = !!v ) + ? parseInt + : parseFloat; + } else { + + // 'config() ERRORS not a boolean or binary digit: {v}' + ifExceptionsThrow( v, p, c, 0, 0, 1 ); + } + } + r[p] = ERRORS; + + return r; +}; + + +// PRIVATE FUNCTIONS + + +// Assemble error messages. Throw BigNumber Errors. +function ifExceptionsThrow( arg, i, j, isArray, isRange, isErrors) { + + if ( ERRORS ) { + var error, + method = ['new BigNumber', 'cmp', 'div', 'eq', 'gt', 'gte', 'lt', + 'lte', 'minus', 'mod', 'plus', 'times', 'toFr' + ][ id ? id < 0 ? -id : id : 1 / id < 0 ? 1 : 0 ] + '()', + message = outOfRange ? ' out of range' : ' not a' + + ( isRange ? ' non-zero' : 'n' ) + ' integer'; + + message = ( [ + method + ' number type has more than 15 significant digits', + method + ' not a base ' + j + ' number', + method + ' base' + message, + method + ' not a number' ][i] || + j + '() ' + i + ( isErrors + ? ' not a boolean or binary digit' + : message + ( isArray + ? ' or not [' + ( outOfRange + ? ' negative, positive' + : ' integer, integer' ) + ' ]' + : '' ) ) ) + ': ' + arg; + + outOfRange = id = 0; + error = new Error(message); + error['name'] = 'BigNumber Error'; + + throw error; + } +} + + +/* + * Convert a numeric string of baseIn to a numeric string of baseOut. + */ +function convert( nStr, baseOut, baseIn, sign ) { + var e, dvs, dvd, nArr, fracArr, fracBN; + + // Convert string of base bIn to an array of numbers of baseOut. + // Eg. strToArr('255', 10) where baseOut is 16, returns [15, 15]. + // Eg. strToArr('ff', 16) where baseOut is 10, returns [2, 5, 5]. + function strToArr( str, bIn ) { + var j, + i = 0, + strL = str.length, + arrL, + arr = [0]; + + for ( bIn = bIn || baseIn; i < strL; i++ ) { + + for ( arrL = arr.length, j = 0; j < arrL; arr[j] *= bIn, j++ ) { + } + + for ( arr[0] += DIGITS.indexOf( str.charAt(i) ), j = 0; + 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(); + } + + // Convert array to string. + // E.g. arrToStr( [9, 10, 11] ) becomes '9ab' (in bases above 11). + function arrToStr( arr ) { + var i = 0, + arrL = arr.length, + str = ''; + + for ( ; i < arrL; str += DIGITS.charAt( arr[i++] ) ) { + } + + return str; + } + + if ( baseIn < 37 ) { + nStr = nStr.toLowerCase(); + } + + /* + * If non-integer convert integer part and fraction part separately. + * Convert the fraction part as if it is an integer than use division to + * reduce it down again to a value less than one. + */ + if ( ( e = nStr.indexOf( '.' ) ) > -1 ) { + + /* + * Calculate the power to which to raise the base to get the number + * to divide the fraction part by after it has been converted as an + * integer to the required base. + */ + e = nStr.length - e - 1; + + // Use toFixed to avoid possible exponential notation. + dvs = strToArr( new BigNumber(baseIn)['pow'](e)['toF'](), 10 ); + + nArr = nStr.split('.'); + + // Convert the base of the fraction part (as integer). + dvd = strToArr( nArr[1] ); + + // Convert the base of the integer part. + nArr = strToArr( nArr[0] ); + + // Result will be a BigNumber with a value less than 1. + fracBN = divide( dvd, dvs, dvd.length - dvs.length, sign, baseOut, + // Is least significant digit of integer part an odd number? + nArr[nArr.length - 1] & 1 ); + + fracArr = fracBN['c']; + + // e can be <= 0 ( if e == 0, fracArr is [0] or [1] ). + if ( e = fracBN['e'] ) { + + // Append zeros according to the exponent of the result. + for ( ; ++e; fracArr.unshift(0) ) { + } + + // Append the fraction part to the converted integer part. + nStr = arrToStr(nArr) + '.' + arrToStr(fracArr); + + // fracArr is [1]. + // Fraction digits rounded up, so increment last digit of integer part. + } else if ( fracArr[0] ) { + + if ( nArr[ e = nArr.length - 1 ] < baseOut - 1 ) { + ++nArr[e]; + nStr = arrToStr(nArr); + } else { + nStr = new BigNumber( arrToStr(nArr), + baseOut )['plus'](ONE)['toS'](baseOut); + } + + // fracArr is [0]. No fraction digits. + } else { + nStr = arrToStr(nArr); + } + } else { + + // Simple integer. Convert base. + nStr = arrToStr( strToArr(nStr) ); + } + + return nStr; +} + + +// Perform division in the specified base. Called by div and convert. +function divide( dvd, dvs, exp, s, base, isOdd ) { + var dvsL, dvsT, next, cmp, remI, + dvsZ = dvs.slice(), + dvdI = dvsL = dvs.length, + dvdL = dvd.length, + rem = dvd.slice( 0, dvsL ), + remL = rem.length, + quo = new BigNumber(ONE), + qc = quo['c'] = [], + qi = 0, + dig = DECIMAL_PLACES + ( quo['e'] = exp ) + 1; + + quo['s'] = s; + s = dig < 0 ? 0 : dig; + + // Add zeros to make remainder as long as divisor. + for ( ; remL++ < dvsL; rem.push(0) ) { + } + + // Create version of divisor with leading zero. + dvsZ.unshift(0); + + do { + + // 'next' is how many times the divisor goes into the current remainder. + for ( next = 0; next < base; next++ ) { + + // Compare divisor and remainder. + if ( dvsL != ( remL = rem.length ) ) { + cmp = dvsL > remL ? 1 : -1; + } else { + for ( remI = -1, cmp = 0; ++remI < dvsL; ) { + + if ( dvs[remI] != rem[remI] ) { + cmp = dvs[remI] > rem[remI] ? 1 : -1; + break; + } + } + } + + // Subtract divisor from remainder (if divisor < remainder). + if ( cmp < 0 ) { + + // Remainder cannot be more than one digit longer than divisor. + // Equalise lengths using divisor with extra leading zero? + for ( dvsT = remL == dvsL ? dvs : dvsZ; remL; ) { + + if ( rem[--remL] < dvsT[remL] ) { + + for ( remI = remL; + remI && !rem[--remI]; + rem[remI] = base - 1 ) { + } + --rem[remI]; + rem[remL] += base; + } + rem[remL] -= dvsT[remL]; + } + for ( ; !rem[0]; rem.shift() ) { + } + } else { + break; + } + } + + // Add the 'next' digit to the result array. + qc[qi++] = cmp ? next : ++next; + + // Update the remainder. + rem[0] && cmp + ? ( rem[remL] = dvd[dvdI] || 0 ) + : ( rem = [ dvd[dvdI] ] ); + + } while ( ( dvdI++ < dvdL || rem[0] != null ) && s-- ); + + // Leading zero? Do not remove if result is simply zero (qi == 1). + if ( !qc[0] && qi != 1 ) { + + // There can't be more than one zero. + --quo['e']; + qc.shift(); + } + + // Round? + if ( qi > dig ) { + rnd( quo, DECIMAL_PLACES, base, isOdd, rem[0] != null ); + } + + // Overflow? + if ( quo['e'] > MAX_EXP ) { + + // Infinity. + quo['c'] = quo['e'] = null; + + // Underflow? + } else if ( quo['e'] < MIN_EXP ) { + + // Zero. + quo['c'] = [quo['e'] = 0]; + } + + return quo; +} + + +/* + * Return a string representing the value of BigNumber n in normal or + * exponential notation rounded to the specified decimal places or + * significant digits. + * Called by toString, toExponential (exp 1), toFixed, and toPrecision (exp 2). + * d is the index (with the value in normal notation) of the digit that may be + * rounded up. + */ +function format( n, d, exp ) { + + // Initially, i is the number of decimal places required. + var i = d - (n = new BigNumber(n))['e'], + c = n['c']; + + // +-Infinity or NaN? + if ( !c ) { + return n['toS'](); + } + + // Round? + if ( c.length > ++d ) { + rnd( n, i, 10 ); + } + + // Recalculate d if toFixed as n['e'] may have changed if value rounded up. + i = c[0] == 0 ? i + 1 : exp ? d : n['e'] + i + 1; + + // Append zeros? + for ( ; c.length < i; c.push(0) ) { + } + i = n['e']; + + /* + * 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 normal notation. + */ + return exp == 1 || exp == 2 && ( --d < i || i <= TO_EXP_NEG ) + + // Exponential notation. + ? ( n['s'] < 0 && c[0] ? '-' : '' ) + ( c.length > 1 + ? ( c.splice( 1, 0, '.' ), c.join('') ) + : c[0] ) + ( i < 0 ? 'e' : 'e+' ) + i + + // Normal notation. + : n['toS'](); +} + + +// Round if necessary. +// Called by divide, format, setMode and sqrt. +function rnd( x, dp, base, isOdd, r ) { + var xc = x['c'], + isNeg = x['s'] < 0, + half = base / 2, + i = x['e'] + dp + 1, + + // 'next' is the digit after the digit that may be rounded up. + next = xc[i], + + /* + * 'more' is whether there are digits after 'next'. + * E.g. + * 0.005 (e = -3) to be rounded to 0 decimal places (dp = 0) gives i = -2 + * The 'next' digit is zero, and there ARE 'more' digits after it. + * 0.5 (e = -1) dp = 0 gives i = 0 + * The 'next' digit is 5 and there are no 'more' digits after it. + */ + more = r || i < 0 || xc[i + 1] != null; + + r = ROUNDING_MODE < 4 + ? ( next != null || more ) && + ( ROUNDING_MODE == 0 || + ROUNDING_MODE == 2 && !isNeg || + ROUNDING_MODE == 3 && isNeg ) + : next > half || next == half && + ( ROUNDING_MODE == 4 || more || + + /* + * isOdd is used in base conversion and refers to the least significant + * digit of the integer part of the value to be converted. The fraction + * part is rounded by this method separately from the integer part. + */ + ROUNDING_MODE == 6 && ( xc[i - 1] & 1 || !dp && isOdd ) || + ROUNDING_MODE == 7 && !isNeg || + ROUNDING_MODE == 8 && isNeg ); + + if ( i < 1 || !xc[0] ) { + xc.length = 0; + xc.push(0); + + if ( r ) { + + // 1, 0.1, 0.01, 0.001, 0.0001 etc. + xc[0] = 1; + x['e'] = -dp; + } else { + + // Zero. + x['e'] = 0; + } + + return x; + } + + // Remove any digits after the required decimal places. + xc.length = i--; + + // Round up? + if ( r ) { + + // Rounding up may mean the previous digit has to be rounded up and so on. + for ( --base; ++xc[i] > base; ) { + xc[i] = 0; + + if ( !i-- ) { + ++x['e']; + xc.unshift(1); + } + } + } + + // Remove trailing zeros. + for ( i = xc.length; !xc[--i]; xc.pop() ) { + } + + return x; +} + + +// Round after setting the appropriate rounding mode. +// Handles ceil, floor and round. +function setMode( x, dp, rm ) { + var r = ROUNDING_MODE; + + ROUNDING_MODE = rm; + x = new BigNumber(x); + x['c'] && rnd( x, dp, 10 ); + ROUNDING_MODE = r; + + return x; +} + + +// PROTOTYPE/INSTANCE METHODS + + +/* + * Return a new BigNumber whose value is the absolute value of this BigNumber. + */ +P['abs'] = P['absoluteValue'] = function () { + var x = new BigNumber(this); + + if ( x['s'] < 0 ) { + x['s'] = 1; + } + + return x; +}; + +/* + * Return the bit length of the number. + */ +P['bitLength'] = function () { + return this.toString(2).length; +}; + + +/* + * 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 setMode( this, 0, 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 ) { + var a, + x = this, + xc = x['c'], + yc = ( id = -id, y = new BigNumber( y, b ) )['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; + } + + // Either Infinity? + if ( a = i < 0, b = k == l, !xc || !yc ) { + return b ? 0 : !xc ^ a ? 1 : -1; + } + + // Compare exponents. + if ( !b ) { + return k > l ^ a ? 1 : -1; + } + + // Compare digit by digit. + for ( i = -1, + j = ( k = xc.length ) < ( l = yc.length ) ? k : l; + ++i < j; ) { + + if ( xc[i] != yc[i] ) { + return xc[i] > yc[i] ^ a ? 1 : -1; + } + } + // Compare lengths. + return k == l ? 0 : k > l ^ a ? 1 : -1; +}; + + +/* + * 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 ) { + var xc = this['c'], + xe = this['e'], + xs = this['s'], + yc = ( id = 2, y = new BigNumber( y, b ) )['c'], + ye = y['e'], + ys = y['s'], + s = xs == ys ? 1 : -1; + + // Either NaN/Infinity/0? + return !xe && ( !xc || !xc[0] ) || !ye && ( !yc || !yc[0] ) + + // Either NaN? + ? new BigNumber( !xs || !ys || + + // Both 0 or both Infinity? + ( xc ? yc && xc[0] == yc[0] : !yc ) + + // Return NaN. + ? NaN + + // x is 0 or y is Infinity? + : xc && xc[0] == 0 || !yc + + // Return +-0. + ? s * 0 + + // y is 0. Return +-Infinity. + : s / 0 ) + + : divide( xc, yc, xe - ye, s, 10 ); +}; + + +/* + * Return true if the value of this BigNumber is equal to the value of + * BigNumber(n, b), otherwise returns false. + */ +P['equals'] = P['eq'] = function ( n, b ) { + id = 3; + return this['cmp']( n, 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 setMode( this, 0, 3 ); +}; + + +/* + * Return true if the value of this BigNumber is greater than the value of + * BigNumber(n, b), otherwise returns false. + */ +P['greaterThan'] = P['gt'] = function ( n, b ) { + id = 4; + return this['cmp']( n, b ) > 0; +}; + + +/* + * Return true if the value of this BigNumber is greater than or equal to + * the value of BigNumber(n, b), otherwise returns false. + */ +P['greaterThanOrEqualTo'] = P['gte'] = function ( n, b ) { + id = 5; + return ( b = this['cmp']( n, b ) ) == 1 || b === 0; +}; + + +/* + * Return true if the value of this BigNumber is a finite number, otherwise + * returns false. + */ +P['isFinite'] = P['isF'] = function () { + return !!this['c']; +}; + + +/* + * 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'] = P['isZ'] = function () { + return !!this['c'] && this['c'][0] == 0; +}; + + +/* + * Return true if the value of this BigNumber is less than the value of + * BigNumber(n, b), otherwise returns false. + */ +P['lessThan'] = P['lt'] = function ( n, b ) { + id = 6; + return this['cmp']( n, b ) < 0; +}; + + +/* + * Return true if the value of this BigNumber is less than or equal to the + * value of BigNumber(n, b), otherwise returns false. + */ +P['lessThanOrEqualTo'] = P['lte'] = P['le'] = function ( n, b ) { + id = 7; + return ( b = this['cmp']( n, 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 d, i, j, xLTy, + x = this, + a = x['s']; + + b = ( id = 8, y = new BigNumber( y, b ) )['s']; + + // Either NaN? + if ( !a || !b ) { + return new BigNumber(NaN); + } + + // Signs differ? + if ( a != b ) { + return y['s'] = -b, x['plus'](y); + } + + var xc = x['c'], + xe = x['e'], + yc = y['c'], + ye = y['e']; + + 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] ) { + + // y is non-zero? + return yc[0] + ? ( y['s'] = -b, y ) + + // x is non-zero? + : new BigNumber( xc[0] + ? x + + // Both are zero. + // IEEE 754 (2008) 6.3: n - n = -0 when rounding to -Infinity + : ROUNDING_MODE == 3 ? -0 : 0 ); + } + } + + // Determine which is the bigger number. + // Prepend zeros to equalise exponents. + if ( xc = xc.slice(), a = xe - ye ) { + d = ( xLTy = a < 0 ) ? ( a = -a, xc ) : ( ye = xe, yc ); + + for ( d.reverse(), b = a; b--; d.push(0) ) { + } + d.reverse(); + } else { + + // Exponents equal. Check digit by digit. + j = ( ( xLTy = xc.length < yc.length ) ? xc : yc ).length; + + 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 ) { + d = xc, xc = yc, yc = d; + y['s'] = -y['s']; + } + + /* + * Append zeros to xc if shorter. No need to add zeros to yc if shorter + * as subtraction only needs to start at yc.length. + */ + if ( ( b = -( ( j = xc.length ) - yc.length ) ) > 0 ) { + + for ( ; b--; xc[j++] = 0 ) { + } + } + + // Subtract yc from xc. + for ( b = yc.length; b > a; ){ + + if ( xc[--b] < yc[b] ) { + + for ( i = b; i && !xc[--i]; xc[i] = 9 ) { + } + --xc[i]; + xc[b] += 10; + } + xc[b] -= yc[b]; + } + + // Remove trailing zeros. + for ( ; xc[--j] == 0; xc.pop() ) { + } + + // Remove leading zeros and adjust exponent accordingly. + for ( ; xc[0] == 0; xc.shift(), --ye ) { + } + + /* + * No need to check for Infinity as +x - +y != Infinity && -x - -y != Infinity + * when neither x or y are Infinity. + */ + + // Underflow? + if ( ye < MIN_EXP || !xc[0] ) { + + /* + * Following IEEE 754 (2008) 6.3, + * n - n = +0 but n - n = -0 when rounding towards -Infinity. + */ + if ( !xc[0] ) { + y['s'] = ROUNDING_MODE == 3 ? -1 : 1; + } + + // Result is zero. + xc = [ye = 0]; + } + + return y['c'] = xc, y['e'] = ye, y; +}; + + +/* + * n % 0 = N + * n % N = N + * 0 % n = 0 + * -0 % n = -0 + * 0 % 0 = N + * 0 % N = N + * N % n = N + * N % 0 = N + * N % N = N + * + * Return a new BigNumber whose value is the value of this BigNumber modulo + * the value of BigNumber(y, b). + */ +P['modulo'] = P['mod'] = function ( y, b ) { + var x = this, + xc = x['c'], + yc = ( id = 9, y = new BigNumber( y, b ) )['c'], + i = x['s'], + j = y['s']; + + // Is x or y NaN, or y zero? + b = !i || !j || yc && !yc[0]; + + if ( b || xc && !xc[0] ) { + return new BigNumber( b ? NaN : x ); + } + + x['s'] = y['s'] = 1; + b = y['cmp'](x) == 1; + x['s'] = i, y['s'] = j; + + return b + ? new BigNumber(x) + : ( i = DECIMAL_PLACES, j = ROUNDING_MODE, + DECIMAL_PLACES = 0, ROUNDING_MODE = 1, + x = x['div'](y), + DECIMAL_PLACES = i, ROUNDING_MODE = j, + this['minus']( x['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); + + return x['s'] = -x['s'] || null, 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 d, + x = this, + a = x['s']; + + b = ( id = 10, y = new BigNumber( y, b ) )['s']; + + // Either NaN? + if ( !a || !b ) { + return new BigNumber(NaN); + } + + // Signs differ? + if ( a != b ) { + return y['s'] = -b, x['minus'](y); + } + + var xe = x['e'], + xc = x['c'], + ye = y['e'], + yc = y['c']; + + if ( !xe || !ye ) { + + // Either Infinity? + if ( !xc || !yc ) { + + // Return +-Infinity. + return new BigNumber( a / 0 ); + } + + // Either zero? + if ( !xc[0] || !yc[0] ) { + + // y is non-zero? + return yc[0] + ? y + + // x is non-zero? + : new BigNumber( xc[0] + ? x + + // Both are zero. Return zero. + : a * 0 ); + } + } + + // Prepend zeros to equalise exponents. + // Note: Faster to use reverse then do unshifts. + if ( xc = xc.slice(), a = xe - ye ) { + d = a > 0 ? ( ye = xe, yc ) : ( a = -a, xc ); + + for ( d.reverse(); a--; d.push(0) ) { + } + d.reverse(); + } + + // Point xc to the longer array. + if ( xc.length - yc.length < 0 ) { + d = yc, yc = xc, xc = d; + } + + /* + * Only start adding at yc.length - 1 as the + * further digits of xc can be left as they are. + */ + for ( a = yc.length, b = 0; a; + b = ( xc[--a] = xc[a] + yc[a] + b ) / 10 ^ 0, xc[a] %= 10 ) { + } + + // No need to check for zero, as +x + +y != 0 && -x + -y != 0 + + if ( b ) { + xc.unshift(b); + + // Overflow? (MAX_EXP + 1 possible) + if ( ++ye > MAX_EXP ) { + + // Infinity. + xc = ye = null; + } + } + + // Remove trailing zeros. + for ( a = xc.length; xc[--a] == 0; xc.pop() ) { + } + + return y['c'] = xc, y['e'] = ye, y; +}; + + +/* + * Return a BigNumber whose value is the value of this BigNumber raised to + * the power e. If e is negative round according to DECIMAL_PLACES and + * ROUNDING_MODE. + * + * e {number} Integer, -MAX_POWER to MAX_POWER inclusive. + */ +P['toPower'] = P['pow'] = function ( e ) { + + // e to integer, avoiding NaN or Infinity becoming 0. + var i = e * 0 == 0 ? e | 0 : e, + x = new BigNumber(this), + y = new BigNumber(ONE); + + // Use Math.pow? + // Pass +-Infinity for out of range exponents. + if ( ( ( ( outOfRange = e < -MAX_POWER || e > MAX_POWER ) && + (i = e * 1 / 0) ) || + + /* + * Any exponent that fails the parse becomes NaN. + * + * Include 'e !== 0' because on Opera -0 == parseFloat(-0) is false, + * despite -0 === parseFloat(-0) && -0 == parseFloat('-0') is true. + */ + parse(e) != e && e !== 0 && !(i = NaN) ) && + + // 'pow() exponent not an integer: {e}' + // 'pow() exponent out of range: {e}' + !ifExceptionsThrow( e, 'exponent', 'pow' ) || + + // Pass zero to Math.pow, as any value to the power zero is 1. + !i ) { + + // i is +-Infinity, NaN or 0. + return new BigNumber( Math.pow( x['toS'](), i ) ); + } + + for ( i = i < 0 ? -i : i; ; ) { + + if ( i & 1 ) { + y = y['times'](x); + } + i >>= 1; + + if ( !i ) { + break; + } + x = x['times'](x); + } + + return e < 0 ? ONE['div'](y) : y; +}; + + +/* + * Return a BigNumber whose value is the value of this BigNumber raised to + * the power m modulo n. + * + * m {BigNumber} the value to take the power of + * n {BigNumber} the value to modulo by + */ +P['powm'] = function ( m, n ) { + return this.pow(m).mod(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} Integer, 0 to MAX inclusive. + * [rm] {number} Integer, 0 to 8 inclusive. + */ +P['round'] = function ( dp, rm ) { + + dp = dp == null || ( ( ( outOfRange = dp < 0 || dp > MAX ) || + parse(dp) != dp ) && + + // 'round() decimal places out of range: {dp}' + // 'round() decimal places not an integer: {dp}' + !ifExceptionsThrow( dp, 'decimal places', 'round' ) ) + ? 0 + : dp | 0; + + rm = rm == null || ( ( ( outOfRange = rm < 0 || rm > 8 ) || + + // Include '&& rm !== 0' because with Opera -0 == parseFloat(-0) is false. + parse(rm) != rm && rm !== 0 ) && + + // 'round() mode not an integer: {rm}' + // 'round() mode out of range: {rm}' + !ifExceptionsThrow( rm, 'mode', 'round' ) ) + ? ROUNDING_MODE + : rm | 0; + + return setMode( this, dp, rm ); +}; + + +/* + * 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 n, r, re, t, + x = this, + c = x['c'], + s = x['s'], + e = x['e'], + dp = DECIMAL_PLACES, + rm = ROUNDING_MODE, + 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['toS']() ); + ROUNDING_MODE = 1; + + /* + 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 = c.join(''); + + if ( !( n.length + e & 1 ) ) { + n += '0'; + } + r = new BigNumber( Math.sqrt(n) + '' ); + + // r may still not be finite. + if ( !r['c'] ) { + r['c'] = [1]; + } + r['e'] = ( ( ( e + 1 ) / 2 ) | 0 ) - ( e < 0 || e & 1 ); + } else { + r = new BigNumber( n = s.toString() ); + } + re = r['e']; + s = re + ( DECIMAL_PLACES += 4 ); + + if ( s < 3 ) { + s = 0; + } + e = s; + + // Newton-Raphson iteration. + for ( ; ; ) { + t = r; + r = half['times']( t['plus']( x['div'](t) ) ); + + if ( t['c'].slice( 0, s ).join('') === r['c'].slice( 0, s ).join('') ) { + c = r['c']; + + /* + The exponent of r may here be one less than the final result + exponent (re), e.g 0.0009999 (e-4) --> 0.001 (e-3), so adjust + s so the rounding digits are indexed correctly. + */ + s = s - ( n && r['e'] < re ); + + /* + 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 ( c[s] == 9 && c[s - 1] == 9 && c[s - 2] == 9 && + ( c[s - 3] == 9 || n && c[s - 3] == 4 ) ) { + + /* + If 9999 on first run through, check to see if rounding up + gives the exact result as the nines may infinitely repeat. + */ + if ( n && c[s - 3] == 9 ) { + t = r['round']( dp, 0 ); + + if ( t['times'](t)['eq'](x) ) { + ROUNDING_MODE = rm; + DECIMAL_PLACES = dp; + + return t; + } + } + DECIMAL_PLACES += 4; + s += 4; + n = ''; + } else { + + /* + If the rounding digits are null, 0000 or 5000, check for an + exact result. If not, then there are further digits so + increment the 1st rounding digit to ensure correct rounding. + */ + if ( !c[e] && !c[e - 1] && !c[e - 2] && + ( !c[e - 3] || c[e - 3] == 5 ) ) { + + // Truncate to the first rounding digit. + if ( c.length > e - 2 ) { + c.length = e - 2; + } + + if ( !r['times'](r)['eq'](x) ) { + + while ( c.length < e - 3 ) { + c.push(0); + } + c[e - 3]++; + } + } + ROUNDING_MODE = rm; + rnd( r, DECIMAL_PLACES = dp, 10 ); + + return r; + } + } + } +}; + + +/* + * 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, + x = this, + xc = x['c'], + yc = ( id = 11, y = new BigNumber( y, b ) )['c'], + i = x['e'], + j = y['e'], + a = x['s']; + + y['s'] = a == ( b = y['s'] ) ? 1 : -1; + + // Either NaN/Infinity/0? + if ( !i && ( !xc || !xc[0] ) || !j && ( !yc || !yc[0] ) ) { + + // Either NaN? + return new BigNumber( !a || !b || + + // x is 0 and y is Infinity or y is 0 and x is Infinity? + xc && !xc[0] && !yc || yc && !yc[0] && !xc + + // Return NaN. + ? NaN + + // Either Infinity? + : !xc || !yc + + // Return +-Infinity. + ? y['s'] / 0 + + // x or y is 0. Return +-0. + : y['s'] * 0 ); + } + y['e'] = i + j; + + if ( ( a = xc.length ) < ( b = yc.length ) ) { + c = xc, xc = yc, yc = c, j = a, a = b, b = j; + } + + for ( j = a + b, c = []; j--; c.push(0) ) { + } + + // Multiply! + for ( i = b - 1; i > -1; i-- ) { + + for ( b = 0, j = a + i; + j > i; + b = c[j] + yc[i] * xc[j - i - 1] + b, + c[j--] = b % 10 | 0, + b = b / 10 | 0 ) { + } + + if ( b ) { + c[j] = ( c[j] + b ) % 10; + } + } + + b && ++y['e']; + + // Remove any leading zero. + !c[0] && c.shift(); + + // Remove trailing zeros. + for ( j = c.length; !c[--j]; c.pop() ) { + } + + // No zero check needed as only x * 0 == 0 etc. + + // Overflow? + y['c'] = y['e'] > MAX_EXP + + // Infinity. + ? ( y['e'] = null ) + + // Underflow? + : y['e'] < MIN_EXP + + // Zero. + ? [ y['e'] = 0 ] + + // Neither. + : c; + + return y; +}; + +/* + * Return a buffer containing the + */ +P['toBuffer'] = function ( opts ) { + + if (typeof opts === 'string') { + if (opts !== 'mpint') return 'Unsupported Buffer representation'; + + var abs = this.abs(); + var buf = abs.toBuffer({ size : 1, endian : 'big' }); + var len = buf.length === 1 && buf[0] === 0 ? 0 : buf.length; + if (buf[0] & 0x80) len ++; + + var ret = new Buffer(4 + len); + if (len > 0) buf.copy(ret, 4 + (buf[0] & 0x80 ? 1 : 0)); + if (buf[0] & 0x80) ret[4] = 0; + + ret[0] = len & (0xff << 24); + ret[1] = len & (0xff << 16); + ret[2] = len & (0xff << 8); + ret[3] = len & (0xff << 0); + + // two's compliment for negative integers: + var isNeg = this.lt(0); + if (isNeg) { + for (var i = 4; i < ret.length; i++) { + ret[i] = 0xff - ret[i]; + } + } + ret[4] = (ret[4] & 0x7f) | (isNeg ? 0x80 : 0); + if (isNeg) ret[ret.length - 1] ++; + + return ret; + } + + if (!opts) opts = {}; + + var endian = { 1 : 'big', '-1' : 'little' }[opts.endian] + || opts.endian || 'big' + ; + + var hex = this.toString(16); + if (hex.charAt(0) === '-') throw new Error( + 'converting negative numbers to Buffers not supported yet' + ); + + var size = opts.size === 'auto' ? Math.ceil(hex.length / 2) : (opts.size || 1); + + var len = Math.ceil(hex.length / (2 * size)) * size; + var buf = new Buffer(len); + + // zero-pad the hex string so the chunks are all `size` long + while (hex.length < 2 * len) hex = '0' + hex; + + var hx = hex + .split(new RegExp('(.{' + (2 * size) + '})')) + .filter(function (s) { return s.length > 0 }) + ; + + hx.forEach(function (chunk, i) { + for (var j = 0; j < size; j++) { + var ix = i * size + (endian === 'big' ? j : size - j - 1); + buf[ix] = parseInt(chunk.slice(j*2,j*2+2), 16); + } + }); + + return buf; +}; + +/* + * Return a string representing the value of this BigNumber in exponential + * notation to dp fixed decimal places and rounded using ROUNDING_MODE if + * necessary. + * + * [dp] {number} Integer, 0 to MAX inclusive. + */ +P['toExponential'] = P['toE'] = function ( dp ) { + + return format( this, + ( dp == null || ( ( outOfRange = dp < 0 || dp > MAX ) || + + /* + * Include '&& dp !== 0' because with Opera -0 == parseFloat(-0) is + * false, despite -0 == parseFloat('-0') && 0 == -0 being true. + */ + parse(dp) != dp && dp !== 0 ) && + + // 'toE() decimal places not an integer: {dp}' + // 'toE() decimal places out of range: {dp}' + !ifExceptionsThrow( dp, 'decimal places', 'toE' ) ) && this['c'] + ? this['c'].length - 1 + : dp | 0, 1 ); +}; + + +/* + * Return a string representing the value of this BigNumber in normal + * notation to dp fixed decimal places and rounded using ROUNDING_MODE if + * necessary. + * + * Note: as with JavaScript's number type, (-0).toFixed(0) is '0', + * but e.g. (-0.00001).toFixed(0) is '-0'. + * + * [dp] {number} Integer, 0 to MAX inclusive. + */ +P['toFixed'] = P['toF'] = function ( dp ) { + var n, str, d, + x = this; + + if ( !( dp == null || ( ( outOfRange = dp < 0 || dp > MAX ) || + parse(dp) != dp && dp !== 0 ) && + + // 'toF() decimal places not an integer: {dp}' + // 'toF() decimal places out of range: {dp}' + !ifExceptionsThrow( dp, 'decimal places', 'toF' ) ) ) { + d = x['e'] + ( dp | 0 ); + } + + n = TO_EXP_NEG, dp = TO_EXP_POS; + TO_EXP_NEG = -( TO_EXP_POS = 1 / 0 ); + + // Note: str is initially undefined. + if ( d == str ) { + str = x['toS'](); + } else { + str = format( x, d ); + + // (-0).toFixed() is '0', but (-0.1).toFixed() is '-0'. + // (-0).toFixed(1) is '0.0', but (-0.01).toFixed(1) is '-0.0'. + if ( x['s'] < 0 && x['c'] ) { + + // As e.g. -0 toFixed(3), will wrongly be returned as -0.000 from toString. + if ( !x['c'][0] ) { + str = str.replace(/^-/, ''); + + // As e.g. -0.5 if rounded to -0 will cause toString to omit the minus sign. + } else if ( str.indexOf('-') < 0 ) { + str = '-' + str; + } + } + } + TO_EXP_NEG = n, TO_EXP_POS = dp; + + 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. + * + * [maxD] {number|string|BigNumber} Integer >= 1 and < Infinity. + */ +P['toFraction'] = P['toFr'] = function ( maxD ) { + var q, frac, n0, d0, d2, n, e, + n1 = d0 = new BigNumber(ONE), + d1 = n0 = new BigNumber('0'), + x = this, + xc = x['c'], + exp = MAX_EXP, + dp = DECIMAL_PLACES, + rm = ROUNDING_MODE, + d = new BigNumber(ONE); + + // NaN, Infinity. + if ( !xc ) { + return x['toS'](); + } + + e = d['e'] = xc.length - x['e'] - 1; + + // If max denominator is undefined or null... + if ( maxD == null || + + // or NaN... + ( !( id = 12, n = new BigNumber(maxD) )['s'] || + + // or less than 1, or Infinity... + ( outOfRange = n['cmp'](n1) < 0 || !n['c'] ) || + + // or not an integer... + ( ERRORS && n['e'] < n['c'].length - 1 ) ) && + + // 'toFr() max denominator not an integer: {maxD}' + // 'toFr() max denominator out of range: {maxD}' + !ifExceptionsThrow( maxD, 'max denominator', 'toFr' ) || + + // or greater than the maxD needed to specify the value exactly... + ( maxD = n )['cmp'](d) > 0 ) { + + // d is e.g. 10, 100, 1000, 10000... , n1 is 1. + maxD = e > 0 ? d : n1; + } + + MAX_EXP = 1 / 0; + n = new BigNumber( xc.join('') ); + + for ( DECIMAL_PLACES = 0, ROUNDING_MODE = 1; ; ) { + q = n['div'](d); + d2 = d0['plus']( q['times'](d1) ); + + if ( d2['cmp'](maxD) == 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 = maxD['minus'](d0)['div'](d1); + n0 = n0['plus']( d2['times'](n1) ); + d0 = d0['plus']( d2['times'](d1) ); + + n0['s'] = n1['s'] = x['s']; + + DECIMAL_PLACES = e * 2; + ROUNDING_MODE = rm; + + // Determine which fraction is closer to x, n0 / d0 or n1 / d1? + frac = n1['div'](d1)['minus'](x)['abs']()['cmp']( + n0['div'](d0)['minus'](x)['abs']() ) < 1 + ? [ n1['toS'](), d1['toS']() ] + : [ n0['toS'](), d0['toS']() ]; + + return MAX_EXP = exp, DECIMAL_PLACES = dp, frac; +}; + + +/* + * Return a string representing the value of this BigNumber to sd significant + * digits and rounded using ROUNDING_MODE if necessary. + * If sd is less than the number of digits necessary to represent the integer + * part of the value in normal notation, then use exponential notation. + * + * sd {number} Integer, 1 to MAX inclusive. + */ +P['toPrecision'] = P['toP'] = function ( sd ) { + + /* + * ERRORS true: Throw if sd not undefined, null or an integer in range. + * ERRORS false: Ignore sd if not a number or not in range. + * Truncate non-integers. + */ + return sd == null || ( ( ( outOfRange = sd < 1 || sd > MAX ) || + parse(sd) != sd ) && + + // 'toP() precision not an integer: {sd}' + // 'toP() precision out of range: {sd}' + !ifExceptionsThrow( sd, 'precision', 'toP' ) ) + ? this['toS']() + : format( this, --sd | 0, 2 ); +}; + + +/* + * 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. + */ +P['toString'] = P['toS'] = function ( b ) { + var u, str, strL, + x = this, + xe = x['e']; + + // Infinity or NaN? + if ( xe === null ) { + str = x['s'] ? 'Infinity' : 'NaN'; + + // Exponential format? + } else if ( b === u && ( xe <= TO_EXP_NEG || xe >= TO_EXP_POS ) ) { + return format( x, x['c'].length - 1, 1 ); + } else { + str = x['c'].join(''); + + // Negative exponent? + if ( xe < 0 ) { + + // Prepend zeros. + for ( ; ++xe; str = '0' + str ) { + } + str = '0.' + str; + + // Positive exponent? + } else if ( strL = str.length, xe > 0 ) { + + if ( ++xe > strL ) { + + // Append zeros. + for ( xe -= strL; xe-- ; str += '0' ) { + } + } else if ( xe < strL ) { + str = str.slice( 0, xe ) + '.' + str.slice(xe); + } + + // Exponent zero. + } else { + if ( u = str.charAt(0), strL > 1 ) { + str = u + '.' + str.slice(1); + + // Avoid '-0' + } else if ( u == '0' ) { + return u; + } + } + + if ( b != null ) { + + if ( !( outOfRange = !( b >= 2 && b < 65 ) ) && + ( b == (b | 0) || !ERRORS ) ) { + str = convert( str, b | 0, 10, x['s'] ); + + // Avoid '-0' + if ( str == '0' ) { + return str; + } + } else { + + // 'toS() base not an integer: {b}' + // 'toS() base out of range: {b}' + ifExceptionsThrow( b, 'base', 'toS' ); + } + } + + } + + return x['s'] < 0 ? '-' + str : str; +}; + +P['toNumber'] = function () { + return parseInt(this['toString'](), 10); +}; + + +/* + * Return as toString, but do not accept a base argument. + */ +P['valueOf'] = function () { + return this['toS'](); +}; + + +// Add aliases for BigDecimal methods. +//P['add'] = P['plus']; +//P['subtract'] = P['minus']; +//P['multiply'] = P['times']; +//P['divide'] = P['div']; +//P['remainder'] = P['mod']; +//P['compareTo'] = P['cmp']; +//P['negate'] = P['neg']; + + +// EXPORT +module.exports = BigNumber; diff --git a/lib/browser/Key.js b/lib/browser/Key.js index e5df2644a..212a52d2e 100644 --- a/lib/browser/Key.js +++ b/lib/browser/Key.js @@ -1,7 +1,7 @@ var ECKey = require('../../browser/vendor-bundle.js').ECKey; var SecureRandom = require('../SecureRandom'); var Curve = require('../Curve'); -var bignum = require('bignum'); +var bignum = require('../Bignum'); var Key = function() { this._pub = null; diff --git a/lib/browser/Point.js b/lib/browser/Point.js index 8c6c085f8..4e5a14ac6 100644 --- a/lib/browser/Point.js +++ b/lib/browser/Point.js @@ -2,7 +2,7 @@ var imports = require('soop').imports(); var Key = imports.Key || require('./Key'); -var bignum = imports.bignum || require('bignum'); +var bignum = imports.bignum || require('../Bignum'); var assert = require('assert'); var ECPointFp = require('../../browser/vendor-bundle.js').ECPointFp; var ECFieldElementFp = require('../../browser/vendor-bundle.js').ECFieldElementFp; diff --git a/lib/node/Point.js b/lib/node/Point.js index 64d4dd7f8..76a04cbf7 100644 --- a/lib/node/Point.js +++ b/lib/node/Point.js @@ -1,7 +1,7 @@ "use strict"; var imports = require('soop').imports(); -var bignum = imports.bignum || require('bignum'); +var bignum = imports.bignum || require('../Bignum'); var CPPKey = imports.CPPKey || require('bindings')('KeyModule').Key; var assert = require('assert'); diff --git a/package.json b/package.json index 3585c617b..c860cd59e 100644 --- a/package.json +++ b/package.json @@ -54,7 +54,6 @@ "dependencies": { "jssha": "=1.5.0", "soop": "=0.1.5", - "base58-native": "=0.1.3", "bindings": "=1.1.1", "bufferput": "git://github.com/bitpay/node-bufferput.git", "bignum": "=0.6.2", @@ -65,7 +64,6 @@ "browserify": "=3.40.0", "browser-pack": "=2.0.1", "commander": "=2.1.0", - "browserify-bignum": "git://github.com/maraoz/browserify-bignum.git", "browserify-buffertools": "git://github.com/maraoz/browserify-buffertools.git", "socks5-client": "~0.3.6", "brfs": "=1.0.0", diff --git a/test/test.Base58.js b/test/test.Base58.js new file mode 100644 index 000000000..edc9227a2 --- /dev/null +++ b/test/test.Base58.js @@ -0,0 +1,49 @@ +var assert = require('assert'); +var base58 = require('../lib/Base58').base58; +var base58Check = require('../lib/Base58').base58Check; + +var testData = [ + ["61", "2g", "C2dGTwc"], + ["626262", "a3gV", "4jF5uERJAK"], + ["636363", "aPEr", "4mT4krqUYJ"], + ["73696d706c792061206c6f6e6720737472696e67", "2cFupjhnEsSn59qHXstmK2ffpLv2", "BXF1HuEUCqeVzZdrKeJjG74rjeXxqJ7dW"], + ["00eb15231dfceb60925886b67d065299925915aeb172c06647", "1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L", "13REmUhe2ckUKy1FvM7AMCdtyYq831yxM3QeyEu4"], + ["516b6fcd0f", "ABnLTmg", "237LSrY9NUUas"], + ["bf4f89001e670274dd", "3SEo3LWLoPntC", "GwDDDeduj1jpykc27e"], + ["572e4794", "3EFU7m", "FamExfqCeza"], + ["ecac89cad93923c02321", "EJDM8drfXA6uyA", "2W1Yd5Zu6WGyKVtHGMrH"], + ["10c8511e", "Rt5zm", "3op3iuGMmhs"], + ["00000000000000000000", "1111111111", "111111111146Momb"], + ["", "", "3QJmnh"] +]; + +//suite('basic'); + +test('allData', function() { + base58.encodeTest = function(raw, b58str) { + assert.equal(base58.encode(raw), b58str); + }; + + base58.decodeTest = function(raw, b58str) { + assert.equal(raw.toString('hex'), base58.decode(b58str).toString('hex')); + }; + + base58Check.encodeTest = function(raw, b58str) { + assert.equal(base58Check.encode(raw), b58str); + }; + + base58Check.decodeTest = function(raw, b58str) { + assert.equal(raw.toString('hex'), base58Check.decode(b58str).toString('hex')); + }; + + testData.forEach(function(datum) { + var raw = new Buffer(datum[0], 'hex'); + var b58 = datum[1]; + var b58Check = datum[2]; + + base58.encodeTest(raw, b58); + base58.decodeTest(raw, b58); + base58Check.encodeTest(raw, b58Check); + base58Check.decodeTest(raw, b58Check); + }); +}); diff --git a/test/test.Curve.js b/test/test.Curve.js index 211645060..bb6ba049b 100644 --- a/test/test.Curve.js +++ b/test/test.Curve.js @@ -4,7 +4,7 @@ var chai = chai || require('chai'); var bitcore = bitcore || require('../bitcore'); var coinUtil = coinUtil || bitcore.util; var buffertools = require('buffertools'); -var bignum = require('bignum'); +var bignum = bitcore.Bignum; var should = chai.should(); var assert = chai.assert; diff --git a/test/test.Key.js b/test/test.Key.js index d2bef6105..2bd397c92 100644 --- a/test/test.Key.js +++ b/test/test.Key.js @@ -8,7 +8,7 @@ var assert = chai.assert; var Key = bitcore.Key; var Point = bitcore.Point; -var bignum = require('bignum'); +var bignum = bitcore.Bignum; describe('Key', function() { it('should initialize the main object', function() { diff --git a/test/test.Point.js b/test/test.Point.js index 4ca45a556..9ec2ff7c2 100644 --- a/test/test.Point.js +++ b/test/test.Point.js @@ -4,7 +4,7 @@ var chai = chai || require('chai'); var bitcore = bitcore || require('../bitcore'); var coinUtil = coinUtil || bitcore.util; var buffertools = require('buffertools'); -var bignum = require('bignum'); +var bignum = bitcore.Bignum; var should = chai.should(); var assert = chai.assert; diff --git a/test/test.misc.js b/test/test.misc.js index f3da0b852..f67642788 100644 --- a/test/test.misc.js +++ b/test/test.misc.js @@ -9,8 +9,8 @@ var should = chai.should(); var testdata = testdata || require('./testdata'); -var bignum = bitcore.bignum; -var base58 = bitcore.base58; +var bignum = bitcore.Bignum; +var base58 = bitcore.Base58; var base58Check = base58.base58Check; var Address = bitcore.Address; @@ -81,7 +81,7 @@ describe('Miscelaneous stuff', function() { }); // bignum it('should initialze the bignum object', function() { - should.exist(bitcore.bignum); + should.exist(bitcore.Bignum); }); it('should create a bignum from string', function() { var n = bignum('9832087987979879879879879879879879879879879879'); @@ -96,7 +96,7 @@ describe('Miscelaneous stuff', function() { // base58 it('should initialze the base58 object', function() { - should.exist(bitcore.base58); + should.exist(bitcore.Base58); }); it('should obtain the same string in base58 roundtrip', function() { var m = 'mqqa8xSMVDyf9QxihGnPtap6Mh6qemUkcu'; diff --git a/util/EncodedData.js b/util/EncodedData.js index 2736fc174..18bf3ad54 100644 --- a/util/EncodedData.js +++ b/util/EncodedData.js @@ -1,5 +1,5 @@ var imports = require('soop').imports(); -var base58 = imports.base58 || require('base58-native').base58Check; +var base58 = imports.base58 || require('../lib/Base58').base58Check; // Constructor. Takes the following forms: diff --git a/util/VersionedData.js b/util/VersionedData.js index ac7555919..3ed357d61 100644 --- a/util/VersionedData.js +++ b/util/VersionedData.js @@ -1,5 +1,5 @@ var imports = require('soop').imports(); -var base58 = imports.base58 || require('base58-native').base58Check; +var base58 = imports.base58 || require('../lib/Base58').base58Check; var parent = imports.parent || require('./EncodedData'); diff --git a/util/util.js b/util/util.js index a59df4b35..ab5220920 100644 --- a/util/util.js +++ b/util/util.js @@ -1,5 +1,5 @@ var crypto = require('crypto'); -var bignum = require('bignum'); +var bignum = require('../lib/Bignum'); var Binary = require('binary'); var Put = require('bufferput'); var buffertools = require('buffertools');