From 0a2e7664b82f994db86d7a7b443570f808f42540 Mon Sep 17 00:00:00 2001 From: Stefan Thomas Date: Fri, 26 Apr 2013 21:51:50 +0200 Subject: [PATCH] JS: Remove ripple-lib and link to it via package.json instead. --- .gitmodules | 7 - README.md | 5 +- bin/browser.js | 2 +- bin/debug_local_sign.js | 2 +- bin/rlint.js | 8 +- bin/rsign.js | 2 +- package.json | 15 +- src/js/README.md | 3 - src/js/account.js | 148 --- src/js/amount.js | 1005 -------------------- src/js/base.js | 140 --- src/js/binformat.js | 90 -- src/js/config.js | 10 - src/js/cryptojs | 1 - src/js/currency.js | 83 -- src/js/index.js | 22 - src/js/jsbn.js | 1219 ------------------------- src/js/keypair.js | 67 -- src/js/meta.js | 137 --- src/js/network.js | 58 -- src/js/orderbook.js | 250 ----- src/js/remote.js | 1258 -------------------------- src/js/seed.js | 116 --- src/js/serializedobject.js | 144 --- src/js/serializedtypes.js | 319 ------- src/js/server.js | 255 ------ src/js/sjcl | 1 - src/js/sjcl-custom/sjcl-ecdsa-der.js | 34 - src/js/sjcl-custom/sjcl-extramath.js | 61 -- src/js/sjcl-custom/sjcl-ripemd160.js | 207 ----- src/js/sjcl-custom/sjcl-secp256k1.js | 72 -- src/js/sjcl-custom/sjcl-validecc.js | 30 - src/js/transaction.js | 680 -------------- src/js/uint.js | 227 ----- src/js/uint160.js | 70 -- src/js/uint256.js | 34 - src/js/utils.js | 136 --- src/js/utils.web.js | 11 - test/account_tx-test.js | 8 +- test/amount-test.js | 355 -------- test/base58-test.js | 20 - test/jsonrpc-test.js | 6 +- test/monitor-test.js | 6 +- {src/js => test}/nodeutils.js | 2 +- test/offer-test.js | 8 +- test/path-test.js | 12 +- test/remote-test.js | 6 +- test/send-test.js | 10 +- test/server.js | 4 +- test/sign-test.js | 24 - test/testutils.js | 6 +- test/utils-test.js | 26 - test/websocket-test.js | 4 +- 53 files changed, 50 insertions(+), 7376 deletions(-) delete mode 100644 src/js/README.md delete mode 100644 src/js/account.js delete mode 100644 src/js/amount.js delete mode 100644 src/js/base.js delete mode 100644 src/js/binformat.js delete mode 100644 src/js/config.js delete mode 160000 src/js/cryptojs delete mode 100644 src/js/currency.js delete mode 100644 src/js/index.js delete mode 100644 src/js/jsbn.js delete mode 100644 src/js/keypair.js delete mode 100644 src/js/meta.js delete mode 100644 src/js/network.js delete mode 100644 src/js/orderbook.js delete mode 100644 src/js/remote.js delete mode 100644 src/js/seed.js delete mode 100644 src/js/serializedobject.js delete mode 100644 src/js/serializedtypes.js delete mode 100644 src/js/server.js delete mode 160000 src/js/sjcl delete mode 100644 src/js/sjcl-custom/sjcl-ecdsa-der.js delete mode 100755 src/js/sjcl-custom/sjcl-extramath.js delete mode 100755 src/js/sjcl-custom/sjcl-ripemd160.js delete mode 100755 src/js/sjcl-custom/sjcl-secp256k1.js delete mode 100644 src/js/sjcl-custom/sjcl-validecc.js delete mode 100644 src/js/transaction.js delete mode 100644 src/js/uint.js delete mode 100644 src/js/uint160.js delete mode 100644 src/js/uint256.js delete mode 100644 src/js/utils.js delete mode 100644 src/js/utils.web.js delete mode 100644 test/amount-test.js delete mode 100644 test/base58-test.js rename {src/js => test}/nodeutils.js (97%) delete mode 100644 test/sign-test.js delete mode 100644 test/utils-test.js diff --git a/.gitmodules b/.gitmodules index 75f16e6dd0..6fdda75677 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,10 +1,3 @@ -[submodule "src/js/cryptojs"] - path = src/js/cryptojs - url = git://github.com/gwjjeff/cryptojs.git -[submodule "src/js/sjcl"] - path = src/js/sjcl - url = git://github.com/bitwiseshiftleft/sjcl.git - ignore = dirty [submodule "src/cpp/leveldb"] path = src/cpp/leveldb url = https://code.google.com/p/leveldb/ diff --git a/README.md b/README.md index 2d33f969b3..96981679c5 100644 --- a/README.md +++ b/README.md @@ -3,13 +3,10 @@ Ripple - P2P Payment Network Some portions of this source code are currently closed source. -This is the repository for Ripple's: -* rippled - Reference P2P network server -* ripple.js - Reference JavaScript client libraries for node.js and browsers. +This is the repository for Ripple's `rippled`, reference P2P network server. Build instructions: * https://ripple.com/wiki/Rippled_build_instructions -* https://ripple.com/wiki/Ripple_JavaScript_library Setup instructions: * https://ripple.com/wiki/Rippled_setup_instructions diff --git a/bin/browser.js b/bin/browser.js index d02aeb2b3b..81618bd002 100755 --- a/bin/browser.js +++ b/bin/browser.js @@ -23,7 +23,7 @@ var extend = require("extend"); var http = require("http"); var url = require("url"); -var Remote = require("../src/js/remote.js").Remote; +var Remote = require("ripple-lib").Remote; var program = process.argv[1]; diff --git a/bin/debug_local_sign.js b/bin/debug_local_sign.js index 7d77d5252c..24f9aab481 100644 --- a/bin/debug_local_sign.js +++ b/bin/debug_local_sign.js @@ -1,4 +1,4 @@ -var ripple = require('../src/js'); +var ripple = require('ripple-lib'); var v = { seed: "snoPBrXtMeMyMHUVTgbuqAfg1SUTb", diff --git a/bin/rlint.js b/bin/rlint.js index e05e424dc5..ce12e9560a 100755 --- a/bin/rlint.js +++ b/bin/rlint.js @@ -1,10 +1,10 @@ #!/usr/bin/node var async = require('async'); -var Remote = require('../src/js/remote').Remote; -var Transaction = require('../src/js/transaction').Transaction; -var UInt160 = require('../src/js/uint160').UInt160; -var Amount = require('../src/js/amount').Amount; +var Remote = require('ripple-lib').Remote; +var Transaction = require('ripple-lib').Transaction; +var UInt160 = require('ripple-lib').UInt160; +var Amount = require('ripple-lib').Amount; var book_key = function (book) { return book.taker_pays.currency diff --git a/bin/rsign.js b/bin/rsign.js index 431b494318..a140df607c 100755 --- a/bin/rsign.js +++ b/bin/rsign.js @@ -1,6 +1,6 @@ #!/usr/bin/node -var Transaction = require('../src/js/transaction').Transaction; +var Transaction = require('ripple-lib').Transaction; var cursor = 2; var verbose; diff --git a/package.json b/package.json index 5a5f32277b..7676843360 100644 --- a/package.json +++ b/package.json @@ -1,19 +1,16 @@ { - "name": "ripple-lib", - "version": "0.7.10", - "description": "Ripple JavaScript client library", + "name": "rippled", + "version": "0.0.1", + "description": "Rippled Server", + + "private": true, - "files": [ - "src/js/*.js", - "build/sjcl.js", - "bin/rsign.js" - ], - "main": "src/js", "directories": { "test": "test" }, "dependencies": { + "ripple-lib": "0.7.10", "async": "~0.1.22", "ws": "~0.4.22", "extend": "~1.1.1", diff --git a/src/js/README.md b/src/js/README.md deleted file mode 100644 index 7b357e08bd..0000000000 --- a/src/js/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Ripple JavaScript library - -This library lets you connect to a ripple server via websockets. diff --git a/src/js/account.js b/src/js/account.js deleted file mode 100644 index 603ad7d180..0000000000 --- a/src/js/account.js +++ /dev/null @@ -1,148 +0,0 @@ -// Routines for working with an account. -// -// You should not instantiate this class yourself, instead use Remote#account. -// -// Events: -// wallet_clean : True, iff the wallet has been updated. -// wallet_dirty : True, iff the wallet needs to be updated. -// balance : The current stamp balance. -// balance_proposed -// - -// var network = require("./network.js"); - -var EventEmitter = require('events').EventEmitter; -var util = require('util'); - -var Amount = require('./amount').Amount; -var UInt160 = require('./uint160').UInt160; - -var extend = require('extend'); - -var Account = function (remote, account) { - EventEmitter.call(this); - var self = this; - - this._remote = remote; - this._account = UInt160.from_json(account); - this._account_id = this._account.to_json(); - this._subs = 0; - - // Ledger entry object - // Important: This must never be overwritten, only extend()-ed - this._entry = {}; - - this.on('newListener', function (type, listener) { - if (Account.subscribe_events.indexOf(type) !== -1) { - if (!self._subs && 'open' === self._remote._online_state) { - self._remote.request_subscribe() - .accounts(self._account_id) - .request(); - } - self._subs += 1; - } - }); - - this.on('removeListener', function (type, listener) { - if (Account.subscribe_events.indexOf(type) !== -1) { - self._subs -= 1; - - if (!self._subs && 'open' === self._remote._online_state) { - self._remote.request_unsubscribe() - .accounts(self._account_id) - .request(); - } - } - }); - - this._remote.on('prepare_subscribe', function (request) { - if (self._subs) request.accounts(self._account_id); - }); - - this.on('transaction', function (msg) { - var changed = false; - msg.mmeta.each(function (an) { - if (an.entryType === 'AccountRoot' && - an.fields.Account === self._account_id) { - extend(self._entry, an.fieldsNew, an.fieldsFinal); - changed = true; - } - }); - if (changed) { - self.emit('entry', self._entry); - } - }); - - return this; -}; - -util.inherits(Account, EventEmitter); - -/** - * List of events that require a remote subscription to the account. - */ -Account.subscribe_events = ['transaction', 'entry']; - -Account.prototype.to_json = function () -{ - return this._account.to_json(); -}; - -/** - * Whether the AccountId is valid. - * - * Note: This does not tell you whether the account exists in the ledger. - */ -Account.prototype.is_valid = function () -{ - return this._account.is_valid(); -}; - -/** - * Retrieve the current AccountRoot entry. - * - * To keep up-to-date with changes to the AccountRoot entry, subscribe to the - * "entry" event. - * - * @param {function (err, entry)} callback Called with the result - */ -Account.prototype.entry = function (callback) -{ - var self = this; - - self._remote.request_account_info(this._account_id) - .on('success', function (e) { - extend(self._entry, e.account_data); - self.emit('entry', self._entry); - - if ("function" === typeof callback) { - callback(null, e); - } - }) - .on('error', function (e) { - callback(e); - }) - .request(); - - return this; -}; - -/** - * Notify object of a relevant transaction. - * - * This is only meant to be called by the Remote class. You should never have to - * call this yourself. - */ -Account.prototype.notifyTx = function (message) -{ - // Only trigger the event if the account object is actually - // subscribed - this prevents some weird phantom events from - // occurring. - if (this._subs) { - this.emit('transaction', message); - } -}; - -exports.Account = Account; - -// vim:sw=2:sts=2:ts=8:et diff --git a/src/js/amount.js b/src/js/amount.js deleted file mode 100644 index 14d6526733..0000000000 --- a/src/js/amount.js +++ /dev/null @@ -1,1005 +0,0 @@ -// Represent Ripple amounts and currencies. -// - Numbers in hex are big-endian. - -var sjcl = require('../../build/sjcl'); -var bn = sjcl.bn; -var utils = require('./utils'); -var jsbn = require('./jsbn'); - -var BigInteger = jsbn.BigInteger; - -var UInt160 = require('./uint160').UInt160, - Seed = require('./seed').Seed, - Currency = require('./currency').Currency; - -var consts = exports.consts = { - 'currency_xns' : 0, - 'currency_one' : 1, - 'xns_precision' : 6, - - // BigInteger values prefixed with bi_. - 'bi_5' : new BigInteger('5'), - 'bi_7' : new BigInteger('7'), - 'bi_10' : new BigInteger('10'), - 'bi_1e14' : new BigInteger(String(1e14)), - 'bi_1e16' : new BigInteger(String(1e16)), - 'bi_1e17' : new BigInteger(String(1e17)), - 'bi_1e32' : new BigInteger('100000000000000000000000000000000'), - 'bi_man_max_value' : new BigInteger('9999999999999999'), - 'bi_man_min_value' : new BigInteger('1000000000000000'), - 'bi_xns_max' : new BigInteger("9000000000000000000"), // Json wire limit. - 'bi_xns_min' : new BigInteger("-9000000000000000000"), // Json wire limit. - 'bi_xns_unit' : new BigInteger('1000000'), - - 'cMinOffset' : -96, - 'cMaxOffset' : 80, -}; - - -// -// Amount class in the style of Java's BigInteger class -// http://docs.oracle.com/javase/1.3/docs/api/java/math/BigInteger.html -// - -var Amount = function () { - // Json format: - // integer : XRP - // { 'value' : ..., 'currency' : ..., 'issuer' : ...} - - this._value = new BigInteger(); // NaN for bad value. Always positive. - this._offset = 0; // Always 0 for XRP. - this._is_native = true; // Default to XRP. Only valid if value is not NaN. - this._is_negative = false; - - this._currency = new Currency(); - this._issuer = new UInt160(); -}; - -// Given "100/USD/mtgox" return the a string with mtgox remapped. -Amount.text_full_rewrite = function (j) { - return Amount.from_json(j).to_text_full(); -} - -// Given "100/USD/mtgox" return the json. -Amount.json_rewrite = function (j) { - return Amount.from_json(j).to_json(); -}; - -Amount.from_json = function (j) { - return (new Amount()).parse_json(j); -}; - -Amount.from_quality = function (q, c, i) { - return (new Amount()).parse_quality(q, c, i); -}; - -Amount.from_human = function (j) { - return (new Amount()).parse_human(j); -}; - -Amount.is_valid = function (j) { - return Amount.from_json(j).is_valid(); -}; - -Amount.is_valid_full = function (j) { - return Amount.from_json(j).is_valid_full(); -}; - -Amount.NaN = function () { - var result = new Amount(); - - result._value = NaN; - - return result; -}; - -// Returns a new value which is the absolute value of this. -Amount.prototype.abs = function () { - return this.clone(this.is_negative()); -}; - -// Result in terms of this' currency and issuer. -Amount.prototype.add = function (v) { - var result; - - v = Amount.from_json(v); - - if (!this.is_comparable(v)) { - result = Amount.NaN(); - } - else if (v.is_zero()) { - result = this; - } - else if (this.is_zero()) { - result = v.clone(); - result._is_negative = false; - result._is_native = this._is_native; - result._currency = this._currency; - result._issuer = this._issuer; - } - else if (this._is_native) { - result = new Amount(); - - var v1 = this._is_negative ? this._value.negate() : this._value; - var v2 = v._is_negative ? v._value.negate() : v._value; - var s = v1.add(v2); - - result._is_negative = s.compareTo(BigInteger.ZERO) < 0; - result._value = result._is_negative ? s.negate() : s; - result._currency = this._currency; - result._issuer = this._issuer; - } - else - { - var v1 = this._is_negative ? this._value.negate() : this._value; - var o1 = this._offset; - var v2 = v._is_negative ? v._value.negate() : v._value; - var o2 = v._offset; - - while (o1 < o2) { - v1 = v1.divide(consts.bi_10); - o1 += 1; - } - - while (o2 < o1) { - v2 = v2.divide(consts.bi_10); - o2 += 1; - } - - result = new Amount(); - result._is_native = false; - result._offset = o1; - result._value = v1.add(v2); - result._is_negative = result._value.compareTo(BigInteger.ZERO) < 0; - - if (result._is_negative) { - result._value = result._value.negate(); - } - - result._currency = this._currency; - result._issuer = this._issuer; - - result.canonicalize(); - } - - return result; -}; - -Amount.prototype.canonicalize = function () { - if (!(this._value instanceof BigInteger)) - { - // NaN. - // nothing - } - else if (this._is_native) { - // Native. - - if (this._value.equals(BigInteger.ZERO)) { - this._offset = 0; - this._is_negative = false; - } - else { - // Normalize _offset to 0. - - while (this._offset < 0) { - this._value = this._value.divide(consts.bi_10); - this._offset += 1; - } - - while (this._offset > 0) { - this._value = this._value.multiply(consts.bi_10); - this._offset -= 1; - } - } - - // XXX Make sure not bigger than supported. Throw if so. - } - else if (this.is_zero()) { - this._offset = -100; - this._is_negative = false; - } - else - { - // Normalize mantissa to valid range. - - while (this._value.compareTo(consts.bi_man_min_value) < 0) { - this._value = this._value.multiply(consts.bi_10); - this._offset -= 1; - } - - while (this._value.compareTo(consts.bi_man_max_value) > 0) { - this._value = this._value.divide(consts.bi_10); - this._offset += 1; - } - } - - return this; -}; - -Amount.prototype.clone = function (negate) { - return this.copyTo(new Amount(), negate); -}; - -Amount.prototype.compareTo = function (v) { - var result; - - if (!this.is_comparable(v)) { - result = Amount.NaN(); - } - else if (this._is_negative !== v._is_negative) { - // Different sign. - result = this._is_negative ? -1 : 1; - } - else if (this._value.equals(BigInteger.ZERO)) { - // Same sign: positive. - result = v._value.equals(BigInteger.ZERO) ? 0 : -1; - } - else if (v._value.equals(BigInteger.ZERO)) { - // Same sign: positive. - result = 1; - } - else if (!this._is_native && this._offset > v._offset) { - result = this._is_negative ? -1 : 1; - } - else if (!this._is_native && this._offset < v._offset) { - result = this._is_negative ? 1 : -1; - } - else { - result = this._value.compareTo(v._value); - - if (result > 0) - result = this._is_negative ? -1 : 1; - else if (result < 0) - result = this._is_negative ? 1 : -1; - } - - return result; -}; - -// Make d a copy of this. Returns d. -// Modification of objects internally refered to is not allowed. -Amount.prototype.copyTo = function (d, negate) { - if ('object' === typeof this._value) - { - this._value.copyTo(d._value); - } - else - { - d._value = this._value; - } - - d._offset = this._offset; - d._is_native = this._is_native; - d._is_negative = negate - ? !this._is_negative // Negating. - : this._is_negative; // Just copying. - - d._currency = this._currency; - d._issuer = this._issuer; - - // Prevent negative zero - if (d.is_zero()) d._is_negative = false; - - return d; -}; - -Amount.prototype.currency = function () { - return this._currency; -}; - -Amount.prototype.equals = function (d, ignore_issuer) { - if ("string" === typeof d) { - return this.equals(Amount.from_json(d)); - } - - if (this === d) return true; - - if (d instanceof Amount) { - if (!this.is_valid() || !d.is_valid()) return false; - if (this._is_native !== d._is_native) return false; - - if (!this._value.equals(d._value) || this._offset !== d._offset) { - return false; - } - - if (this._is_negative !== d._is_negative) return false; - - if (!this._is_native) { - if (!this._currency.equals(d._currency)) return false; - if (!ignore_issuer && !this._issuer.equals(d._issuer)) return false; - } - return true; - } else return false; -}; - -// Result in terms of this' currency and issuer. -Amount.prototype.divide = function (d) { - var result; - - if (d.is_zero()) { - throw "divide by zero"; - } - else if (this.is_zero()) { - result = this; - } - else if (!this.is_valid()) { - throw new Error("Invalid dividend"); - } - else if (!d.is_valid()) { - throw new Error("Invalid divisor"); - } - else { - var _n = this; - - if (_n.is_native()) { - _n = _n.clone(); - - while (_n._value.compareTo(consts.bi_man_min_value) < 0) { - _n._value = _n._value.multiply(consts.bi_10); - _n._offset -= 1; - } - } - - var _d = d; - - if (_d.is_native()) { - _d = _d.clone(); - - while (_d._value.compareTo(consts.bi_man_min_value) < 0) { - _d._value = _d._value.multiply(consts.bi_10); - _d._offset -= 1; - } - } - - result = new Amount(); - result._offset = _n._offset - _d._offset - 17; - result._value = _n._value.multiply(consts.bi_1e17).divide(_d._value).add(consts.bi_5); - result._is_native = _n._is_native; - result._is_negative = _n._is_negative !== _d._is_negative; - result._currency = _n._currency; - result._issuer = _n._issuer; - - result.canonicalize(); - } - - return result; -}; - -/** - * Calculate a ratio between two amounts. - * - * This function calculates a ratio - such as a price - between two Amount - * objects. - * - * The return value will have the same type (currency) as the numerator. This is - * a simplification, which should be sane in most cases. For example, a USD/XRP - * price would be rendered as USD. - * - * @example - * var price = buy_amount.ratio_human(sell_amount); - * - * @this {Amount} The numerator (top half) of the fraction. - * @param {Amount} denominator The denominator (bottom half) of the fraction. - * @return {Amount} The resulting ratio. Unit will be the same as numerator. - */ -Amount.prototype.ratio_human = function (denominator) { - if ("number" === typeof denominator && parseInt(denominator) === denominator) { - // Special handling of integer arguments - denominator = Amount.from_json("" + denominator + ".0"); - } else { - denominator = Amount.from_json(denominator); - } - - var numerator = this; - denominator = Amount.from_json(denominator); - - // Special case: The denominator is a native (XRP) amount. - // - // In that case, it's going to be expressed as base units (1 XRP = - // 10^xns_precision base units). - // - // However, the unit of the denominator is lost, so when the resulting ratio - // is printed, the ratio is going to be too small by a factor of - // 10^xns_precision. - // - // To compensate, we multiply the numerator by 10^xns_precision. - if (denominator._is_native) { - numerator = numerator.clone(); - numerator._value = numerator._value.multiply(consts.bi_xns_unit); - numerator.canonicalize(); - } - - return numerator.divide(denominator); -}; - -/** - * Calculate a product of two amounts. - * - * This function allows you to calculate a product between two amounts which - * retains XRPs human/external interpretation (i.e. 1 XRP = 1,000,000 base - * units). - * - * Intended use is to calculate something like: 10 USD * 10 XRP/USD = 100 XRP - * - * @example - * var sell_amount = buy_amount.product_human(price); - * - * @see Amount#ratio_human - * - * @this {Amount} The first factor of the product. - * @param {Amount} factor The second factor of the product. - * @return {Amount} The product. Unit will be the same as the first factor. - */ -Amount.prototype.product_human = function (factor) { - if ("number" === typeof factor && parseInt(factor) === factor) { - // Special handling of integer arguments - factor = Amount.from_json("" + factor + ".0"); - } else { - factor = Amount.from_json(factor); - } - - var product = this.multiply(factor); - - // Special case: The second factor is a native (XRP) amount expressed as base - // units (1 XRP = 10^xns_precision base units). - // - // See also Amount#ratio_human. - if (factor._is_native) { - product._value = product._value.divide(consts.bi_xns_unit); - product.canonicalize(); - } - - return product; -} - -// True if Amounts are valid and both native or non-native. -Amount.prototype.is_comparable = function (v) { - return this._value instanceof BigInteger - && v._value instanceof BigInteger - && this._is_native === v._is_native; -}; - -Amount.prototype.is_native = function () { - return this._is_native; -}; - -Amount.prototype.is_negative = function () { - return this._value instanceof BigInteger - ? this._is_negative - : false; // NaN is not negative -}; - -Amount.prototype.is_positive = function () { - return !this.is_zero() && !this.is_negative(); -}; - -// Only checks the value. Not the currency and issuer. -Amount.prototype.is_valid = function () { - return this._value instanceof BigInteger; -}; - -Amount.prototype.is_valid_full = function () { - return this.is_valid() && this._currency.is_valid() && this._issuer.is_valid(); -}; - -Amount.prototype.is_zero = function () { - return this._value instanceof BigInteger - ? this._value.equals(BigInteger.ZERO) - : false; -}; - -Amount.prototype.issuer = function () { - return this._issuer; -}; - -// Result in terms of this' currency and issuer. -// XXX Diverges from cpp. -Amount.prototype.multiply = function (v) { - var result; - - if (this.is_zero()) { - result = this; - } - else if (v.is_zero()) { - result = this.clone(); - result._value = BigInteger.ZERO; - } - else { - var v1 = this._value; - var o1 = this._offset; - var v2 = v._value; - var o2 = v._offset; - - if (this.is_native()) { - while (v1.compareTo(consts.bi_man_min_value) < 0) { - v1 = v1.multiply(consts.bi_10); - o1 -= 1; - } - } - - if (v.is_native()) { - while (v2.compareTo(consts.bi_man_min_value) < 0) { - v2 = v2.multiply(consts.bi_10); - o2 -= 1; - } - } - - result = new Amount(); - result._offset = o1 + o2 + 14; - result._value = v1.multiply(v2).divide(consts.bi_1e14).add(consts.bi_7); - result._is_native = this._is_native; - result._is_negative = this._is_negative !== v._is_negative; - result._currency = this._currency; - result._issuer = this._issuer; - - result.canonicalize(); - } - - return result; -}; - -// Return a new value. -Amount.prototype.negate = function () { - return this.clone('NEGATE'); -}; - -/** - * Tries to correctly interpret an amount as entered by a user. - * - * Examples: - * - * XRP 250 => 250000000/XRP - * 25.2 XRP => 25200000/XRP - * USD 100.40 => 100.4/USD/? - * 100 => 100000000/XRP - */ -Amount.prototype.parse_human = function (j) { - // Cast to string - j = ""+j; - - // Parse - var m = j.match(/^\s*([a-z]{3})?\s*(-)?(\d+)(?:\.(\d*))?\s*([a-z]{3})?\s*$/i); - - if (m) { - var currency = m[1] || m[5] || "XRP", - integer = m[3] || "0", - fraction = m[4] || "", - precision = null; - - currency = currency.toUpperCase(); - - this._value = new BigInteger(integer); - this.set_currency(currency); - - // XRP have exactly six digits of precision - if (currency === 'XRP') { - fraction = fraction.slice(0, 6); - while (fraction.length < 6) { - fraction += "0"; - } - this._is_native = true; - this._value = this._value.multiply(consts.bi_xns_unit).add(new BigInteger(fraction)); - } - // Other currencies have arbitrary precision - else { - while (fraction[fraction.length - 1] === "0") { - fraction = fraction.slice(0, fraction.length - 1); - } - - precision = fraction.length; - - this._is_native = false; - var multiplier = consts.bi_10.clone().pow(precision); - this._value = this._value.multiply(multiplier).add(new BigInteger(fraction)); - this._offset = -precision; - - this.canonicalize(); - } - - this._is_negative = !!m[2]; - } else { - this._value = NaN; - } - - return this; -}; - -Amount.prototype.parse_issuer = function (issuer) { - this._issuer = UInt160.from_json(issuer); - - return this; -}; - -// --> h: 8 hex bytes quality or 32 hex bytes directory index. -Amount.prototype.parse_quality = function (q, c, i) { - this._is_negative = false; - this._value = new BigInteger(q.substring(q.length-14), 16); - this._offset = parseInt(q.substring(q.length-16, q.length-14), 16)-100; - this._currency = Currency.from_json(c); - this._issuer = UInt160.from_json(i); - this._is_native = this._currency.is_native(); - - this.canonicalize(); - - return this; -} - -// <-> j -Amount.prototype.parse_json = function (j) { - if ('string' === typeof j) { - // .../.../... notation is not a wire format. But allowed for easier testing. - var m = j.match(/^([^/]+)\/(...)(?:\/(.+))?$/); - - if (m) { - this._currency = Currency.from_json(m[2]); - if (m[3]) { - this._issuer = UInt160.from_json(m[3]); - } else { - this._issuer = UInt160.from_json('1'); - } - this.parse_value(m[1]); - } - else { - this.parse_native(j); - this._currency = Currency.from_json("0"); - this._issuer = UInt160.from_json("0"); - } - } - else if ('number' === typeof j) { - this.parse_json(""+j); - } - else if ('object' === typeof j && j instanceof Amount) { - j.copyTo(this); - } - else if ('object' === typeof j && 'value' in j) { - // Parse the passed value to sanitize and copy it. - - this._currency.parse_json(j.currency); // Never XRP. - if ("string" === typeof j.issuer) this._issuer.parse_json(j.issuer); - this.parse_value(j.value); - } - else { - this._value = NaN; - } - - return this; -}; - -// Parse a XRP value from untrusted input. -// - integer = raw units -// - float = with precision 6 -// XXX Improvements: disallow leading zeros. -Amount.prototype.parse_native = function (j) { - var m; - - if ('string' === typeof j) - m = j.match(/^(-?)(\d*)(\.\d{0,6})?$/); - - if (m) { - if (undefined === m[3]) { - // Integer notation - - this._value = new BigInteger(m[2]); - } - else { - // Float notation : values multiplied by 1,000,000. - - var int_part = (new BigInteger(m[2])).multiply(consts.bi_xns_unit); - var fraction_part = (new BigInteger(m[3])).multiply(new BigInteger(String(Math.pow(10, 1+consts.xns_precision-m[3].length)))); - - this._value = int_part.add(fraction_part); - } - - this._is_native = true; - this._offset = 0; - this._is_negative = !!m[1] && this._value.compareTo(BigInteger.ZERO) !== 0; - - if (this._value.compareTo(consts.bi_xns_max) > 0) - { - this._value = NaN; - } - } - else { - this._value = NaN; - } - - return this; -}; - -// Parse a non-native value for the json wire format. -// Requires _currency to be set! -Amount.prototype.parse_value = function (j) { - this._is_native = false; - - if ('number' === typeof j) { - this._is_negative = j < 0; - this._value = new BigInteger(this._is_negative ? -j : j); - this._offset = 0; - - this.canonicalize(); - } - else if ('string' === typeof j) { - var i = j.match(/^(-?)(\d+)$/); - var d = !i && j.match(/^(-?)(\d*)\.(\d*)$/); - var e = !e && j.match(/^(-?)(\d*)e(-?\d+)$/); - - if (e) { - // e notation - - this._value = new BigInteger(e[2]); - this._offset = parseInt(e[3]); - this._is_negative = !!e[1]; - - this.canonicalize(); - } - else if (d) { - // float notation - - var integer = new BigInteger(d[2]); - var fraction = new BigInteger(d[3]); - var precision = d[3].length; - - this._value = integer.multiply(consts.bi_10.clone().pow(precision)).add(fraction); - this._offset = -precision; - this._is_negative = !!d[1]; - - this.canonicalize(); - } - else if (i) { - // integer notation - - this._value = new BigInteger(i[2]); - this._offset = 0; - this._is_negative = !!i[1]; - - this.canonicalize(); - } - else { - this._value = NaN; - } - } - else if (j instanceof BigInteger) { - this._value = j; - } - else { - this._value = NaN; - } - - return this; -}; - -Amount.prototype.set_currency = function (c) { - if ('string' === typeof c) { - this._currency = Currency.from_json(c); - } - else - { - this._currency = c; - } - this._is_native = this._currency.is_native(); - - return this; -}; - -Amount.prototype.set_issuer = function (issuer) { - if (issuer instanceof UInt160) { - this._issuer = issuer; - } else { - this._issuer = UInt160.from_json(issuer); - } - - return this; -}; - -// Result in terms of this' currency and issuer. -Amount.prototype.subtract = function (v) { - // Correctness over speed, less code has less bugs, reuse add code. - return this.add(Amount.from_json(v).negate()); -}; - -Amount.prototype.to_number = function (allow_nan) { - var s = this.to_text(allow_nan); - - return ('string' === typeof s) ? Number(s) : s; -} - -// Convert only value to JSON wire format. -Amount.prototype.to_text = function (allow_nan) { - if (!(this._value instanceof BigInteger)) { - // Never should happen. - return allow_nan ? NaN : "0"; - } - else if (this._is_native) { - if (this._value.compareTo(consts.bi_xns_max) > 0) - { - // Never should happen. - return allow_nan ? NaN : "0"; - } - else - { - return (this._is_negative ? "-" : "") + this._value.toString(); - } - } - else if (this.is_zero()) - { - return "0"; - } - else if (this._offset && (this._offset < -25 || this._offset > -4)) - { - // Use e notation. - // XXX Clamp output. - - return (this._is_negative ? "-" : "") + this._value.toString() + "e" + this._offset; - } - else - { - var val = "000000000000000000000000000" + this._value.toString() + "00000000000000000000000"; - var pre = val.substring(0, this._offset + 43); - var post = val.substring(this._offset + 43); - var s_pre = pre.match(/[1-9].*$/); // Everything but leading zeros. - var s_post = post.match(/[1-9]0*$/); // Last non-zero plus trailing zeros. - - return (this._is_negative ? "-" : "") - + (s_pre ? s_pre[0] : "0") - + (s_post ? "." + post.substring(0, 1+post.length-s_post[0].length) : ""); - } -}; - -/** - * Format only value in a human-readable format. - * - * @example - * var pretty = amount.to_human({precision: 2}); - * - * @param opts Options for formatter. - * @param opts.precision {Number} Max. number of digits after decimal point. - * @param opts.min_precision {Number} Min. number of digits after dec. point. - * @param opts.skip_empty_fraction {Boolean} Don't show fraction if it is zero, - * even if min_precision is set. - * @param opts.group_sep {Boolean|String} Whether to show a separator every n - * digits, if a string, that value will be used as the separator. Default: "," - * @param opts.group_width {Number} How many numbers will be grouped together, - * default: 3. - * @param opts.signed {Boolean|String} Whether negative numbers will have a - * prefix. If String, that string will be used as the prefix. Default: "-" - */ -Amount.prototype.to_human = function (opts) -{ - opts = opts || {}; - - if (!this.is_valid()) return ""; - - // Default options - if ("undefined" === typeof opts.signed) opts.signed = true; - if ("undefined" === typeof opts.group_sep) opts.group_sep = true; - opts.group_width = opts.group_width || 3; - - var order = this._is_native ? consts.xns_precision : -this._offset; - var denominator = consts.bi_10.clone().pow(order); - var int_part = this._value.divide(denominator).toString(10); - var fraction_part = this._value.mod(denominator).toString(10); - - // Add leading zeros to fraction - while (fraction_part.length < order) { - fraction_part = "0" + fraction_part; - } - - int_part = int_part.replace(/^0*/, ''); - fraction_part = fraction_part.replace(/0*$/, ''); - - if (fraction_part.length || !opts.skip_empty_fraction) { - if ("number" === typeof opts.precision) { - fraction_part = fraction_part.slice(0, opts.precision); - } - - if ("number" === typeof opts.min_precision) { - while (fraction_part.length < opts.min_precision) { - fraction_part += "0"; - } - } - } - - if (opts.group_sep) { - if ("string" !== typeof opts.group_sep) { - opts.group_sep = ','; - } - int_part = utils.chunkString(int_part, opts.group_width, true).join(opts.group_sep); - } - - var formatted = ''; - if (opts.signed && this._is_negative) { - if ("string" !== typeof opts.signed) { - opts.signed = '-'; - } - formatted += opts.signed; - } - formatted += int_part.length ? int_part : '0'; - formatted += fraction_part.length ? '.'+fraction_part : ''; - - return formatted; -}; - -Amount.prototype.to_human_full = function (opts) { - opts = opts || {}; - - var a = this.to_human(opts); - var c = this._currency.to_human(); - var i = this._issuer.to_json(opts); - - var o; - - if (this._is_native) - { - o = a + "/" + c; - } - else - { - o = a + "/" + c + "/" + i; - } - - return o; -}; - -Amount.prototype.to_json = function () { - if (this._is_native) { - return this.to_text(); - } - else - { - var amount_json = { - 'value' : this.to_text(), - 'currency' : this._currency.to_json() - }; - if (this._issuer.is_valid()) { - amount_json.issuer = this._issuer.to_json(); - } - return amount_json; - } -}; - -Amount.prototype.to_text_full = function (opts) { - return this._value instanceof BigInteger - ? this._is_native - ? this.to_text() + "/XRP" - : this.to_text() + "/" + this._currency.to_json() + "/" + this._issuer.to_json(opts) - : NaN; -}; - -// For debugging. -Amount.prototype.not_equals_why = function (d, ignore_issuer) { - if ("string" === typeof d) { - return this.not_equals_why(Amount.from_json(d)); - } - - if (this === d) return false; - - if (d instanceof Amount) { - if (!this.is_valid() || !d.is_valid()) return "Invalid amount."; - if (this._is_native !== d._is_native) return "Native mismatch."; - - var type = this._is_native ? "XRP" : "Non-XRP"; - - if (!this._value.equals(d._value) || this._offset !== d._offset) { - return type+" value differs."; - } - - if (this._is_negative !== d._is_negative) return type+" sign differs."; - - if (!this._is_native) { - if (!this._currency.equals(d._currency)) return "Non-XRP currency differs."; - if (!ignore_issuer && !this._issuer.equals(d._issuer)) { - return "Non-XRP issuer differs: " + d._issuer.to_json() + "/" + this._issuer.to_json(); - } - } - return false; - } else return "Wrong constructor."; -}; - -exports.Amount = Amount; - -// DEPRECATED: Include the corresponding files instead. -exports.Currency = Currency; -exports.Seed = Seed; -exports.UInt160 = UInt160; - -// vim:sw=2:sts=2:ts=8:et diff --git a/src/js/base.js b/src/js/base.js deleted file mode 100644 index be2cab483b..0000000000 --- a/src/js/base.js +++ /dev/null @@ -1,140 +0,0 @@ - -var sjcl = require('../../build/sjcl'); -var utils = require('./utils'); -var jsbn = require('./jsbn'); -var extend = require('extend'); - -var BigInteger = jsbn.BigInteger; -var nbi = jsbn.nbi; - -var Base = {}; - -var alphabets = Base.alphabets = { - 'ripple' : "rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz", - 'tipple' : "RPShNAF39wBUDnEGHJKLM4pQrsT7VWXYZ2bcdeCg65jkm8ofqi1tuvaxyz", - 'bitcoin' : "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz" -}; - -extend(Base, { - 'VER_NONE' : 1, - 'VER_NODE_PUBLIC' : 28, - 'VER_NODE_PRIVATE' : 32, - 'VER_ACCOUNT_ID' : 0, - 'VER_ACCOUNT_PUBLIC' : 35, - 'VER_ACCOUNT_PRIVATE' : 34, - 'VER_FAMILY_GENERATOR' : 41, - 'VER_FAMILY_SEED' : 33 -}); - -var sha256 = function (bytes) { - return sjcl.codec.bytes.fromBits(sjcl.hash.sha256.hash(sjcl.codec.bytes.toBits(bytes))); -}; - -var sha256hash = function (bytes) { - return sha256(sha256(bytes)); -}; - -// --> input: big-endian array of bytes. -// <-- string at least as long as input. -Base.encode = function (input, alpha) { - var alphabet = alphabets[alpha || 'ripple']; - var bi_base = new BigInteger(String(alphabet.length)); - var bi_q = nbi(); - var bi_r = nbi(); - var bi_value = new BigInteger(input); - var buffer = []; - - while (bi_value.compareTo(BigInteger.ZERO) > 0) - { - bi_value.divRemTo(bi_base, bi_q, bi_r); - bi_q.copyTo(bi_value); - - buffer.push(alphabet[bi_r.intValue()]); - } - - var i; - - for (i = 0; i != input.length && !input[i]; i += 1) { - buffer.push(alphabet[0]); - } - - return buffer.reverse().join(""); -}; - -// --> input: String -// <-- array of bytes or undefined. -Base.decode = function (input, alpha) { - var alphabet = alphabets[alpha || 'ripple']; - var bi_base = new BigInteger(String(alphabet.length)); - var bi_value = nbi(); - var i; - - for (i = 0; i != input.length && input[i] === alphabet[0]; i += 1) - ; - - for (; i != input.length; i += 1) { - var v = alphabet.indexOf(input[i]); - - if (v < 0) - return undefined; - - var r = nbi(); - - r.fromInt(v); - - bi_value = bi_value.multiply(bi_base).add(r); - } - - // toByteArray: - // - Returns leading zeros! - // - Returns signed bytes! - var bytes = bi_value.toByteArray().map(function (b) { return b ? b < 0 ? 256+b : b : 0; }); - var extra = 0; - - while (extra != bytes.length && !bytes[extra]) - extra += 1; - - if (extra) - bytes = bytes.slice(extra); - - var zeros = 0; - - while (zeros !== input.length && input[zeros] === alphabet[0]) - zeros += 1; - - return [].concat(utils.arraySet(zeros, 0), bytes); -}; - -// --> input: Array -// <-- String -Base.encode_check = function (version, input, alphabet) { - var buffer = [].concat(version, input); - var check = sha256(sha256(buffer)).slice(0, 4); - - return Base.encode([].concat(buffer, check), alphabet); -} - -// --> input : String -// <-- NaN || BigInteger -Base.decode_check = function (version, input, alphabet) { - var buffer = Base.decode(input, alphabet); - - if (!buffer || buffer[0] !== version || buffer.length < 5) - return NaN; - - var computed = sha256hash(buffer.slice(0, -4)).slice(0, 4); - var checksum = buffer.slice(-4); - var i; - - for (i = 0; i != 4; i += 1) - if (computed[i] !== checksum[i]) - return NaN; - - // We'll use the version byte to add a leading zero, this ensures JSBN doesn't - // intrepret the value as a negative number - buffer[0] = 0; - - return new BigInteger(buffer.slice(0, -4), 256); -} - -exports.Base = Base; diff --git a/src/js/binformat.js b/src/js/binformat.js deleted file mode 100644 index b9f9b4d944..0000000000 --- a/src/js/binformat.js +++ /dev/null @@ -1,90 +0,0 @@ -var ST = require("./serializedtypes"); - -var REQUIRED = exports.REQUIRED = 0, - OPTIONAL = exports.OPTIONAL = 1, - DEFAULT = exports.DEFAULT = 2; - -ST.Int16.id = 1; -ST.Int32.id = 2; -ST.Int64.id = 3; -ST.Hash128.id = 4; -ST.Hash256.id = 5; -ST.Amount.id = 6; -ST.VariableLength.id = 7; -ST.Account.id = 8; -ST.Object.id = 14; -ST.Array.id = 15; -ST.Int8.id = 16; -ST.Hash160.id = 17; -ST.PathSet.id = 18; -ST.Vector256.id = 19; - -var base = [ - [ 'TransactionType' , REQUIRED, 2, ST.Int16 ], - [ 'Flags' , OPTIONAL, 2, ST.Int32 ], - [ 'SourceTag' , OPTIONAL, 3, ST.Int32 ], - [ 'Account' , REQUIRED, 1, ST.Account ], - [ 'Sequence' , REQUIRED, 4, ST.Int32 ], - [ 'Fee' , REQUIRED, 8, ST.Amount ], - [ 'OperationLimit' , OPTIONAL, 29, ST.Int32 ], - [ 'SigningPubKey' , REQUIRED, 3, ST.VariableLength ], - [ 'TxnSignature' , OPTIONAL, 4, ST.VariableLength ] -]; - -exports.tx = { - AccountSet: [3].concat(base, [ - [ 'EmailHash' , OPTIONAL, 1, ST.Hash128 ], - [ 'WalletLocator' , OPTIONAL, 7, ST.Hash256 ], - [ 'WalletSize' , OPTIONAL, 12, ST.Int32 ], - [ 'MessageKey' , OPTIONAL, 2, ST.VariableLength ], - [ 'Domain' , OPTIONAL, 7, ST.VariableLength ], - [ 'TransferRate' , OPTIONAL, 11, ST.Int32 ] - ]), - TrustSet: [20].concat(base, [ - [ 'LimitAmount' , OPTIONAL, 3, ST.Amount ], - [ 'QualityIn' , OPTIONAL, 20, ST.Int32 ], - [ 'QualityOut' , OPTIONAL, 21, ST.Int32 ] - ]), - OfferCreate: [7].concat(base, [ - [ 'TakerPays' , REQUIRED, 4, ST.Amount ], - [ 'TakerGets' , REQUIRED, 5, ST.Amount ], - [ 'Expiration' , OPTIONAL, 10, ST.Int32 ] - ]), - OfferCancel: [8].concat(base, [ - [ 'OfferSequence' , REQUIRED, 25, ST.Int32 ] - ]), - SetRegularKey: [5].concat(base, [ - [ 'RegularKey' , REQUIRED, 8, ST.Account ] - ]), - Payment: [0].concat(base, [ - [ 'Destination' , REQUIRED, 3, ST.Account ], - [ 'Amount' , REQUIRED, 1, ST.Amount ], - [ 'SendMax' , OPTIONAL, 9, ST.Amount ], - [ 'Paths' , DEFAULT , 1, ST.PathSet ], - [ 'InvoiceID' , OPTIONAL, 17, ST.Hash256 ], - [ 'DestinationTag' , OPTIONAL, 14, ST.Int32 ] - ]), - Contract: [9].concat(base, [ - [ 'Expiration' , REQUIRED, 10, ST.Int32 ], - [ 'BondAmount' , REQUIRED, 23, ST.Int32 ], - [ 'StampEscrow' , REQUIRED, 22, ST.Int32 ], - [ 'RippleEscrow' , REQUIRED, 17, ST.Amount ], - [ 'CreateCode' , OPTIONAL, 11, ST.VariableLength ], - [ 'FundCode' , OPTIONAL, 8, ST.VariableLength ], - [ 'RemoveCode' , OPTIONAL, 9, ST.VariableLength ], - [ 'ExpireCode' , OPTIONAL, 10, ST.VariableLength ] - ]), - RemoveContract: [10].concat(base, [ - [ 'Target' , REQUIRED, 7, ST.Account ] - ]), - EnableFeature: [100].concat(base, [ - [ 'Feature' , REQUIRED, 19, ST.Hash256 ] - ]), - SetFee: [101].concat(base, [ - [ 'Features' , REQUIRED, 9, ST.Array ], - [ 'BaseFee' , REQUIRED, 5, ST.Int64 ], - [ 'ReferenceFeeUnits' , REQUIRED, 30, ST.Int32 ], - [ 'ReserveBase' , REQUIRED, 31, ST.Int32 ], - [ 'ReserveIncrement' , REQUIRED, 32, ST.Int32 ] - ]) -}; diff --git a/src/js/config.js b/src/js/config.js deleted file mode 100644 index b8095cc667..0000000000 --- a/src/js/config.js +++ /dev/null @@ -1,10 +0,0 @@ -// This object serves as a singleton to store config options - -var extend = require("extend"); - -var config = module.exports = { - load: function (newOpts) { - extend(config, newOpts); - return config; - } -}; diff --git a/src/js/cryptojs b/src/js/cryptojs deleted file mode 160000 index c3c843c513..0000000000 --- a/src/js/cryptojs +++ /dev/null @@ -1 +0,0 @@ -Subproject commit c3c843c5131e00607fd8cad1baf3761d0209663a diff --git a/src/js/currency.js b/src/js/currency.js deleted file mode 100644 index 22bd112fca..0000000000 --- a/src/js/currency.js +++ /dev/null @@ -1,83 +0,0 @@ - -// -// Currency support -// - -// XXX Internal form should be UInt160. -var Currency = function () { - // Internal form: 0 = XRP. 3 letter-code. - // XXX Internal should be 0 or hex with three letter annotation when valid. - - // Json form: - // '', 'XRP', '0': 0 - // 3-letter code: ... - // XXX Should support hex, C++ doesn't currently allow it. - - this._value = NaN; -} - -// Given "USD" return the json. -Currency.json_rewrite = function (j) { - return Currency.from_json(j).to_json(); -}; - -Currency.from_json = function (j) { - if (j instanceof Currency) return j.clone(); - else if ('string' === typeof j) return (new Currency()).parse_json(j); - else return new Currency(); // NaN -}; - -Currency.is_valid = function (j) { - return Currency.from_json(j).is_valid(); -}; - -Currency.prototype.clone = function() { - return this.copyTo(new Currency()); -}; - -// Returns copy. -Currency.prototype.copyTo = function (d) { - d._value = this._value; - - return d; -}; - -Currency.prototype.equals = function (d) { - return ('string' !== typeof this._value && isNaN(this._value)) - || ('string' !== typeof d._value && isNaN(d._value)) ? false : this._value === d._value; -}; - -// this._value = NaN on error. -Currency.prototype.parse_json = function (j) { - if ("" === j || "0" === j || "XRP" === j) { - this._value = 0; - } - else if ('string' != typeof j || 3 !== j.length) { - this._value = NaN; - } - else { - this._value = j; - } - - return this; -}; - -Currency.prototype.is_native = function () { - return !isNaN(this._value) && !this._value; -}; - -Currency.prototype.is_valid = function () { - return 'string' === typeof this._value || !isNaN(this._value); -}; - -Currency.prototype.to_json = function () { - return this._value ? this._value : "XRP"; -}; - -Currency.prototype.to_human = function () { - return this._value ? this._value : "XRP"; -}; - -exports.Currency = Currency; - -// vim:sw=2:sts=2:ts=8:et diff --git a/src/js/index.js b/src/js/index.js deleted file mode 100644 index 139c71cb1f..0000000000 --- a/src/js/index.js +++ /dev/null @@ -1,22 +0,0 @@ -exports.Remote = require('./remote').Remote; -exports.Amount = require('./amount').Amount; -exports.Currency = require('./currency').Currency; -exports.UInt160 = require('./amount').UInt160; -exports.Seed = require('./amount').Seed; -exports.Transaction = require('./transaction').Transaction; -exports.Meta = require('./meta').Meta; - -exports.utils = require('./utils'); - -// Important: We do not guarantee any specific version of SJCL or for any -// specific features to be included. The version and configuration may change at -// any time without warning. -// -// However, for programs that are tied to a specific version of ripple.js like -// the official client, it makes sense to expose the SJCL instance so we don't -// have to include it twice. -exports.sjcl = require('../../build/sjcl'); - -exports.config = require('./config'); - -// vim:sw=2:sts=2:ts=8:et diff --git a/src/js/jsbn.js b/src/js/jsbn.js deleted file mode 100644 index 772ae15fc7..0000000000 --- a/src/js/jsbn.js +++ /dev/null @@ -1,1219 +0,0 @@ -// Derived from Tom Wu's jsbn code. -// -// Changes made for clean up and to package as a node.js module. - -// Copyright (c) 2005-2009 Tom Wu -// All Rights Reserved. -// See "LICENSE" for details. - -// Basic JavaScript BN library - subset useful for RSA encryption. -// Extended JavaScript BN functions, required for RSA private ops. -// Version 1.1: new BigInteger("0", 10) returns "proper" zero -// Version 1.2: square() API, isProbablePrime fix - -// Bits per digit -var dbits; - -// JavaScript engine analysis -var canary = 0xdeadbeefcafe; -var j_lm = ((canary&0xffffff)==0xefcafe); - -// (public) Constructor -var BigInteger = function BigInteger(a,b,c) { - if(a != null) - if("number" == typeof a) this.fromNumber(a,b,c); - else if(b == null && "string" != typeof a) this.fromString(a,256); - else this.fromString(a,b); -}; - -// return new, unset BigInteger -var nbi = function nbi() { return new BigInteger(null); }; - -// am: Compute w_j += (x*this_i), propagate carries, -// c is initial carry, returns final carry. -// c < 3*dvalue, x < 2*dvalue, this_i < dvalue -// We need to select the fastest one that works in this environment. - -// am1: use a single mult and divide to get the high bits, -// max digit bits should be 26 because -// max internal value = 2*dvalue^2-2*dvalue (< 2^53) -function am1(i,x,w,j,c,n) { - while(--n >= 0) { - var v = x*this[i++]+w[j]+c; - c = Math.floor(v/0x4000000); - w[j++] = v&0x3ffffff; - } - return c; -} -// am2 avoids a big mult-and-extract completely. -// Max digit bits should be <= 30 because we do bitwise ops -// on values up to 2*hdvalue^2-hdvalue-1 (< 2^31) -function am2(i,x,w,j,c,n) { - var xl = x&0x7fff, xh = x>>15; - while(--n >= 0) { - var l = this[i]&0x7fff; - var h = this[i++]>>15; - var m = xh*l+h*xl; - l = xl*l+((m&0x7fff)<<15)+w[j]+(c&0x3fffffff); - c = (l>>>30)+(m>>>15)+xh*h+(c>>>30); - w[j++] = l&0x3fffffff; - } - return c; -} -// Alternately, set max digit bits to 28 since some -// browsers slow down when dealing with 32-bit numbers. -function am3(i,x,w,j,c,n) { - var xl = x&0x3fff, xh = x>>14; - while(--n >= 0) { - var l = this[i]&0x3fff; - var h = this[i++]>>14; - var m = xh*l+h*xl; - l = xl*l+((m&0x3fff)<<14)+w[j]+c; - c = (l>>28)+(m>>14)+xh*h; - w[j++] = l&0xfffffff; - } - return c; -} - -if(j_lm && 'undefined' !== typeof navigator && (navigator.appName == "Microsoft Internet Explorer")) { - BigInteger.prototype.am = am2; - dbits = 30; -} -else if(j_lm && 'undefined' !== typeof navigator && (navigator.appName != "Netscape")) { - BigInteger.prototype.am = am1; - dbits = 26; -} -else { // Mozilla/Netscape seems to prefer am3 - BigInteger.prototype.am = am3; - dbits = 28; -} - -BigInteger.prototype.DB = dbits; -BigInteger.prototype.DM = ((1<= 0; --i) r[i] = this[i]; - r.t = this.t; - r.s = this.s; -} - -// (protected) set from integer value x, -DV <= x < DV -function bnpFromInt(x) { - this.t = 1; - this.s = (x<0)?-1:0; - if(x > 0) this[0] = x; - else if(x < -1) this[0] = x+DV; - else this.t = 0; -} - -// return bigint initialized to value -function nbv(i) { var r = nbi(); r.fromInt(i); return r; } - -// (protected) set from string and radix -function bnpFromString(s,b) { - var k; - if(b == 16) k = 4; - else if(b == 8) k = 3; - else if(b == 256) k = 8; // byte array - else if(b == 2) k = 1; - else if(b == 32) k = 5; - else if(b == 4) k = 2; - else { this.fromRadix(s,b); return; } - this.t = 0; - this.s = 0; - var i = s.length, mi = false, sh = 0; - while(--i >= 0) { - var x = (k==8)?s[i]&0xff:intAt(s,i); - if(x < 0) { - if(s.charAt(i) == "-") mi = true; - continue; - } - mi = false; - if(sh == 0) - this[this.t++] = x; - else if(sh+k > this.DB) { - this[this.t-1] |= (x&((1<<(this.DB-sh))-1))<>(this.DB-sh)); - } - else - this[this.t-1] |= x<= this.DB) sh -= this.DB; - } - if(k == 8 && (s[0]&0x80) != 0) { - this.s = -1; - if(sh > 0) this[this.t-1] |= ((1<<(this.DB-sh))-1)< 0 && this[this.t-1] == c) --this.t; -} - -// (public) return string representation in given radix -function bnToString(b) { - if(this.s < 0) return "-"+this.negate().toString(b); - var k; - if(b == 16) k = 4; - else if(b == 8) k = 3; - else if(b == 2) k = 1; - else if(b == 32) k = 5; - else if(b == 4) k = 2; - else return this.toRadix(b); - var km = (1< 0) { - if(p < this.DB && (d = this[i]>>p) > 0) { m = true; r = int2char(d); } - while(i >= 0) { - if(p < k) { - d = (this[i]&((1<>(p+=this.DB-k); - } - else { - d = (this[i]>>(p-=k))&km; - if(p <= 0) { p += this.DB; --i; } - } - if(d > 0) m = true; - if(m) r += int2char(d); - } - } - return m?r:"0"; -} - -// (public) -this -function bnNegate() { var r = nbi(); BigInteger.ZERO.subTo(this,r); return r; } - -// (public) |this| -function bnAbs() { return (this.s<0)?this.negate():this; } - -// (public) return + if this > a, - if this < a, 0 if equal -function bnCompareTo(a) { - var r = this.s-a.s; - if(r != 0) return r; - var i = this.t; - r = i-a.t; - if(r != 0) return (this.s<0)?-r:r; - while(--i >= 0) if((r=this[i]-a[i]) != 0) return r; - return 0; -} - -// returns bit length of the integer x -function nbits(x) { - var r = 1, t; - if((t=x>>>16) != 0) { x = t; r += 16; } - if((t=x>>8) != 0) { x = t; r += 8; } - if((t=x>>4) != 0) { x = t; r += 4; } - if((t=x>>2) != 0) { x = t; r += 2; } - if((t=x>>1) != 0) { x = t; r += 1; } - return r; -} - -// (public) return the number of bits in "this" -function bnBitLength() { - if(this.t <= 0) return 0; - return this.DB*(this.t-1)+nbits(this[this.t-1]^(this.s&this.DM)); -} - -// (protected) r = this << n*DB -function bnpDLShiftTo(n,r) { - var i; - for(i = this.t-1; i >= 0; --i) r[i+n] = this[i]; - for(i = n-1; i >= 0; --i) r[i] = 0; - r.t = this.t+n; - r.s = this.s; -} - -// (protected) r = this >> n*DB -function bnpDRShiftTo(n,r) { - for(var i = n; i < this.t; ++i) r[i-n] = this[i]; - r.t = Math.max(this.t-n,0); - r.s = this.s; -} - -// (protected) r = this << n -function bnpLShiftTo(n,r) { - var bs = n%this.DB; - var cbs = this.DB-bs; - var bm = (1<= 0; --i) { - r[i+ds+1] = (this[i]>>cbs)|c; - c = (this[i]&bm)<= 0; --i) r[i] = 0; - r[ds] = c; - r.t = this.t+ds+1; - r.s = this.s; - r.clamp(); -} - -// (protected) r = this >> n -function bnpRShiftTo(n,r) { - r.s = this.s; - var ds = Math.floor(n/this.DB); - if(ds >= this.t) { r.t = 0; return; } - var bs = n%this.DB; - var cbs = this.DB-bs; - var bm = (1<>bs; - for(var i = ds+1; i < this.t; ++i) { - r[i-ds-1] |= (this[i]&bm)<>bs; - } - if(bs > 0) r[this.t-ds-1] |= (this.s&bm)<>= this.DB; - } - if(a.t < this.t) { - c -= a.s; - while(i < this.t) { - c += this[i]; - r[i++] = c&this.DM; - c >>= this.DB; - } - c += this.s; - } - else { - c += this.s; - while(i < a.t) { - c -= a[i]; - r[i++] = c&this.DM; - c >>= this.DB; - } - c -= a.s; - } - r.s = (c<0)?-1:0; - if(c < -1) r[i++] = this.DV+c; - else if(c > 0) r[i++] = c; - r.t = i; - r.clamp(); -} - -// (protected) r = this * a, r != this,a (HAC 14.12) -// "this" should be the larger one if appropriate. -function bnpMultiplyTo(a,r) { - var x = this.abs(), y = a.abs(); - var i = x.t; - r.t = i+y.t; - while(--i >= 0) r[i] = 0; - for(i = 0; i < y.t; ++i) r[i+x.t] = x.am(0,y[i],r,i,0,x.t); - r.s = 0; - r.clamp(); - if(this.s != a.s) BigInteger.ZERO.subTo(r,r); -} - -// (protected) r = this^2, r != this (HAC 14.16) -function bnpSquareTo(r) { - var x = this.abs(); - var i = r.t = 2*x.t; - while(--i >= 0) r[i] = 0; - for(i = 0; i < x.t-1; ++i) { - var c = x.am(i,x[i],r,2*i,0,1); - if((r[i+x.t]+=x.am(i+1,2*x[i],r,2*i+1,c,x.t-i-1)) >= x.DV) { - r[i+x.t] -= x.DV; - r[i+x.t+1] = 1; - } - } - if(r.t > 0) r[r.t-1] += x.am(i,x[i],r,2*i,0,1); - r.s = 0; - r.clamp(); -} - -// (protected) divide this by m, quotient and remainder to q, r (HAC 14.20) -// r != q, this != m. q or r may be null. -function bnpDivRemTo(m,q,r) { - var pm = m.abs(); - if(pm.t <= 0) return; - var pt = this.abs(); - if(pt.t < pm.t) { - if(q != null) q.fromInt(0); - if(r != null) this.copyTo(r); - return; - } - if(r == null) r = nbi(); - var y = nbi(), ts = this.s, ms = m.s; - var nsh = this.DB-nbits(pm[pm.t-1]); // normalize modulus - if(nsh > 0) { pm.lShiftTo(nsh,y); pt.lShiftTo(nsh,r); } - else { pm.copyTo(y); pt.copyTo(r); } - var ys = y.t; - var y0 = y[ys-1]; - if(y0 == 0) return; - var yt = y0*(1<1)?y[ys-2]>>this.F2:0); - var d1 = this.FV/yt, d2 = (1<= 0) { - r[r.t++] = 1; - r.subTo(t,r); - } - BigInteger.ONE.dlShiftTo(ys,t); - t.subTo(y,y); // "negative" y so we can replace sub with am later - while(y.t < ys) y[y.t++] = 0; - while(--j >= 0) { - // Estimate quotient digit - var qd = (r[--i]==y0)?this.DM:Math.floor(r[i]*d1+(r[i-1]+e)*d2); - if((r[i]+=y.am(0,qd,r,j,0,ys)) < qd) { // Try it out - y.dlShiftTo(j,t); - r.subTo(t,r); - while(r[i] < --qd) r.subTo(t,r); - } - } - if(q != null) { - r.drShiftTo(ys,q); - if(ts != ms) BigInteger.ZERO.subTo(q,q); - } - r.t = ys; - r.clamp(); - if(nsh > 0) r.rShiftTo(nsh,r); // Denormalize remainder - if(ts < 0) BigInteger.ZERO.subTo(r,r); -} - -// (public) this mod a -function bnMod(a) { - var r = nbi(); - this.abs().divRemTo(a,null,r); - if(this.s < 0 && r.compareTo(BigInteger.ZERO) > 0) a.subTo(r,r); - return r; -} - -// Modular reduction using "classic" algorithm -function Classic(m) { this.m = m; } -function cConvert(x) { - if(x.s < 0 || x.compareTo(this.m) >= 0) return x.mod(this.m); - else return x; -} -function cRevert(x) { return x; } -function cReduce(x) { x.divRemTo(this.m,null,x); } -function cMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); } -function cSqrTo(x,r) { x.squareTo(r); this.reduce(r); } - -Classic.prototype.convert = cConvert; -Classic.prototype.revert = cRevert; -Classic.prototype.reduce = cReduce; -Classic.prototype.mulTo = cMulTo; -Classic.prototype.sqrTo = cSqrTo; - -// (protected) return "-1/this % 2^DB"; useful for Mont. reduction -// justification: -// xy == 1 (mod m) -// xy = 1+km -// xy(2-xy) = (1+km)(1-km) -// x[y(2-xy)] = 1-k^2m^2 -// x[y(2-xy)] == 1 (mod m^2) -// if y is 1/x mod m, then y(2-xy) is 1/x mod m^2 -// should reduce x and y(2-xy) by m^2 at each step to keep size bounded. -// JS multiply "overflows" differently from C/C++, so care is needed here. -function bnpInvDigit() { - if(this.t < 1) return 0; - var x = this[0]; - if((x&1) == 0) return 0; - var y = x&3; // y == 1/x mod 2^2 - y = (y*(2-(x&0xf)*y))&0xf; // y == 1/x mod 2^4 - y = (y*(2-(x&0xff)*y))&0xff; // y == 1/x mod 2^8 - y = (y*(2-(((x&0xffff)*y)&0xffff)))&0xffff; // y == 1/x mod 2^16 - // last step - calculate inverse mod DV directly; - // assumes 16 < DB <= 32 and assumes ability to handle 48-bit ints - y = (y*(2-x*y%this.DV))%this.DV; // y == 1/x mod 2^dbits - // we really want the negative inverse, and -DV < y < DV - return (y>0)?this.DV-y:-y; -} - -// Montgomery reduction -function Montgomery(m) { - this.m = m; - this.mp = m.invDigit(); - this.mpl = this.mp&0x7fff; - this.mph = this.mp>>15; - this.um = (1<<(m.DB-15))-1; - this.mt2 = 2*m.t; -} - -// xR mod m -function montConvert(x) { - var r = nbi(); - x.abs().dlShiftTo(this.m.t,r); - r.divRemTo(this.m,null,r); - if(x.s < 0 && r.compareTo(BigInteger.ZERO) > 0) this.m.subTo(r,r); - return r; -} - -// x/R mod m -function montRevert(x) { - var r = nbi(); - x.copyTo(r); - this.reduce(r); - return r; -} - -// x = x/R mod m (HAC 14.32) -function montReduce(x) { - while(x.t <= this.mt2) // pad x so am has enough room later - x[x.t++] = 0; - for(var i = 0; i < this.m.t; ++i) { - // faster way of calculating u0 = x[i]*mp mod DV - var j = x[i]&0x7fff; - var u0 = (j*this.mpl+(((j*this.mph+(x[i]>>15)*this.mpl)&this.um)<<15))&x.DM; - // use am to combine the multiply-shift-add into one call - j = i+this.m.t; - x[j] += this.m.am(0,u0,x,i,0,this.m.t); - // propagate carry - while(x[j] >= x.DV) { x[j] -= x.DV; x[++j]++; } - } - x.clamp(); - x.drShiftTo(this.m.t,x); - if(x.compareTo(this.m) >= 0) x.subTo(this.m,x); -} - -// r = "x^2/R mod m"; x != r -function montSqrTo(x,r) { x.squareTo(r); this.reduce(r); } - -// r = "xy/R mod m"; x,y != r -function montMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); } - -Montgomery.prototype.convert = montConvert; -Montgomery.prototype.revert = montRevert; -Montgomery.prototype.reduce = montReduce; -Montgomery.prototype.mulTo = montMulTo; -Montgomery.prototype.sqrTo = montSqrTo; - -// (protected) true iff this is even -function bnpIsEven() { return ((this.t>0)?(this[0]&1):this.s) == 0; } - -// (protected) this^e, e < 2^32, doing sqr and mul with "r" (HAC 14.79) -function bnpExp(e,z) { - if(e > 0xffffffff || e < 1) return BigInteger.ONE; - var r = nbi(), r2 = nbi(), g = z.convert(this), i = nbits(e)-1; - g.copyTo(r); - while(--i >= 0) { - z.sqrTo(r,r2); - if((e&(1< 0) z.mulTo(r2,g,r); - else { var t = r; r = r2; r2 = t; } - } - return z.revert(r); -} - -// (public) this^e % m, 0 <= e < 2^32 -function bnModPowInt(e,m) { - var z; - if(e < 256 || m.isEven()) z = new Classic(m); else z = new Montgomery(m); - return this.exp(e,z); -} - -// (public) -function bnClone() { var r = nbi(); this.copyTo(r); return r; } - -// (public) return value as integer -function bnIntValue() { - if(this.s < 0) { - if(this.t == 1) return this[0]-this.DV; - else if(this.t == 0) return -1; - } - else if(this.t == 1) return this[0]; - else if(this.t == 0) return 0; - // assumes 16 < DB < 32 - return ((this[1]&((1<<(32-this.DB))-1))<>24; } - -// (public) return value as short (assumes DB>=16) -function bnShortValue() { return (this.t==0)?this.s:(this[0]<<16)>>16; } - -// (protected) return x s.t. r^x < DV -function bnpChunkSize(r) { return Math.floor(Math.LN2*this.DB/Math.log(r)); } - -// (public) 0 if this == 0, 1 if this > 0 -function bnSigNum() { - if(this.s < 0) return -1; - else if(this.t <= 0 || (this.t == 1 && this[0] <= 0)) return 0; - else return 1; -} - -// (protected) convert to radix string -function bnpToRadix(b) { - if(b == null) b = 10; - if(this.signum() == 0 || b < 2 || b > 36) return "0"; - var cs = this.chunkSize(b); - var a = Math.pow(b,cs); - var d = nbv(a), y = nbi(), z = nbi(), r = ""; - this.divRemTo(d,y,z); - while(y.signum() > 0) { - r = (a+z.intValue()).toString(b).substr(1) + r; - y.divRemTo(d,y,z); - } - return z.intValue().toString(b) + r; -} - -// (protected) convert from radix string -function bnpFromRadix(s,b) { - this.fromInt(0); - if(b == null) b = 10; - var cs = this.chunkSize(b); - var d = Math.pow(b,cs), mi = false, j = 0, w = 0; - for(var i = 0; i < s.length; ++i) { - var x = intAt(s,i); - if(x < 0) { - if(s.charAt(i) == "-" && this.signum() == 0) mi = true; - continue; - } - w = b*w+x; - if(++j >= cs) { - this.dMultiply(d); - this.dAddOffset(w,0); - j = 0; - w = 0; - } - } - if(j > 0) { - this.dMultiply(Math.pow(b,j)); - this.dAddOffset(w,0); - } - if(mi) BigInteger.ZERO.subTo(this,this); -} - -// (protected) alternate constructor -function bnpFromNumber(a,b,c) { - if("number" == typeof b) { - // new BigInteger(int,int,RNG) - if(a < 2) this.fromInt(1); - else { - this.fromNumber(a,c); - if(!this.testBit(a-1)) // force MSB set - this.bitwiseTo(BigInteger.ONE.shiftLeft(a-1),op_or,this); - if(this.isEven()) this.dAddOffset(1,0); // force odd - while(!this.isProbablePrime(b)) { - this.dAddOffset(2,0); - if(this.bitLength() > a) this.subTo(BigInteger.ONE.shiftLeft(a-1),this); - } - } - } - else { - // new BigInteger(int,RNG) - var x = new Array(), t = a&7; - x.length = (a>>3)+1; - b.nextBytes(x); - if(t > 0) x[0] &= ((1< 0) { - if(p < this.DB && (d = this[i]>>p) != (this.s&this.DM)>>p) - r[k++] = d|(this.s<<(this.DB-p)); - while(i >= 0) { - if(p < 8) { - d = (this[i]&((1<>(p+=this.DB-8); - } - else { - d = (this[i]>>(p-=8))&0xff; - if(p <= 0) { p += this.DB; --i; } - } - if((d&0x80) != 0) d |= -256; - if(k == 0 && (this.s&0x80) != (d&0x80)) ++k; - if(k > 0 || d != this.s) r[k++] = d; - } - } - return r; -} - -function bnEquals(a) { return(this.compareTo(a)==0); } -function bnMin(a) { return(this.compareTo(a)<0)?this:a; } -function bnMax(a) { return(this.compareTo(a)>0)?this:a; } - -// (protected) r = this op a (bitwise) -function bnpBitwiseTo(a,op,r) { - var i, f, m = Math.min(a.t,this.t); - for(i = 0; i < m; ++i) r[i] = op(this[i],a[i]); - if(a.t < this.t) { - f = a.s&this.DM; - for(i = m; i < this.t; ++i) r[i] = op(this[i],f); - r.t = this.t; - } - else { - f = this.s&this.DM; - for(i = m; i < a.t; ++i) r[i] = op(f,a[i]); - r.t = a.t; - } - r.s = op(this.s,a.s); - r.clamp(); -} - -// (public) this & a -function op_and(x,y) { return x&y; } -function bnAnd(a) { var r = nbi(); this.bitwiseTo(a,op_and,r); return r; } - -// (public) this | a -function op_or(x,y) { return x|y; } -function bnOr(a) { var r = nbi(); this.bitwiseTo(a,op_or,r); return r; } - -// (public) this ^ a -function op_xor(x,y) { return x^y; } -function bnXor(a) { var r = nbi(); this.bitwiseTo(a,op_xor,r); return r; } - -// (public) this & ~a -function op_andnot(x,y) { return x&~y; } -function bnAndNot(a) { var r = nbi(); this.bitwiseTo(a,op_andnot,r); return r; } - -// (public) ~this -function bnNot() { - var r = nbi(); - for(var i = 0; i < this.t; ++i) r[i] = this.DM&~this[i]; - r.t = this.t; - r.s = ~this.s; - return r; -} - -// (public) this << n -function bnShiftLeft(n) { - var r = nbi(); - if(n < 0) this.rShiftTo(-n,r); else this.lShiftTo(n,r); - return r; -} - -// (public) this >> n -function bnShiftRight(n) { - var r = nbi(); - if(n < 0) this.lShiftTo(-n,r); else this.rShiftTo(n,r); - return r; -} - -// return index of lowest 1-bit in x, x < 2^31 -function lbit(x) { - if(x == 0) return -1; - var r = 0; - if((x&0xffff) == 0) { x >>= 16; r += 16; } - if((x&0xff) == 0) { x >>= 8; r += 8; } - if((x&0xf) == 0) { x >>= 4; r += 4; } - if((x&3) == 0) { x >>= 2; r += 2; } - if((x&1) == 0) ++r; - return r; -} - -// (public) returns index of lowest 1-bit (or -1 if none) -function bnGetLowestSetBit() { - for(var i = 0; i < this.t; ++i) - if(this[i] != 0) return i*this.DB+lbit(this[i]); - if(this.s < 0) return this.t*this.DB; - return -1; -} - -// return number of 1 bits in x -function cbit(x) { - var r = 0; - while(x != 0) { x &= x-1; ++r; } - return r; -} - -// (public) return number of set bits -function bnBitCount() { - var r = 0, x = this.s&this.DM; - for(var i = 0; i < this.t; ++i) r += cbit(this[i]^x); - return r; -} - -// (public) true iff nth bit is set -function bnTestBit(n) { - var j = Math.floor(n/this.DB); - if(j >= this.t) return(this.s!=0); - return((this[j]&(1<<(n%this.DB)))!=0); -} - -// (protected) this op (1<>= this.DB; - } - if(a.t < this.t) { - c += a.s; - while(i < this.t) { - c += this[i]; - r[i++] = c&this.DM; - c >>= this.DB; - } - c += this.s; - } - else { - c += this.s; - while(i < a.t) { - c += a[i]; - r[i++] = c&this.DM; - c >>= this.DB; - } - c += a.s; - } - r.s = (c<0)?-1:0; - if(c > 0) r[i++] = c; - else if(c < -1) r[i++] = this.DV+c; - r.t = i; - r.clamp(); -} - -// (public) this + a -function bnAdd(a) { var r = nbi(); this.addTo(a,r); return r; } - -// (public) this - a -function bnSubtract(a) { var r = nbi(); this.subTo(a,r); return r; } - -// (public) this * a -function bnMultiply(a) { var r = nbi(); this.multiplyTo(a,r); return r; } - -// (public) this^2 -function bnSquare() { var r = nbi(); this.squareTo(r); return r; } - -// (public) this / a -function bnDivide(a) { var r = nbi(); this.divRemTo(a,r,null); return r; } - -// (public) this % a -function bnRemainder(a) { var r = nbi(); this.divRemTo(a,null,r); return r; } - -// (public) [this/a,this%a] -function bnDivideAndRemainder(a) { - var q = nbi(), r = nbi(); - this.divRemTo(a,q,r); - return new Array(q,r); -} - -// (protected) this *= n, this >= 0, 1 < n < DV -function bnpDMultiply(n) { - this[this.t] = this.am(0,n-1,this,0,0,this.t); - ++this.t; - this.clamp(); -} - -// (protected) this += n << w words, this >= 0 -function bnpDAddOffset(n,w) { - if(n == 0) return; - while(this.t <= w) this[this.t++] = 0; - this[w] += n; - while(this[w] >= this.DV) { - this[w] -= this.DV; - if(++w >= this.t) this[this.t++] = 0; - ++this[w]; - } -} - -// A "null" reducer -function NullExp() {} -function nNop(x) { return x; } -function nMulTo(x,y,r) { x.multiplyTo(y,r); } -function nSqrTo(x,r) { x.squareTo(r); } - -NullExp.prototype.convert = nNop; -NullExp.prototype.revert = nNop; -NullExp.prototype.mulTo = nMulTo; -NullExp.prototype.sqrTo = nSqrTo; - -// (public) this^e -function bnPow(e) { return this.exp(e,new NullExp()); } - -// (protected) r = lower n words of "this * a", a.t <= n -// "this" should be the larger one if appropriate. -function bnpMultiplyLowerTo(a,n,r) { - var i = Math.min(this.t+a.t,n); - r.s = 0; // assumes a,this >= 0 - r.t = i; - while(i > 0) r[--i] = 0; - var j; - for(j = r.t-this.t; i < j; ++i) r[i+this.t] = this.am(0,a[i],r,i,0,this.t); - for(j = Math.min(a.t,n); i < j; ++i) this.am(0,a[i],r,i,0,n-i); - r.clamp(); -} - -// (protected) r = "this * a" without lower n words, n > 0 -// "this" should be the larger one if appropriate. -function bnpMultiplyUpperTo(a,n,r) { - --n; - var i = r.t = this.t+a.t-n; - r.s = 0; // assumes a,this >= 0 - while(--i >= 0) r[i] = 0; - for(i = Math.max(n-this.t,0); i < a.t; ++i) - r[this.t+i-n] = this.am(n-i,a[i],r,0,0,this.t+i-n); - r.clamp(); - r.drShiftTo(1,r); -} - -// Barrett modular reduction -function Barrett(m) { - // setup Barrett - this.r2 = nbi(); - this.q3 = nbi(); - BigInteger.ONE.dlShiftTo(2*m.t,this.r2); - this.mu = this.r2.divide(m); - this.m = m; -} - -function barrettConvert(x) { - if(x.s < 0 || x.t > 2*this.m.t) return x.mod(this.m); - else if(x.compareTo(this.m) < 0) return x; - else { var r = nbi(); x.copyTo(r); this.reduce(r); return r; } -} - -function barrettRevert(x) { return x; } - -// x = x mod m (HAC 14.42) -function barrettReduce(x) { - x.drShiftTo(this.m.t-1,this.r2); - if(x.t > this.m.t+1) { x.t = this.m.t+1; x.clamp(); } - this.mu.multiplyUpperTo(this.r2,this.m.t+1,this.q3); - this.m.multiplyLowerTo(this.q3,this.m.t+1,this.r2); - while(x.compareTo(this.r2) < 0) x.dAddOffset(1,this.m.t+1); - x.subTo(this.r2,x); - while(x.compareTo(this.m) >= 0) x.subTo(this.m,x); -} - -// r = x^2 mod m; x != r -function barrettSqrTo(x,r) { x.squareTo(r); this.reduce(r); } - -// r = x*y mod m; x,y != r -function barrettMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); } - -Barrett.prototype.convert = barrettConvert; -Barrett.prototype.revert = barrettRevert; -Barrett.prototype.reduce = barrettReduce; -Barrett.prototype.mulTo = barrettMulTo; -Barrett.prototype.sqrTo = barrettSqrTo; - -// (public) this^e % m (HAC 14.85) -function bnModPow(e,m) { - var i = e.bitLength(), k, r = nbv(1), z; - if(i <= 0) return r; - else if(i < 18) k = 1; - else if(i < 48) k = 3; - else if(i < 144) k = 4; - else if(i < 768) k = 5; - else k = 6; - if(i < 8) - z = new Classic(m); - else if(m.isEven()) - z = new Barrett(m); - else - z = new Montgomery(m); - - // precomputation - var g = new Array(), n = 3, k1 = k-1, km = (1< 1) { - var g2 = nbi(); - z.sqrTo(g[1],g2); - while(n <= km) { - g[n] = nbi(); - z.mulTo(g2,g[n-2],g[n]); - n += 2; - } - } - - var j = e.t-1, w, is1 = true, r2 = nbi(), t; - i = nbits(e[j])-1; - while(j >= 0) { - if(i >= k1) w = (e[j]>>(i-k1))&km; - else { - w = (e[j]&((1<<(i+1))-1))<<(k1-i); - if(j > 0) w |= e[j-1]>>(this.DB+i-k1); - } - - n = k; - while((w&1) == 0) { w >>= 1; --n; } - if((i -= n) < 0) { i += this.DB; --j; } - if(is1) { // ret == 1, don't bother squaring or multiplying it - g[w].copyTo(r); - is1 = false; - } - else { - while(n > 1) { z.sqrTo(r,r2); z.sqrTo(r2,r); n -= 2; } - if(n > 0) z.sqrTo(r,r2); else { t = r; r = r2; r2 = t; } - z.mulTo(r2,g[w],r); - } - - while(j >= 0 && (e[j]&(1< 0) { - x.rShiftTo(g,x); - y.rShiftTo(g,y); - } - while(x.signum() > 0) { - if((i = x.getLowestSetBit()) > 0) x.rShiftTo(i,x); - if((i = y.getLowestSetBit()) > 0) y.rShiftTo(i,y); - if(x.compareTo(y) >= 0) { - x.subTo(y,x); - x.rShiftTo(1,x); - } - else { - y.subTo(x,y); - y.rShiftTo(1,y); - } - } - if(g > 0) y.lShiftTo(g,y); - return y; -} - -// (protected) this % n, n < 2^26 -function bnpModInt(n) { - if(n <= 0) return 0; - var d = this.DV%n, r = (this.s<0)?n-1:0; - if(this.t > 0) - if(d == 0) r = this[0]%n; - else for(var i = this.t-1; i >= 0; --i) r = (d*r+this[i])%n; - return r; -} - -// (public) 1/this % m (HAC 14.61) -function bnModInverse(m) { - var ac = m.isEven(); - if((this.isEven() && ac) || m.signum() == 0) return BigInteger.ZERO; - var u = m.clone(), v = this.clone(); - var a = nbv(1), b = nbv(0), c = nbv(0), d = nbv(1); - while(u.signum() != 0) { - while(u.isEven()) { - u.rShiftTo(1,u); - if(ac) { - if(!a.isEven() || !b.isEven()) { a.addTo(this,a); b.subTo(m,b); } - a.rShiftTo(1,a); - } - else if(!b.isEven()) b.subTo(m,b); - b.rShiftTo(1,b); - } - while(v.isEven()) { - v.rShiftTo(1,v); - if(ac) { - if(!c.isEven() || !d.isEven()) { c.addTo(this,c); d.subTo(m,d); } - c.rShiftTo(1,c); - } - else if(!d.isEven()) d.subTo(m,d); - d.rShiftTo(1,d); - } - if(u.compareTo(v) >= 0) { - u.subTo(v,u); - if(ac) a.subTo(c,a); - b.subTo(d,b); - } - else { - v.subTo(u,v); - if(ac) c.subTo(a,c); - d.subTo(b,d); - } - } - if(v.compareTo(BigInteger.ONE) != 0) return BigInteger.ZERO; - if(d.compareTo(m) >= 0) return d.subtract(m); - if(d.signum() < 0) d.addTo(m,d); else return d; - if(d.signum() < 0) return d.add(m); else return d; -} - -var lowprimes = [2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509,521,523,541,547,557,563,569,571,577,587,593,599,601,607,613,617,619,631,641,643,647,653,659,661,673,677,683,691,701,709,719,727,733,739,743,751,757,761,769,773,787,797,809,811,821,823,827,829,839,853,857,859,863,877,881,883,887,907,911,919,929,937,941,947,953,967,971,977,983,991,997]; -var lplim = (1<<26)/lowprimes[lowprimes.length-1]; - -// (public) test primality with certainty >= 1-.5^t -function bnIsProbablePrime(t) { - var i, x = this.abs(); - if(x.t == 1 && x[0] <= lowprimes[lowprimes.length-1]) { - for(i = 0; i < lowprimes.length; ++i) - if(x[0] == lowprimes[i]) return true; - return false; - } - if(x.isEven()) return false; - i = 1; - while(i < lowprimes.length) { - var m = lowprimes[i], j = i+1; - while(j < lowprimes.length && m < lplim) m *= lowprimes[j++]; - m = x.modInt(m); - while(i < j) if(m%lowprimes[i++] == 0) return false; - } - return x.millerRabin(t); -} - -// (protected) true if probably prime (HAC 4.24, Miller-Rabin) -function bnpMillerRabin(t) { - var n1 = this.subtract(BigInteger.ONE); - var k = n1.getLowestSetBit(); - if(k <= 0) return false; - var r = n1.shiftRight(k); - t = (t+1)>>1; - if(t > lowprimes.length) t = lowprimes.length; - var a = nbi(); - for(var i = 0; i < t; ++i) { - //Pick bases at random, instead of starting at 2 - a.fromInt(lowprimes[Math.floor(Math.random()*lowprimes.length)]); - var y = a.modPow(r,this); - if(y.compareTo(BigInteger.ONE) != 0 && y.compareTo(n1) != 0) { - var j = 1; - while(j++ < k && y.compareTo(n1) != 0) { - y = y.modPowInt(2,this); - if(y.compareTo(BigInteger.ONE) == 0) return false; - } - if(y.compareTo(n1) != 0) return false; - } - } - return true; -} - -// protected -BigInteger.prototype.chunkSize = bnpChunkSize; -BigInteger.prototype.toRadix = bnpToRadix; -BigInteger.prototype.fromRadix = bnpFromRadix; -BigInteger.prototype.fromNumber = bnpFromNumber; -BigInteger.prototype.bitwiseTo = bnpBitwiseTo; -BigInteger.prototype.changeBit = bnpChangeBit; -BigInteger.prototype.addTo = bnpAddTo; -BigInteger.prototype.dMultiply = bnpDMultiply; -BigInteger.prototype.dAddOffset = bnpDAddOffset; -BigInteger.prototype.multiplyLowerTo = bnpMultiplyLowerTo; -BigInteger.prototype.multiplyUpperTo = bnpMultiplyUpperTo; -BigInteger.prototype.modInt = bnpModInt; -BigInteger.prototype.millerRabin = bnpMillerRabin; - -// public -BigInteger.prototype.clone = bnClone; -BigInteger.prototype.intValue = bnIntValue; -BigInteger.prototype.byteValue = bnByteValue; -BigInteger.prototype.shortValue = bnShortValue; -BigInteger.prototype.signum = bnSigNum; -BigInteger.prototype.toByteArray = bnToByteArray; -BigInteger.prototype.equals = bnEquals; -BigInteger.prototype.min = bnMin; -BigInteger.prototype.max = bnMax; -BigInteger.prototype.and = bnAnd; -BigInteger.prototype.or = bnOr; -BigInteger.prototype.xor = bnXor; -BigInteger.prototype.andNot = bnAndNot; -BigInteger.prototype.not = bnNot; -BigInteger.prototype.shiftLeft = bnShiftLeft; -BigInteger.prototype.shiftRight = bnShiftRight; -BigInteger.prototype.getLowestSetBit = bnGetLowestSetBit; -BigInteger.prototype.bitCount = bnBitCount; -BigInteger.prototype.testBit = bnTestBit; -BigInteger.prototype.setBit = bnSetBit; -BigInteger.prototype.clearBit = bnClearBit; -BigInteger.prototype.flipBit = bnFlipBit; -BigInteger.prototype.add = bnAdd; -BigInteger.prototype.subtract = bnSubtract; -BigInteger.prototype.multiply = bnMultiply; -BigInteger.prototype.divide = bnDivide; -BigInteger.prototype.remainder = bnRemainder; -BigInteger.prototype.divideAndRemainder = bnDivideAndRemainder; -BigInteger.prototype.modPow = bnModPow; -BigInteger.prototype.modInverse = bnModInverse; -BigInteger.prototype.pow = bnPow; -BigInteger.prototype.gcd = bnGCD; -BigInteger.prototype.isProbablePrime = bnIsProbablePrime; - -// JSBN-specific extension -BigInteger.prototype.square = bnSquare; - -// BigInteger interfaces not implemented in jsbn: - -// BigInteger(int signum, byte[] magnitude) -// double doubleValue() -// float floatValue() -// int hashCode() -// long longValue() -// static BigInteger valueOf(long val) -// protected -BigInteger.prototype.copyTo = bnpCopyTo; -BigInteger.prototype.fromInt = bnpFromInt; -BigInteger.prototype.fromString = bnpFromString; -BigInteger.prototype.clamp = bnpClamp; -BigInteger.prototype.dlShiftTo = bnpDLShiftTo; -BigInteger.prototype.drShiftTo = bnpDRShiftTo; -BigInteger.prototype.lShiftTo = bnpLShiftTo; -BigInteger.prototype.rShiftTo = bnpRShiftTo; -BigInteger.prototype.subTo = bnpSubTo; -BigInteger.prototype.multiplyTo = bnpMultiplyTo; -BigInteger.prototype.squareTo = bnpSquareTo; -BigInteger.prototype.divRemTo = bnpDivRemTo; -BigInteger.prototype.invDigit = bnpInvDigit; -BigInteger.prototype.isEven = bnpIsEven; -BigInteger.prototype.exp = bnpExp; - -// public -BigInteger.prototype.toString = bnToString; -BigInteger.prototype.negate = bnNegate; -BigInteger.prototype.abs = bnAbs; -BigInteger.prototype.compareTo = bnCompareTo; -BigInteger.prototype.bitLength = bnBitLength; -BigInteger.prototype.mod = bnMod; -BigInteger.prototype.modPowInt = bnModPowInt; - -// "constants" -BigInteger.ZERO = nbv(0); -BigInteger.ONE = nbv(1); - -exports.nbi = nbi; -exports.BigInteger = BigInteger; - -// vim:sw=2:sts=2:ts=8:et diff --git a/src/js/keypair.js b/src/js/keypair.js deleted file mode 100644 index 7c6a559de7..0000000000 --- a/src/js/keypair.js +++ /dev/null @@ -1,67 +0,0 @@ -var sjcl = require('../../build/sjcl'); - -var UInt256 = require('./uint256').UInt256; - -var KeyPair = function () -{ - this._curve = sjcl.ecc.curves['c256']; - this._secret = null; - this._pubkey = null; -}; - -KeyPair.from_bn_secret = function (j) -{ - if (j instanceof this) { - return j.clone(); - } else { - return (new this()).parse_bn_secret(j); - } -}; - -KeyPair.prototype.parse_bn_secret = function (j) -{ - this._secret = new sjcl.ecc.ecdsa.secretKey(sjcl.ecc.curves['c256'], j); - return this; -}; - -/** - * Returns public key as sjcl public key. - * - * @private - */ -KeyPair.prototype._pub = function () -{ - var curve = this._curve; - - if (!this._pubkey && this._secret) { - var exponent = this._secret._exponent; - this._pubkey = new sjcl.ecc.ecdsa.publicKey(curve, curve.G.mult(exponent)); - } - - return this._pubkey; -}; - -/** - * Returns public key as hex. - * - * Key will be returned as a compressed pubkey - 33 bytes converted to hex. - */ -KeyPair.prototype.to_hex_pub = function () -{ - var pub = this._pub(); - if (!pub) return null; - - var point = pub._point, y_even = point.y.mod(2).equals(0); - return sjcl.codec.hex.fromBits(sjcl.bitArray.concat( - [sjcl.bitArray.partial(8, y_even ? 0x02 : 0x03)], - point.x.toBits(this._curve.r.bitLength()) - )).toUpperCase(); -}; - -KeyPair.prototype.sign = function (hash) -{ - hash = UInt256.from_json(hash); - return this._secret.signDER(hash.to_bits(), 0); -}; - -exports.KeyPair = KeyPair; diff --git a/src/js/meta.js b/src/js/meta.js deleted file mode 100644 index 23ba815215..0000000000 --- a/src/js/meta.js +++ /dev/null @@ -1,137 +0,0 @@ -var extend = require('extend'); -var utils = require('./utils'); -var UInt160 = require('./uint160').UInt160; -var Amount = require('./amount').Amount; - -/** - * Meta data processing facility. - */ -var Meta = function (raw_data) -{ - this.nodes = []; - - for (var i = 0, l = raw_data.AffectedNodes.length; i < l; i++) { - var an = raw_data.AffectedNodes[i], - result = {}; - - ["CreatedNode", "ModifiedNode", "DeletedNode"].forEach(function (x) { - if (an[x]) result.diffType = x; - }); - - if (!result.diffType) return null; - - an = an[result.diffType]; - - result.entryType = an.LedgerEntryType; - result.ledgerIndex = an.LedgerIndex; - - result.fields = extend({}, an.PreviousFields, an.NewFields, an.FinalFields); - result.fieldsPrev = an.PreviousFields || {}; - result.fieldsNew = an.NewFields || {}; - result.fieldsFinal = an.FinalFields || {}; - - this.nodes.push(result); - } -}; - -/** - * Execute a function on each affected node. - * - * The callback is passed two parameters. The first is a node object which looks - * like this: - * - * { - * // Type of diff, e.g. CreatedNode, ModifiedNode - * diffType: 'CreatedNode' - * - * // Type of node affected, e.g. RippleState, AccountRoot - * entryType: 'RippleState', - * - * // Index of the ledger this change occurred in - * ledgerIndex: '01AB01AB...', - * - * // Contains all fields with later versions taking precedence - * // - * // This is a shorthand for doing things like checking which account - * // this affected without having to check the diffType. - * fields: {...}, - * - * // Old fields (before the change) - * fieldsPrev: {...}, - * - * // New fields (that have been added) - * fieldsNew: {...}, - * - * // Changed fields - * fieldsFinal: {...} - * } - * - * The second parameter to the callback is the index of the node in the metadata - * (first entry is index 0). - */ -Meta.prototype.each = function (fn) -{ - for (var i = 0, l = this.nodes.length; i < l; i++) { - fn(this.nodes[i], i); - } -}; - -var amountFieldsAffectingIssuer = [ - "LowLimit", "HighLimit", "TakerPays", "TakerGets" -]; -Meta.prototype.getAffectedAccounts = function () -{ - var accounts = []; - - // This code should match the behavior of the C++ method: - // TransactionMetaSet::getAffectedAccounts - this.each(function (an) { - var fields = (an.diffType === "CreatedNode") ? an.fieldsNew : an.fieldsFinal; - - for (var i in fields) { - var field = fields[i]; - - if ("string" === typeof field && UInt160.is_valid(field)) { - accounts.push(field); - } else if (amountFieldsAffectingIssuer.indexOf(i) !== -1) { - var amount = Amount.from_json(field); - var issuer = amount.issuer(); - if (issuer.is_valid() && !issuer.is_zero()) { - accounts.push(issuer.to_json()); - } - } - } - }); - - accounts = utils.arrayUnique(accounts); - - return accounts; -}; - -Meta.prototype.getAffectedBooks = function () -{ - var books = []; - - this.each(function (an) { - if (an.entryType !== 'Offer') return; - - var gets = Amount.from_json(an.fields.TakerGets); - var pays = Amount.from_json(an.fields.TakerPays); - - var getsKey = gets.currency().to_json(); - if (getsKey !== 'XRP') getsKey += '/' + gets.issuer().to_json(); - - var paysKey = pays.currency().to_json(); - if (paysKey !== 'XRP') paysKey += '/' + pays.issuer().to_json(); - - var key = getsKey + ":" + paysKey; - - books.push(key); - }); - - books = utils.arrayUnique(books); - - return books; -}; - -exports.Meta = Meta; diff --git a/src/js/network.js b/src/js/network.js deleted file mode 100644 index 3f7697a995..0000000000 --- a/src/js/network.js +++ /dev/null @@ -1,58 +0,0 @@ -// -// Access to the Ripple network via multiple untrusted servers or a single trusted server. -// -// Overview: -// Network configuration. -// Can leverage local storage to remember network configuration -// Aquires the network -// events: -// online -// offline -// - -var remote = require("./remote.js"); - -var opts_default = { - DEFAULT_VALIDATORS_SITE : "redstem.com", - - ips = { - } -}; - -// -// opts : { -// cache : undefined || { -// get : function () { return cached_value; }, -// set : function (value) { cached_value = value; }, -// }, -// -// // Where to get validators.txt if needed. -// DEFAULT_VALIDATORS_SITE : _domain_, -// -// // Validator.txt to use. -// validators : _txt_, -// } -// - -var Network = function (opts) { - -}; - -// Set the network configuration. -Network.protocol.configure = function () { - -}; - -// Target state: connectted -Network.protocol.start = function () { - -}; - -// Target state: disconnect -Network.protocol.stop = function () { - -}; - -exports.Network = Network; - -// vim:sw=2:sts=2:ts=8:et diff --git a/src/js/orderbook.js b/src/js/orderbook.js deleted file mode 100644 index 70baa4d545..0000000000 --- a/src/js/orderbook.js +++ /dev/null @@ -1,250 +0,0 @@ -// Routines for working with an orderbook. -// -// One OrderBook object represents one half of an order book. (i.e. bids OR -// asks) Which one depends on the ordering of the parameters. -// -// Events: -// - transaction A transaction that affects the order book. - -// var network = require("./network.js"); - -var EventEmitter = require('events').EventEmitter; -var util = require('util'); - -var Amount = require('./amount').Amount; -var UInt160 = require('./uint160').UInt160; -var Currency = require('./currency').Currency; - -var extend = require('extend'); - -var OrderBook = function (remote, - currency_gets, issuer_gets, - currency_pays, issuer_pays) { - EventEmitter.call(this); - - var self = this; - - this._remote = remote; - this._currency_gets = currency_gets; - this._issuer_gets = issuer_gets; - this._currency_pays = currency_pays; - this._issuer_pays = issuer_pays; - - this._subs = 0; - - // We consider ourselves synchronized if we have a current copy of the offers, - // we are online and subscribed to updates. - this._sync = false; - - // Offers - this._offers = []; - - this.on('newListener', function (type, listener) { - if (OrderBook.subscribe_events.indexOf(type) !== -1) { - if (!self._subs && 'open' === self._remote._online_state) { - self._subscribe(); - } - self._subs += 1; - } - }); - - this.on('removeListener', function (type, listener) { - if (OrderBook.subscribe_events.indexOf(type) !== -1) { - self._subs -= 1; - - if (!self._subs && 'open' === self._remote._online_state) { - self._sync = false; - self._remote.request_unsubscribe() - .books([self.to_json()]) - .request(); - } - } - }); - - this._remote.on('connect', function () { - if (self._subs) { - self._subscribe(); - } - }); - - this._remote.on('disconnect', function () { - self._sync = false; - }); - - return this; -}; - -util.inherits(OrderBook, EventEmitter); - -/** - * List of events that require a remote subscription to the orderbook. - */ -OrderBook.subscribe_events = ['transaction', 'model', 'trade']; - -/** - * Subscribes to orderbook. - * - * @private - */ -OrderBook.prototype._subscribe = function () -{ - var self = this; - self._remote.request_subscribe() - .books([self.to_json()], true) - .on('error', function () { - // XXX What now? - }) - .on('success', function (res) { - self._sync = true; - self._offers = res.offers; - self.emit('model', self._offers); - }) - .request(); -}; - -OrderBook.prototype.to_json = function () -{ - var json = { - "taker_gets": { - "currency": this._currency_gets - }, - "taker_pays": { - "currency": this._currency_pays - } - }; - - if (this._currency_gets !== "XRP") json["taker_gets"]["issuer"] = this._issuer_gets; - if (this._currency_pays !== "XRP") json["taker_pays"]["issuer"] = this._issuer_pays; - - return json; -}; - -/** - * Whether the OrderBook is valid. - * - * Note: This only checks whether the parameters (currencies and issuer) are - * syntactically valid. It does not check anything against the ledger. - */ -OrderBook.prototype.is_valid = function () -{ - // XXX Should check for same currency (non-native) && same issuer - return ( - Currency.is_valid(this._currency_pays) && - (this._currency_pays === "XRP" || UInt160.is_valid(this._issuer_pays)) && - Currency.is_valid(this._currency_gets) && - (this._currency_gets === "XRP" || UInt160.is_valid(this._issuer_gets)) && - !(this._currency_pays === "XRP" && this._currency_gets === "XRP") - ); -}; - -/** - * Notify object of a relevant transaction. - * - * This is only meant to be called by the Remote class. You should never have to - * call this yourself. - */ -OrderBook.prototype.notifyTx = function (message) -{ - var self = this; - - var changed = false; - - var trade_gets = Amount.from_json("0" + ((this._currency_gets === 'XRP') ? "" : - "/" + this._currency_gets + - "/" + this._issuer_gets)); - var trade_pays = Amount.from_json("0" + ((this._currency_pays === 'XRP') ? "" : - "/" + this._currency_pays + - "/" + this._issuer_pays)); - - message.mmeta.each(function (an) { - if (an.entryType !== 'Offer') return; - - var i, l, offer; - if (an.diffType === 'DeletedNode' || - an.diffType === 'ModifiedNode') { - for (i = 0, l = self._offers.length; i < l; i++) { - offer = self._offers[i]; - if (offer.index === an.ledgerIndex) { - if (an.diffType === 'DeletedNode') { - self._offers.splice(i, 1); - } - else extend(offer, an.fieldsFinal); - changed = true; - break; - } - } - - // We don't want to count a OfferCancel as a trade - if (message.transaction.TransactionType === "OfferCancel") return; - - trade_gets = trade_gets.add(an.fieldsPrev.TakerGets); - trade_pays = trade_pays.add(an.fieldsPrev.TakerPays); - if (an.diffType === 'ModifiedNode') { - trade_gets = trade_gets.subtract(an.fieldsFinal.TakerGets); - trade_pays = trade_pays.subtract(an.fieldsFinal.TakerPays); - } - } else if (an.diffType === 'CreatedNode') { - var price = Amount.from_json(an.fields.TakerPays).ratio_human(an.fields.TakerGets); - for (i = 0, l = self._offers.length; i < l; i++) { - offer = self._offers[i]; - var priceItem = Amount.from_json(offer.TakerPays).ratio_human(offer.TakerGets); - - if (price.compareTo(priceItem) <= 0) { - var obj = an.fields; - obj.index = an.ledgerIndex; - self._offers.splice(i, 0, an.fields); - changed = true; - break; - } - } - } - }); - - // Only trigger the event if the account object is actually - // subscribed - this prevents some weird phantom events from - // occurring. - if (this._subs) { - this.emit('transaction', message); - if (changed) this.emit('model', this._offers); - if (!trade_gets.is_zero()) this.emit('trade', trade_pays, trade_gets); - } -}; - -/** - * Get offers model asynchronously. - * - * This function takes a callback and calls it with an array containing the - * current set of offers in this order book. - * - * If the data is available immediately, the callback may be called synchronously. - */ -OrderBook.prototype.offers = function (callback) -{ - var self = this; - - if ("function" === typeof callback) { - if (this._sync) { - callback(this._offers); - } else { - this.once('model', function (offers) { - callback(offers); - }); - } - } - return this; -}; - -/** - * Return latest known offers. - * - * Usually, this will just be an empty array if the order book hasn't been - * loaded yet. But this accessor may be convenient in some circumstances. - */ -OrderBook.prototype.offersSync = function () -{ - return this._offers; -}; - -exports.OrderBook = OrderBook; - -// vim:sw=2:sts=2:ts=8:et diff --git a/src/js/remote.js b/src/js/remote.js deleted file mode 100644 index 941813468a..0000000000 --- a/src/js/remote.js +++ /dev/null @@ -1,1258 +0,0 @@ -// Remote access to a server. -// - We never send binary data. -// - We use the W3C interface for node and browser compatibility: -// http://www.w3.org/TR/websockets/#the-websocket-interface -// -// This class is intended for both browser and node.js use. -// -// This class is designed to work via peer protocol via either the public or -// private websocket interfaces. The JavaScript class for the peer protocol -// has not yet been implemented. However, this class has been designed for it -// to be a very simple drop option. -// -// YYY Will later provide js/network.js which will transparently use multiple -// instances of this class for network access. -// - -// npm -var EventEmitter = require('events').EventEmitter; -var util = require('util'); - -var Server = require('./server').Server; -var Amount = require('./amount').Amount; -var Currency = require('./currency').Currency; -var UInt160 = require('./uint160').UInt160; -var Transaction = require('./transaction').Transaction; -var Account = require('./account').Account; -var Meta = require('./meta').Meta; -var OrderBook = require('./orderbook').OrderBook; - -var utils = require('./utils'); -var config = require('./config'); -var sjcl = require('../../build/sjcl'); - -// Request events emitted: -// 'success' : Request successful. -// 'error' : Request failed. -// 'remoteError' -// 'remoteUnexpected' -// 'remoteDisconnected' -var Request = function (remote, command) { - EventEmitter.call(this); - - var self = this; - - this.message = { - 'command' : command, - 'id' : undefined, - }; - this.remote = remote; - this.requested = false; -}; - -util.inherits(Request, EventEmitter); - -// Send the request to a remote. -Request.prototype.request = function (remote) { - if (!this.requested) { - this.requested = true; - this.remote.request(this); - this.emit('request', remote); - } -}; - -Request.prototype.build_path = function (build) { - if (build) - this.message.build_path = true; - - return this; -}; - -Request.prototype.ledger_choose = function (current) { - if (current) - { - this.message.ledger_index = this.remote._ledger_current_index; - } - else { - this.message.ledger_hash = this.remote._ledger_hash; - } - - return this; -}; - -// Set the ledger for a request. -// - ledger_entry -// - transaction_entry -Request.prototype.ledger_hash = function (h) { - this.message.ledger_hash = h; - - return this; -}; - -// Set the ledger_index for a request. -// - ledger_entry -Request.prototype.ledger_index = function (ledger_index) { - this.message.ledger_index = ledger_index; - - return this; -}; - -Request.prototype.ledger_select = function (ledger_spec) { - if (ledger_spec === 'current') { - this.message.ledger_index = ledger_spec; - - } else if (ledger_spec === 'closed') { - this.message.ledger_index = ledger_spec; - - } else if (ledger_spec === 'verified') { - this.message.ledger_index = ledger_spec; - - } else if (String(ledger_spec).length > 12) { // XXX Better test needed - this.message.ledger_hash = ledger_spec; - - } else { - this.message.ledger_index = ledger_spec; - } - - return this; -}; - -Request.prototype.account_root = function (account) { - this.message.account_root = UInt160.json_rewrite(account); - - return this; -}; - -Request.prototype.index = function (hash) { - this.message.index = hash; - - return this; -}; - -// Provide the information id an offer. -// --> account -// --> seq : sequence number of transaction creating offer (integer) -Request.prototype.offer_id = function (account, seq) { - this.message.offer = { - 'account' : UInt160.json_rewrite(account), - 'seq' : seq - }; - - return this; -}; - -// --> index : ledger entry index. -Request.prototype.offer_index = function (index) { - this.message.offer = index; - - return this; -}; - -Request.prototype.secret = function (s) { - if (s) - this.message.secret = s; - - return this; -}; - -Request.prototype.tx_hash = function (h) { - this.message.tx_hash = h; - - return this; -}; - -Request.prototype.tx_json = function (j) { - this.message.tx_json = j; - - return this; -}; - -Request.prototype.tx_blob = function (j) { - this.message.tx_blob = j; - - return this; -}; - -Request.prototype.ripple_state = function (account, issuer, currency) { - this.message.ripple_state = { - 'accounts' : [ - UInt160.json_rewrite(account), - UInt160.json_rewrite(issuer) - ], - 'currency' : currency - }; - - return this; -}; - -Request.prototype.accounts = function (accounts, realtime) { - if ("object" !== typeof accounts) { - accounts = [accounts]; - } - - // Process accounts parameters - var procAccounts = []; - for (var i = 0, l = accounts.length; i < l; i++) { - procAccounts.push(UInt160.json_rewrite(accounts[i])); - } - if (realtime) { - this.message.rt_accounts = procAccounts; - } else { - this.message.accounts = procAccounts; - } - - return this; -}; - -Request.prototype.rt_accounts = function (accounts) { - return this.accounts(accounts, true); -}; - -Request.prototype.books = function (books, snapshot) { - var procBooks = []; - - for (var i = 0, l = books.length; i < l; i++) { - var book = books[i]; - var json = {}; - - function process(side) { - if (!book[side]) throw new Error("Missing "+side); - - var obj = {}; - obj["currency"] = Currency.json_rewrite(book[side]["currency"]); - if (obj["currency"] !== "XRP") { - obj.issuer = UInt160.json_rewrite(book[side]["issuer"]); - } - - json[side] = obj; - } - - process("taker_gets"); - process("taker_pays"); - - if (snapshot || book["snapshot"]) json["snapshot"] = true; - if (book["both"]) json["both"] = true; - - procBooks.push(json); - } - this.message.books = procBooks; - - return this; -}; - -// -// Remote - access to a remote Ripple server via websocket. -// -// Events: -// 'connect' -// 'connected' (DEPRECATED) -// 'disconnect' -// 'disconnected' (DEPRECATED) -// 'state': -// - 'online' : Connected and subscribed. -// - 'offline' : Not subscribed or not connected. -// 'subscribed' : This indicates stand-alone is available. -// -// Server events: -// 'ledger_closed' : A good indicate of ready to serve. -// 'transaction' : Transactions we receive based on current subscriptions. -// 'transaction_all' : Listening triggers a subscribe to all transactions -// globally in the network. - -// --> trusted: truthy, if remote is trusted -var Remote = function (opts, trace) { - EventEmitter.call(this); - - var self = this; - - this.trusted = opts.trusted; - this.websocket_ip = opts.websocket_ip; - this.websocket_port = opts.websocket_port; - this.websocket_ssl = opts.websocket_ssl; - this.local_sequence = opts.local_sequence; // Locally track sequence numbers - this.local_fee = opts.local_fee; // Locally set fees - this.local_signing = opts.local_signing; - this.id = 0; - this.trace = opts.trace || trace; - this._server_fatal = false; // True, if we know server exited. - this._ledger_current_index = undefined; - this._ledger_hash = undefined; - this._ledger_time = undefined; - this._stand_alone = undefined; - this._testnet = undefined; - this._transaction_subs = 0; - this.online_target = false; - this._online_state = 'closed'; // 'open', 'closed', 'connecting', 'closing' - this.state = 'offline'; // 'online', 'offline' - this.retry_timer = undefined; - this.retry = undefined; - - this._load_base = 256; - this._load_factor = 1.0; - this._fee_ref = undefined; - this._fee_base = undefined; - this._reserve_base = undefined; - this._reserve_inc = undefined; - this._connection_count = 0; - - this._last_tx = null; - - // Local signing implies local fees and sequences - if (this.local_signing) { - this.local_sequence = true; - this.local_fee = true; - } - - this._servers = []; - - // Cache information for accounts. - // DEPRECATED, will be removed - this.accounts = { - // Consider sequence numbers stable if you know you're not generating bad transactions. - // Otherwise, clear it to have it automatically refreshed from the network. - - // account : { seq : __ } - - }; - - // Hash map of Account objects by AccountId. - this._accounts = {}; - - // Hash map of OrderBook objects - this._books = {}; - - // List of secrets that we know about. - this.secrets = { - // Secrets can be set by calling set_secret(account, secret). - - // account : secret - }; - - // Cache for various ledgers. - // XXX Clear when ledger advances. - this.ledgers = { - 'current' : { - 'account_root' : {} - } - }; - - // XXX Add support for multiple servers - var url = (this.websocket_ssl ? "wss://" : "ws://") + - this.websocket_ip + ":" + this.websocket_port; - - this.add_server(new Server(this, {url: url})); - - this.on('newListener', function (type, listener) { - if ('transaction_all' === type) - { - if (!self._transaction_subs && 'open' === self._online_state) - { - self.request_subscribe([ 'transactions' ]) - .request(); - } - self._transaction_subs += 1; - } - }); - - this.on('removeListener', function (type, listener) { - if ('transaction_all' === type) - { - self._transaction_subs -= 1; - - if (!self._transaction_subs && 'open' === self._online_state) - { - self.request_unsubscribe([ 'transactions' ]) - .request(); - } - } - }); -}; - -util.inherits(Remote, EventEmitter); - -Remote.from_config = function (obj, trace) { - var serverConfig = 'string' === typeof obj ? config.servers[obj] : obj; - - var remote = new Remote(serverConfig, trace); - - for (var account in config.accounts) { - var accountInfo = config.accounts[account]; - if ("object" === typeof accountInfo) { - if (accountInfo.secret) { - // Index by nickname ... - remote.set_secret(account, accountInfo.secret); - // ... and by account ID - remote.set_secret(accountInfo.account, accountInfo.secret); - } - } - } - - return remote; -}; - -var isTemMalformed = function (engine_result_code) { - return (engine_result_code >= -299 && engine_result_code < 199); -}; - -var isTefFailure = function (engine_result_code) { - return (engine_result_code >= -299 && engine_result_code < 199); -}; - -Remote.prototype.add_server = function (server) { - var self = this; - - server.on('message', function (data) { - self._handle_message(data); - }); - - server.on('connect', function () { - self._connection_count++; - self._set_state('online'); - }); - - server.on('disconnect', function () { - self._connection_count--; - if (!self._connection_count) self._set_state('offline'); - }); - - this._servers.push(server); - - return this; -}; - -// Inform remote that the remote server is not comming back. -Remote.prototype.server_fatal = function () { - this._server_fatal = true; -}; - -// Set the emitted state: 'online' or 'offline' -Remote.prototype._set_state = function (state) { - if (this.trace) console.log("remote: set_state: %s", state); - - if (this.state !== state) { - this.state = state; - - this.emit('state', state); - - switch (state) { - case 'online': - this._online_state = 'open'; - this.emit('connect'); - this.emit('connected'); - break; - - case 'offline': - this._online_state = 'closed'; - this.emit('disconnect'); - this.emit('disconnected'); - break; - } - } -}; - -Remote.prototype.set_trace = function (trace) { - this.trace = undefined === trace || trace; - - return this; -}; - -/** - * Connect to the Ripple network. - */ -Remote.prototype.connect = function (online) { - // Downwards compatibility - if ("undefined" !== typeof online && !online) { - return this.disconnect(); - } - - if (!this._servers.length) { - throw new Error("No servers available."); - } else { - // XXX Add support for multiple servers - this._servers[0].connect(); - } - - return this; -}; - -/** - * Disconnect from the Ripple network. - */ -Remote.prototype.disconnect = function (online) { - for (var i = 0, l = this._servers.length; i < l; i++) { - this._servers[i].disconnect(); - } - - this._set_state('offline'); - - return this; -}; - -Remote.prototype.ledger_hash = function () { - return this._ledger_hash; -}; - -// It is possible for messages to be dispatched after the connection is closed. -Remote.prototype._handle_message = function (json) { - var self = this; - var message = JSON.parse(json); - var unexpected = false; - var request; - - if ('object' !== typeof message) { - unexpected = true; - } - else { - switch (message.type) { - case 'response': - // Handled by the server that sent the request - break; - - case 'ledgerClosed': - // XXX If not trusted, need to verify we consider ledger closed. - // XXX Also need to consider a slow server or out of order response. - // XXX Be more defensive fields could be missing or of wrong type. - // YYY Might want to do some cache management. - - this._ledger_time = message.ledger_time; - this._ledger_hash = message.ledger_hash; - this._ledger_current_index = message.ledger_index + 1; - - this.emit('ledger_closed', message); - break; - - case 'transaction': - // To get these events, just subscribe to them. A subscribes and - // unsubscribes will be added as needed. - // XXX If not trusted, need proof. - - // De-duplicate transactions that are immediately following each other - // XXX Should have a cache of n txs so we can dedup out of order txs - if (this._last_tx === message.transaction.hash) break; - this._last_tx = message.transaction.hash; - - if (this.trace) utils.logObject("remote: tx: %s", message); - - // Process metadata - message.mmeta = new Meta(message.meta); - - // Pass the event on to any related Account objects - var affected = message.mmeta.getAffectedAccounts(); - for (var i = 0, l = affected.length; i < l; i++) { - var account = self._accounts[affected[i]]; - - if (account) account.notifyTx(message); - } - - // Pass the event on to any related OrderBooks - affected = message.mmeta.getAffectedBooks(); - for (i = 0, l = affected.length; i < l; i++) { - var book = self._books[affected[i]]; - - if (book) book.notifyTx(message); - } - - this.emit('transaction', message); - this.emit('transaction_all', message); - break; - - // XXX Should be tracked by the Server object - case 'serverStatus': - if ('load_base' in message && - 'load_factor' in message && - (message.load_base !== self._load_base || message.load_factor != self._load_factor)) - { - self._load_base = message.load_base; - self._load_factor = message.load_factor; - - self.emit('load', { 'load_base' : self._load_base, 'load_factor' : self.load_factor }); - } - break; - - // All other messages - default: - if (this.trace) utils.logObject("remote: "+message.type+": %s", message); - this.emit('net_'+message.type, message); - break; - } - } - - // Unexpected response from remote. - if (unexpected) { - console.log("unexpected message from trusted remote: %s", json); - - (request || this).emit('error', { - 'error' : 'remoteUnexpected', - 'error_message' : 'Unexpected response from remote.' - }); - } -}; - -// Send a request. -// <-> request: what to send, consumed. -Remote.prototype.request = function (request) { - if (!this._servers.length) { - throw new Error("No servers available."); - } else { - // XXX Add support for multiple servers - this._servers[0].request(request); - } -}; - -Remote.prototype.request_server_info = function () { - return new Request(this, 'server_info'); -}; - -// XXX This is a bad command. Some varients don't scale. -// XXX Require the server to be trusted. -Remote.prototype.request_ledger = function (ledger, opts) { - //utils.assert(this.trusted); - - var request = new Request(this, 'ledger'); - - if (ledger) - { - // DEPRECATED: use .ledger_hash() or .ledger_index() - console.log("request_ledger: ledger parameter is deprecated"); - request.message.ledger = ledger; - } - - if ('object' == typeof opts) { - if (opts.full) - request.message.full = true; - - if (opts.expand) - request.message.expand = true; - - if (opts.transactions) - request.message.transactions = true; - - if (opts.accounts) - request.message.accounts = true; - } - // DEPRECATED: - else if (opts) - { - console.log("request_ledger: full parameter is deprecated"); - request.message.full = true; - } - - return request; -}; - -// Only for unit testing. -Remote.prototype.request_ledger_hash = function () { - //utils.assert(this.trusted); // If not trusted, need to check proof. - - return new Request(this, 'ledger_closed'); -}; - -// .ledger() -// .ledger_index() -Remote.prototype.request_ledger_header = function () { - return new Request(this, 'ledger_header'); -}; - -// Get the current proposed ledger entry. May be closed (and revised) at any time (even before returning). -// Only for unit testing. -Remote.prototype.request_ledger_current = function () { - return new Request(this, 'ledger_current'); -}; - -// --> type : the type of ledger entry. -// .ledger() -// .ledger_index() -// .offer_id() -Remote.prototype.request_ledger_entry = function (type) { - //utils.assert(this.trusted); // If not trusted, need to check proof, maybe talk packet protocol. - - var self = this; - var request = new Request(this, 'ledger_entry'); - - // Transparent caching. When .request() is invoked, look in the Remote object for the result. - // If not found, listen, cache result, and emit it. - // - // Transparent caching: - if ('account_root' === type) { - request.request_default = request.request; - - request.request = function () { // Intercept default request. - var bDefault = true; - // .self = Remote - // this = Request - - // console.log('request_ledger_entry: caught'); - - if (self._ledger_hash) { - // A specific ledger is requested. - - // XXX Add caching. - } - // else if (req.ledger_index) - // else if ('ripple_state' === request.type) // YYY Could be cached per ledger. - else if ('account_root' === type) { - var cache = self.ledgers.current.account_root; - - if (!cache) - { - cache = self.ledgers.current.account_root = {}; - } - - var node = self.ledgers.current.account_root[request.message.account_root]; - - if (node) { - // Emulate fetch of ledger entry. - // console.log('request_ledger_entry: emulating'); - request.emit('success', { - // YYY Missing lots of fields. - 'node' : node, - }); - - bDefault = false; - } - else { - // Was not cached. - - // XXX Only allow with trusted mode. Must sync response with advance. - switch (type) { - case 'account_root': - request.on('success', function (message) { - // Cache node. - // console.log('request_ledger_entry: caching'); - self.ledgers.current.account_root[message.node.Account] = message.node; - }); - break; - - default: - // This type not cached. - // console.log('request_ledger_entry: non-cached type'); - } - } - } - - if (bDefault) { - // console.log('request_ledger_entry: invoking'); - request.request_default(); - } - } - }; - - return request; -}; - -// .accounts(accounts, realtime) -Remote.prototype.request_subscribe = function (streams) { - var request = new Request(this, 'subscribe'); - - if (streams) { - if ("object" !== typeof streams) { - streams = [streams]; - } - request.message.streams = streams; - } - - return request; -}; - -// .accounts(accounts, realtime) -Remote.prototype.request_unsubscribe = function (streams) { - var request = new Request(this, 'unsubscribe'); - - if (streams) { - if ("object" !== typeof streams) { - streams = [streams]; - } - request.message.streams = streams; - } - - return request; -}; - -// .ledger_choose() -// .ledger_hash() -// .ledger_index() -Remote.prototype.request_transaction_entry = function (hash) { - //utils.assert(this.trusted); // If not trusted, need to check proof, maybe talk packet protocol. - - return (new Request(this, 'transaction_entry')) - .tx_hash(hash); -}; - -// DEPRECATED: use request_transaction_entry -Remote.prototype.request_tx = function (hash) { - var request = new Request(this, 'tx'); - - request.message.transaction = hash; - - return request; -}; - -Remote.prototype.request_account_info = function (accountID) { - var request = new Request(this, 'account_info'); - - request.message.ident = UInt160.json_rewrite(accountID); // DEPRECATED - request.message.account = UInt160.json_rewrite(accountID); - - return request; -}; - -// --> account_index: sub_account index (optional) -// --> current: true, for the current ledger. -Remote.prototype.request_account_lines = function (accountID, account_index, current) { - // XXX Does this require the server to be trusted? - //utils.assert(this.trusted); - - var request = new Request(this, 'account_lines'); - - request.message.account = UInt160.json_rewrite(accountID); - - if (account_index) - request.message.index = account_index; - - return request - .ledger_choose(current); -}; - -// --> account_index: sub_account index (optional) -// --> current: true, for the current ledger. -Remote.prototype.request_account_offers = function (accountID, account_index, current) { - var request = new Request(this, 'account_offers'); - - request.message.account = UInt160.json_rewrite(accountID); - - if (account_index) - request.message.index = account_index; - - return request - .ledger_choose(current); -}; - - -/* - account: account, - ledger_index_min: ledger_index, // optional, defaults to -1 if ledger_index_max is specified. - ledger_index_max: ledger_index, // optional, defaults to -1 if ledger_index_min is specified. - binary: boolean, // optional, defaults to false - count: boolean, // optional, defaults to false - descending: boolean, // optional, defaults to false - offset: integer, // optional, defaults to 0 - limit: integer // optional -*/ - -Remote.prototype.request_account_tx = function (obj) { - // XXX Does this require the server to be trusted? - //utils.assert(this.trusted); - - var request = new Request(this, 'account_tx'); - - request.message.account = obj.account; - - if (false && ledger_min === ledger_max) { - //request.message.ledger = ledger_min; - } - else { - if ("undefined" != typeof obj.ledger_index_min) {request.message.ledger_index_min = obj.ledger_index_min;} - if ("undefined" != typeof obj.ledger_index_max) {request.message.ledger_index_max = obj.ledger_index_max;} - if ("undefined" != typeof obj.binary) {request.message.binary = obj.binary;} - if ("undefined" != typeof obj.count) {request.message.count = obj.count;} - if ("undefined" != typeof obj.descending) {request.message.descending = obj.descending;} - if ("undefined" != typeof obj.offset) {request.message.offset = obj.offset;} - if ("undefined" != typeof obj.limit) {request.message.limit = obj.limit;} - } - return request; -}; - -Remote.prototype.request_book_offers = function (gets, pays, taker) { - var request = new Request(this, 'book_offers'); - - request.message.taker_gets = { - currency: Currency.json_rewrite(gets.currency) - }; - - if (request.message.taker_gets.currency !== 'XRP') { - request.message.taker_gets.issuer = UInt160.json_rewrite(gets.issuer); - } - - request.message.taker_pays = { - currency: Currency.json_rewrite(pays.currency) - }; - - if (request.message.taker_pays.currency !== 'XRP') { - request.message.taker_pays.issuer = UInt160.json_rewrite(pays.issuer); - } - - request.message.taker = taker ? taker : UInt160.ACCOUNT_ONE; - - return request; -}; - -Remote.prototype.request_wallet_accounts = function (seed) { - utils.assert(this.trusted); // Don't send secrets. - - var request = new Request(this, 'wallet_accounts'); - - request.message.seed = seed; - - return request; -}; - -Remote.prototype.request_sign = function (secret, tx_json) { - utils.assert(this.trusted); // Don't send secrets. - - var request = new Request(this, 'sign'); - - request.message.secret = secret; - request.message.tx_json = tx_json; - - return request; -}; - -// Submit a transaction. -Remote.prototype.request_submit = function () { - var self = this; - - var request = new Request(this, 'submit'); - - return request; -}; - -// -// Higher level functions. -// - -/** - * Create a subscribe request with current subscriptions. - * - * Other classes can add their own subscriptions to this request by listening to - * the server_subscribe event. - * - * This function will create and return the request, but not submit it. - */ -Remote.prototype._server_prepare_subscribe = function () -{ - var self = this; - - var feeds = [ 'ledger', 'server' ]; - - if (this._transaction_subs) - feeds.push('transactions'); - - var req = this.request_subscribe(feeds); - - req.on('success', function (message) { - self._stand_alone = !!message.stand_alone; - self._testnet = !!message.testnet; - - if ("string" === typeof message.random) { - var rand = message.random.match(/[0-9A-F]{8}/ig); - while (rand && rand.length) - sjcl.random.addEntropy(parseInt(rand.pop(), 16)); - - self.emit('random', utils.hexToArray(message.random)); - } - - if (message.ledger_hash && message.ledger_index) { - self._ledger_time = message.ledger_time; - self._ledger_hash = message.ledger_hash; - self._ledger_current_index = message.ledger_index+1; - - self.emit('ledger_closed', message); - } - - // FIXME Use this to estimate fee. - // XXX When we have multiple server support, most of this should be tracked - // by the Server objects and then aggregated/interpreted by Remote. - self._load_base = message.load_base || 256; - self._load_factor = message.load_factor || 1.0; - self._fee_ref = message.fee_ref; - self._fee_base = message.fee_base; - self._reserve_base = message.reserve_base; - self._reserve_inc = message.reserve_inc; - - self.emit('subscribed'); - }); - - self.emit('prepare_subscribe', req); - - // XXX Could give error events, maybe even time out. - - return req; -}; - -// For unit testing: ask the remote to accept the current ledger. -// - To be notified when the ledger is accepted, server_subscribe() then listen to 'ledger_hash' events. -// A good way to be notified of the result of this is: -// remote.once('ledger_closed', function (ledger_closed, ledger_index) { ... } ); -Remote.prototype.ledger_accept = function () { - if (this._stand_alone || undefined === this._stand_alone) - { - var request = new Request(this, 'ledger_accept'); - - request - .request(); - } - else { - this.emit('error', { - 'error' : 'notStandAlone' - }); - } - - return this; -}; - -// Return a request to refresh the account balance. -Remote.prototype.request_account_balance = function (account, current) { - var request = this.request_ledger_entry('account_root'); - - return request - .account_root(account) - .ledger_choose(current) - .on('success', function (message) { - // If the caller also waits for 'success', they might run before this. - request.emit('account_balance', Amount.from_json(message.node.Balance)); - }); -}; - -// Return a request to emit the owner count. -Remote.prototype.request_owner_count = function (account, current) { - var request = this.request_ledger_entry('account_root'); - - return request - .account_root(account) - .ledger_choose(current) - .on('success', function (message) { - // If the caller also waits for 'success', they might run before this. - request.emit('owner_count', message.node.OwnerCount); - }); -}; - -Remote.prototype.account = function (accountId) { - accountId = UInt160.json_rewrite(accountId); - - if (!this._accounts[accountId]) { - var account = new Account(this, accountId); - - if (!account.is_valid()) return account; - - this._accounts[accountId] = account; - } - - return this._accounts[accountId]; -}; - -Remote.prototype.book = function (currency_gets, issuer_gets, - currency_pays, issuer_pays) { - var gets = currency_gets; - if (gets !== 'XRP') gets += '/' + issuer_gets; - var pays = currency_pays; - if (pays !== 'XRP') pays += '/' + issuer_pays; - - var key = gets + ":" + pays; - - if (!this._books[key]) { - var book = new OrderBook(this, - currency_gets, issuer_gets, - currency_pays, issuer_pays); - - if (!book.is_valid()) return book; - - this._books[key] = book; - } - - return this._books[key]; -} - -// Return the next account sequence if possible. -// <-- undefined or Sequence -Remote.prototype.account_seq = function (account, advance) { - account = UInt160.json_rewrite(account); - var account_info = this.accounts[account]; - var seq; - - if (account_info && account_info.seq) - { - seq = account_info.seq; - - if (advance === "ADVANCE") account_info.seq += 1; - if (advance === "REWIND") account_info.seq -= 1; - - // console.log("cached: %s current=%d next=%d", account, seq, account_info.seq); - } - else { - // console.log("uncached: %s", account); - } - - return seq; -} - -Remote.prototype.set_account_seq = function (account, seq) { - var account = UInt160.json_rewrite(account); - - if (!this.accounts[account]) this.accounts[account] = {}; - - this.accounts[account].seq = seq; -} - -// Return a request to refresh accounts[account].seq. -Remote.prototype.account_seq_cache = function (account, current) { - var self = this; - var request; - - if (!self.accounts[account]) self.accounts[account] = {}; - - var account_info = self.accounts[account]; - - request = account_info.caching_seq_request; - if (!request) { - // console.log("starting: %s", account); - request = self.request_ledger_entry('account_root') - .account_root(account) - .ledger_choose(current) - .on('success', function (message) { - delete account_info.caching_seq_request; - - var seq = message.node.Sequence; - - account_info.seq = seq; - - // console.log("caching: %s %d", account, seq); - // If the caller also waits for 'success', they might run before this. - request.emit('success_account_seq_cache', message); - }) - .on('error', function (message) { - // console.log("error: %s", account); - delete account_info.caching_seq_request; - - request.emit('error_account_seq_cache', message); - }); - - account_info.caching_seq_request = request; - } - - return request; -}; - -// Mark an account's root node as dirty. -Remote.prototype.dirty_account_root = function (account) { - var account = UInt160.json_rewrite(account); - - delete this.ledgers.current.account_root[account]; -}; - -// Store a secret - allows the Remote to automatically fill out auth information. -Remote.prototype.set_secret = function (account, secret) { - this.secrets[account] = secret; -}; - - -// Return a request to get a ripple balance. -// -// --> account: String -// --> issuer: String -// --> currency: String -// --> current: bool : true = current ledger -// -// If does not exist: emit('error', 'error' : 'remoteError', 'remote' : { 'error' : 'entryNotFound' }) -Remote.prototype.request_ripple_balance = function (account, issuer, currency, current) { - var request = this.request_ledger_entry('ripple_state'); // YYY Could be cached per ledger. - - return request - .ripple_state(account, issuer, currency) - .ledger_choose(current) - .on('success', function (message) { - var node = message.node; - - var lowLimit = Amount.from_json(node.LowLimit); - var highLimit = Amount.from_json(node.HighLimit); - // The amount the low account holds of issuer. - var balance = Amount.from_json(node.Balance); - // accountHigh implies: for account: balance is negated, highLimit is the limit set by account. - var accountHigh = UInt160.from_json(account).equals(highLimit.issuer()); - - request.emit('ripple_state', { - 'account_balance' : ( accountHigh ? balance.negate() : balance.clone()).parse_issuer(account), - 'peer_balance' : (!accountHigh ? balance.negate() : balance.clone()).parse_issuer(issuer), - - 'account_limit' : ( accountHigh ? highLimit : lowLimit).clone().parse_issuer(issuer), - 'peer_limit' : (!accountHigh ? highLimit : lowLimit).clone().parse_issuer(account), - - 'account_quality_in' : ( accountHigh ? node.HighQualityIn : node.LowQualityIn), - 'peer_quality_in' : (!accountHigh ? node.HighQualityIn : node.LowQualityIn), - - 'account_quality_out' : ( accountHigh ? node.HighQualityOut : node.LowQualityOut), - 'peer_quality_out' : (!accountHigh ? node.HighQualityOut : node.LowQualityOut), - }); - }); -}; - -Remote.prototype.request_ripple_path_find = function (src_account, dst_account, dst_amount, source_currencies) { - var self = this; - var request = new Request(this, 'ripple_path_find'); - - request.message.source_account = UInt160.json_rewrite(src_account); - request.message.destination_account = UInt160.json_rewrite(dst_account); - request.message.destination_amount = Amount.json_rewrite(dst_amount); - - if (source_currencies) { - request.message.source_currencies = source_currencies.map(function (ci) { - var ci_new = {}; - - if ('issuer' in ci) - ci_new.issuer = UInt160.json_rewrite(ci.issuer); - - if ('currency' in ci) - ci_new.currency = Currency.json_rewrite(ci.currency); - - return ci_new; - }); - } - - return request; -}; - -Remote.prototype.request_unl_list = function () { - return new Request(this, 'unl_list'); -}; - -Remote.prototype.request_unl_add = function (addr, comment) { - var request = new Request(this, 'unl_add'); - - request.message.node = addr; - - if (comment !== undefined) - request.message.comment = note; - - return request; -}; - -// --> node: | -Remote.prototype.request_unl_delete = function (node) { - var request = new Request(this, 'unl_delete'); - - request.message.node = node; - - return request; -}; - -Remote.prototype.request_peers = function () { - return new Request(this, 'peers'); -}; - -Remote.prototype.request_connect = function (ip, port) { - var request = new Request(this, 'connect'); - - request.message.ip = ip; - - if (port) - request.message.port = port; - - return request; -}; - -Remote.prototype.transaction = function () { - return new Transaction(this); -}; - -exports.Remote = Remote; - -// vim:sw=2:sts=2:ts=8:et diff --git a/src/js/seed.js b/src/js/seed.js deleted file mode 100644 index 11d1f226fd..0000000000 --- a/src/js/seed.js +++ /dev/null @@ -1,116 +0,0 @@ -// -// Seed support -// - -var sjcl = require('../../build/sjcl'); -var utils = require('./utils'); -var jsbn = require('./jsbn'); -var extend = require('extend'); - -var BigInteger = jsbn.BigInteger; - -var Base = require('./base').Base, - UInt = require('./uint').UInt, - UInt256 = require('./uint256').UInt256, - KeyPair = require('./keypair').KeyPair; - -var Seed = extend(function () { - // Internal form: NaN or BigInteger - this._curve = sjcl.ecc.curves['c256']; - this._value = NaN; -}, UInt); - -Seed.width = 16; -Seed.prototype = extend({}, UInt.prototype); -Seed.prototype.constructor = Seed; - -// value = NaN on error. -// One day this will support rfc1751 too. -Seed.prototype.parse_json = function (j) { - if ('string' === typeof j) { - if (!j.length) { - this._value = NaN; - // XXX Should actually always try and continue if it failed. - } else if (j[0] === "s") { - this._value = Base.decode_check(Base.VER_FAMILY_SEED, j); - } else if (j.length === 32) { - this._value = this.parse_hex(j); - // XXX Should also try 1751 - } else { - this.parse_passphrase(j); - } - } else { - this._value = NaN; - } - - return this; -}; - -Seed.prototype.parse_passphrase = function (j) { - if ("string" !== typeof j) { - throw new Error("Passphrase must be a string"); - } - - var hash = sjcl.hash.sha512.hash(sjcl.codec.utf8String.toBits(j)); - var bits = sjcl.bitArray.bitSlice(hash, 0, 128); - - this.parse_bits(bits); - - return this; -}; - -Seed.prototype.to_json = function () { - if (!(this._value instanceof BigInteger)) - return NaN; - - var output = Base.encode_check(Base.VER_FAMILY_SEED, this.to_bytes()); - - return output; -}; - -function append_int(a, i) { - return [].concat(a, i >> 24, (i >> 16) & 0xff, (i >> 8) & 0xff, i & 0xff); -} - -function firstHalfOfSHA512(bytes) { - return sjcl.bitArray.bitSlice( - sjcl.hash.sha512.hash(sjcl.codec.bytes.toBits(bytes)), - 0, 256 - ); -} - -function SHA256_RIPEMD160(bits) { - return sjcl.hash.ripemd160.hash(sjcl.hash.sha256.hash(bits)); -} - -Seed.prototype.get_key = function (account_id) { - if (!this.is_valid()) { - throw new Error("Cannot generate keys from invalid seed!"); - } - // XXX Should loop over keys until we find the right one - - var curve = this._curve; - - var seq = 0; - - var private_gen, public_gen, i = 0; - do { - private_gen = sjcl.bn.fromBits(firstHalfOfSHA512(append_int(this.to_bytes(), i))); - i++; - } while (!curve.r.greaterEquals(private_gen)); - - public_gen = curve.G.mult(private_gen); - - var sec; - i = 0; - do { - sec = sjcl.bn.fromBits(firstHalfOfSHA512(append_int(append_int(public_gen.toBytesCompressed(), seq), i))); - i++; - } while (!curve.r.greaterEquals(sec)); - - sec = sec.add(private_gen).mod(curve.r); - - return KeyPair.from_bn_secret(sec); -}; - -exports.Seed = Seed; diff --git a/src/js/serializedobject.js b/src/js/serializedobject.js deleted file mode 100644 index f346f69524..0000000000 --- a/src/js/serializedobject.js +++ /dev/null @@ -1,144 +0,0 @@ -var binformat = require('./binformat'), - sjcl = require('../../build/sjcl'), - extend = require('extend'), - stypes = require('./serializedtypes'); - -var UInt256 = require('./uint256').UInt256; - -var SerializedObject = function () { - this.buffer = []; - this.pointer = 0; -}; - -SerializedObject.from_json = function (obj) { - var typedef; - var so = new SerializedObject(); - - // Create a copy of the object so we don't modify it - obj = extend({}, obj); - - if ("number" === typeof obj.TransactionType) { - obj.TransactionType = SerializedObject.lookup_type_tx(obj.TransactionType); - - if (!obj.TransactionType) { - throw new Error("Transaction type ID is invalid."); - } - } - - if ("string" === typeof obj.TransactionType) { - typedef = binformat.tx[obj.TransactionType].slice(); - - obj.TransactionType = typedef.shift(); - } else if ("undefined" !== typeof obj.LedgerEntryType) { - // XXX: TODO - throw new Error("Ledger entry binary format not yet implemented."); - } else throw new Error("Object to be serialized must contain either " + - "TransactionType or LedgerEntryType."); - - so.serialize(typedef, obj); - - return so; -}; - -SerializedObject.prototype.append = function (bytes) { - this.buffer = this.buffer.concat(bytes); - this.pointer += bytes.length; -}; - -SerializedObject.prototype.to_bits = function () -{ - return sjcl.codec.bytes.toBits(this.buffer); -}; - -SerializedObject.prototype.to_hex = function () { - return sjcl.codec.hex.fromBits(this.to_bits()).toUpperCase(); -}; - -SerializedObject.prototype.serialize = function (typedef, obj) -{ - // Ensure canonical order - typedef = SerializedObject._sort_typedef(typedef.slice()); - - // Serialize fields - for (var i = 0, l = typedef.length; i < l; i++) { - var spec = typedef[i]; - this.serialize_field(spec, obj); - } -}; - -SerializedObject.prototype.signing_hash = function (prefix) -{ - var sign_buffer = new SerializedObject(); - stypes.Int32.serialize(sign_buffer, prefix); - sign_buffer.append(this.buffer); - return sign_buffer.hash_sha512_half(); -}; - -SerializedObject.prototype.hash_sha512_half = function () -{ - var bits = sjcl.codec.bytes.toBits(this.buffer), - hash = sjcl.bitArray.bitSlice(sjcl.hash.sha512.hash(bits), 0, 256); - - return UInt256.from_hex(sjcl.codec.hex.fromBits(hash)); -}; - -SerializedObject.prototype.serialize_field = function (spec, obj) -{ - spec = spec.slice(); - - var name = spec.shift(), - presence = spec.shift(), - field_id = spec.shift(), - Type = spec.shift(); - - if ("undefined" !== typeof obj[name]) { - //console.log(name, Type.id, field_id); - this.append(SerializedObject.get_field_header(Type.id, field_id)); - - try { - Type.serialize(this, obj[name]); - } catch (e) { - // Add field name to message and rethrow - e.message = "Error serializing '"+name+"': "+e.message; - throw e; - } - } else if (presence === binformat.REQUIRED) { - throw new Error('Missing required field '+name); - } -}; - -SerializedObject.get_field_header = function (type_id, field_id) -{ - var buffer = [0]; - if (type_id > 0xf) buffer.push(type_id & 0xff); - else buffer[0] += (type_id & 0xf) << 4; - - if (field_id > 0xf) buffer.push(field_id & 0xff); - else buffer[0] += field_id & 0xf; - - return buffer; -}; - -function sort_field_compare(a, b) { - // Sort by type id first, then by field id - return a[3].id !== b[3].id ? - a[3].id - b[3].id : - a[2] - b[2]; -}; -SerializedObject._sort_typedef = function (typedef) { - return typedef.sort(sort_field_compare); -}; - -SerializedObject.lookup_type_tx = function (id) { - for (var i in binformat.tx) { - if (!binformat.tx.hasOwnProperty(i)) continue; - - if (binformat.tx[i][0] === id) { - return i; - } - } - - return null; -}; - -exports.SerializedObject = SerializedObject; diff --git a/src/js/serializedtypes.js b/src/js/serializedtypes.js deleted file mode 100644 index a3a2808d81..0000000000 --- a/src/js/serializedtypes.js +++ /dev/null @@ -1,319 +0,0 @@ -/** - * Type definitions for binary format. - * - * This file should not be included directly. Instead, find the format you're - * trying to parse or serialize in binformat.js and pass that to - * SerializedObject.parse() or SerializedObject.serialize(). - */ - -var extend = require('extend'), - utils = require('./utils'), - sjcl = require('../../build/sjcl'); - -var amount = require('./amount'), - UInt160 = amount.UInt160, - Amount = amount.Amount, - Currency= amount.Currency; - -// Shortcuts -var hex = sjcl.codec.hex, - bytes = sjcl.codec.bytes; - -var SerializedType = function (methods) { - extend(this, methods); -}; - -SerializedType.prototype.serialize_hex = function (so, hexData) { - var byteData = bytes.fromBits(hex.toBits(hexData)); - this.serialize_varint(so, byteData.length); - so.append(byteData); -}; - -SerializedType.prototype.serialize_varint = function (so, val) { - if (val < 0) { - throw new Error("Variable integers are unsigned."); - } - if (val <= 192) { - so.append([val]); - } else if (val <= 12,480) { - val -= 193; - so.append([193 + (val >>> 8), val & 0xff]); - } else if (val <= 918744) { - val -= 12481; - so.append([ - 241 + (val >>> 16), - val >>> 8 & 0xff, - val & 0xff - ]); - } else throw new Error("Variable integer overflow."); -}; - -var STInt8 = exports.Int8 = new SerializedType({ - serialize: function (so, val) { - so.append([val & 0xff]); - }, - parse: function (so) { - return so.read(1)[0]; - } -}); - -var STInt16 = exports.Int16 = new SerializedType({ - serialize: function (so, val) { - so.append([ - val >>> 8 & 0xff, - val & 0xff - ]); - }, - parse: function (so) { - // XXX - throw new Error("Parsing Int16 not implemented"); - } -}); - -var STInt32 = exports.Int32 = new SerializedType({ - serialize: function (so, val) { - so.append([ - val >>> 24 & 0xff, - val >>> 16 & 0xff, - val >>> 8 & 0xff, - val & 0xff - ]); - }, - parse: function (so) { - // XXX - throw new Error("Parsing Int32 not implemented"); - } -}); - -var STInt64 = exports.Int64 = new SerializedType({ - serialize: function (so, val) { - // XXX - throw new Error("Serializing Int64 not implemented"); - }, - parse: function (so) { - // XXX - throw new Error("Parsing Int64 not implemented"); - } -}); - -var STHash128 = exports.Hash128 = new SerializedType({ - serialize: function (so, val) { - // XXX - throw new Error("Serializing Hash128 not implemented"); - }, - parse: function (so) { - // XXX - throw new Error("Parsing Hash128 not implemented"); - } -}); - -var STHash256 = exports.Hash256 = new SerializedType({ - serialize: function (so, val) { - // XXX - throw new Error("Serializing Hash256 not implemented"); - }, - parse: function (so) { - // XXX - throw new Error("Parsing Hash256 not implemented"); - } -}); - -var STHash160 = exports.Hash160 = new SerializedType({ - serialize: function (so, val) { - // XXX - throw new Error("Serializing Hash160 not implemented"); - }, - parse: function (so) { - // XXX - throw new Error("Parsing Hash160 not implemented"); - } -}); - -// Internal -var STCurrency = new SerializedType({ - serialize: function (so, val) { - var currency = val.to_json(); - if ("string" === typeof currency && currency.length === 3) { - var currencyCode = currency.toUpperCase(), - currencyData = utils.arraySet(20, 0); - - if (!/^[A-Z]{3}$/.test(currencyCode)) { - throw new Error('Invalid currency code'); - } - - currencyData[12] = currencyCode.charCodeAt(0) & 0xff; - currencyData[13] = currencyCode.charCodeAt(1) & 0xff; - currencyData[14] = currencyCode.charCodeAt(2) & 0xff; - - so.append(currencyData); - } else { - throw new Error('Tried to serialize invalid/unimplemented currency type.'); - } - }, - parse: function (so) { - // XXX - throw new Error("Parsing Currency not implemented"); - } -}); - -var STAmount = exports.Amount = new SerializedType({ - serialize: function (so, val) { - var amount = Amount.from_json(val); - if (!amount.is_valid()) { - throw new Error("Not a valid Amount object."); - } - - // Amount (64-bit integer) - var valueBytes = utils.arraySet(8, 0); - if (amount.is_native()) { - var valueHex = amount._value.toString(16); - - // Enforce correct length (64 bits) - if (valueHex.length > 16) { - throw new Error('Value out of bounds'); - } - while (valueHex.length < 16) { - valueHex = "0" + valueHex; - } - - valueBytes = bytes.fromBits(hex.toBits(valueHex)); - // Clear most significant two bits - these bits should already be 0 if - // Amount enforces the range correctly, but we'll clear them anyway just - // so this code can make certain guarantees about the encoded value. - valueBytes[0] &= 0x3f; - if (!amount.is_negative()) valueBytes[0] |= 0x40; - } else { - var hi = 0, lo = 0; - - // First bit: non-native - hi |= 1 << 31; - - if (!amount.is_zero()) { - // Second bit: non-negative? - if (!amount.is_negative()) hi |= 1 << 30; - - // Next eight bits: offset/exponent - hi |= ((97 + amount._offset) & 0xff) << 22; - - // Remaining 52 bits: mantissa - hi |= amount._value.shiftRight(32).intValue() & 0x3fffff; - lo = amount._value.intValue() & 0xffffffff; - } - - valueBytes = sjcl.codec.bytes.fromBits([hi, lo]); - } - - so.append(valueBytes); - - if (!amount.is_native()) { - // Currency (160-bit hash) - var currency = amount.currency(); - STCurrency.serialize(so, currency); - - // Issuer (160-bit hash) - so.append(amount.issuer().to_bytes()); - } - }, - parse: function (so) { - // XXX - throw new Error("Parsing Amount not implemented"); - } -}); - -var STVL = exports.VariableLength = new SerializedType({ - serialize: function (so, val) { - if ("string" === typeof val) this.serialize_hex(so, val); - else throw new Error("Unknown datatype."); - }, - parse: function (so) { - // XXX - throw new Error("Parsing VL not implemented"); - } -}); - -var STAccount = exports.Account = new SerializedType({ - serialize: function (so, val) { - var account = UInt160.from_json(val); - this.serialize_hex(so, account.to_hex()); - }, - parse: function (so) { - // XXX - throw new Error("Parsing Account not implemented"); - } -}); - -var STPathSet = exports.PathSet = new SerializedType({ - typeBoundary: 0xff, - typeEnd: 0x00, - typeAccount: 0x01, - typeCurrency: 0x10, - typeIssuer: 0x20, - serialize: function (so, val) { - // XXX - for (var i = 0, l = val.length; i < l; i++) { - // Boundary - if (i) STInt8.serialize(so, this.typeBoundary); - - for (var j = 0, l2 = val[i].length; j < l2; j++) { - var entry = val[i][j]; - - var type = 0; - - if (entry.account) type |= this.typeAccount; - if (entry.currency) type |= this.typeCurrency; - if (entry.issuer) type |= this.typeIssuer; - - STInt8.serialize(so, type); - - if (entry.account) { - so.append(UInt160.from_json(entry.account).to_bytes()); - } - if (entry.currency) { - var currency = Currency.from_json(entry.currency); - STCurrency.serialize(so, currency); - } - if (entry.issuer) { - so.append(UInt160.from_json(entry.issuer).to_bytes()); - } - } - } - STInt8.serialize(so, this.typeEnd); - }, - parse: function (so) { - // XXX - throw new Error("Parsing PathSet not implemented"); - } -}); - -var STVector256 = exports.Vector256 = new SerializedType({ - serialize: function (so, val) { - // XXX - throw new Error("Serializing Vector256 not implemented"); - }, - parse: function (so) { - // XXX - throw new Error("Parsing Vector256 not implemented"); - } -}); - -var STObject = exports.Object = new SerializedType({ - serialize: function (so, val) { - // XXX - throw new Error("Serializing Object not implemented"); - }, - parse: function (so) { - // XXX - throw new Error("Parsing Object not implemented"); - } -}); - -var STArray = exports.Array = new SerializedType({ - serialize: function (so, val) { - // XXX - throw new Error("Serializing Array not implemented"); - }, - parse: function (so) { - // XXX - throw new Error("Parsing Array not implemented"); - } -}); diff --git a/src/js/server.js b/src/js/server.js deleted file mode 100644 index 22dcacfa2d..0000000000 --- a/src/js/server.js +++ /dev/null @@ -1,255 +0,0 @@ -var EventEmitter = require('events').EventEmitter; -var util = require('util'); - -var utils = require('./utils'); - -var Server = function (remote, cfg) -{ - EventEmitter.call(this); - - if ("object" !== typeof cfg || "string" !== typeof cfg.url) { - throw new Error("Invalid server configuration."); - } - - this._remote = remote; - this._cfg = cfg; - - this._ws = null; - this._connected = false; - this._should_connect = false; - this._state = null; - - this._id = 0; - this._retry = 0; - - this._requests = {}; - - this.on('message', this._handle_message.bind(this)); - this.on('response_subscribe', this._handle_response_subscribe.bind(this)); -}; - -util.inherits(Server, EventEmitter); - -/** - * Server states that we will treat as the server being online. - * - * Our requirements are that the server can process transactions and notify - * us of changes. - */ -Server.online_states = [ - 'proposing', - 'validating', - 'full' -]; - -Server.prototype.connect = function () -{ - var self = this; - - // We don't connect if we believe we're already connected. This means we have - // recently received a message from the server and the WebSocket has not - // reported any issues either. If we do fail to ping or the connection drops, - // we will automatically reconnect. - if (this._connected === true) return; - - if (this._remote.trace) console.log("server: connect: %s", this._cfg.url); - - // Ensure any existing socket is given the command to close first. - if (this._ws) this._ws.close(); - - var WebSocket = require('ws'); - var ws = this._ws = new WebSocket(this._cfg.url); - - this._should_connect = true; - - self.emit('connecting'); - - ws.onopen = function () { - // If we are no longer the active socket, simply ignore any event - if (ws !== self._ws) return; - - self.emit('socket_open'); - - // Subscribe to events - var request = self._remote._server_prepare_subscribe(); - self.request(request); - }; - - ws.onerror = function (e) { - // If we are no longer the active socket, simply ignore any event - if (ws !== self._ws) return; - - if (self._remote.trace) console.log("server: onerror: %s", e.data || e); - - // Most connection errors for WebSockets are conveyed as "close" events with - // code 1006. This is done for security purposes and therefore unlikely to - // ever change. - - // This means that this handler is hardly ever called in practice. If it is, - // it probably means the server's WebSocket implementation is corrupt, or - // the connection is somehow producing corrupt data. - - // Most WebSocket applications simply log and ignore this error. Once we - // support for multiple servers, we may consider doing something like - // lowering this server's quality score. - - // However, in Node.js this event may be triggered instead of the close - // event, so we need to handle it. - handleConnectionClose(); - }; - - // Failure to open. - ws.onclose = function () { - // If we are no longer the active socket, simply ignore any event - if (ws !== self._ws) return; - - if (self._remote.trace) console.log("server: onclose: %s", ws.readyState); - - handleConnectionClose(); - }; - - function handleConnectionClose() - { - self.emit('socket_close'); - self._set_state('offline'); - - // Prevent additional events from this socket - ws.onopen = ws.onerror = ws.onclose = ws.onmessage = function () {}; - - // Should we be connected? - if (!self._should_connect) return; - - // Delay and retry. - self._retry += 1; - self._retry_timer = setTimeout(function () { - if (self._remote.trace) console.log("server: retry"); - - if (!self._should_connect) return; - self.connect(); - }, self._retry < 40 - ? 1000/20 // First, for 2 seconds: 20 times per second - : self._retry < 40+60 - ? 1000 // Then, for 1 minute: once per second - : self._retry < 40+60+60 - ? 10*1000 // Then, for 10 minutes: once every 10 seconds - : 30*1000); // Then: once every 30 seconds - } - - ws.onmessage = function (msg) { - self.emit('message', msg.data); - }; -}; - -Server.prototype.disconnect = function () -{ - this._should_connect = false; - this._set_state('offline'); - - if (this.ws) { - this.ws.close(); - } -}; - -/** - * Submit a Request object to this server. - */ -Server.prototype.request = function (request) -{ - var self = this; - - // Only bother if we are still connected. - if (self._ws) { - request.message.id = self._id; - - self._requests[request.message.id] = request; - - // Advance message ID - self._id++; - - if (self._state === "online" || - (request.message.command === "subscribe" && self._ws.readyState === 1)) { - if (self._remote.trace) { - utils.logObject("server: request: %s", request.message); - } - - self._ws.send(JSON.stringify(request.message)); - } else { - // XXX There are many ways to make self smarter. - self.once('connect', function () { - if (self._remote.trace) { - utils.logObject("server: request: %s", request.message); - } - self._ws.send(JSON.stringify(request.message)); - }); - } - } else { - if (self._remote.trace) { - utils.logObject("server: request: DROPPING: %s", request.message); - } - } -}; - -Server.prototype._set_state = function (state) { - if (state !== this._state) { - this._state = state; - - this.emit('state', state); - if (state === 'online') { - this.emit('connect'); - } else if (state === 'offline') { - this.emit('disconnect'); - } - } -}; - -Server.prototype._handle_message = function (json) { - var self = this; - - var message = JSON.parse(json); - - if (message.type === 'response') { - // A response to a request. - var request = self._requests[message.id]; - - delete self._requests[message.id]; - - if (!request) { - if (self._remote.trace) utils.logObject("server: UNEXPECTED: %s", message); - } else if ('success' === message.status) { - if (self._remote.trace) utils.logObject("server: response: %s", message); - - request.emit('success', message.result); - self.emit('response_'+request.message.command, message.result, request, message); - self._remote.emit('response_'+request.message.command, message.result, request, message); - } else if (message.error) { - if (self._remote.trace) utils.logObject("server: error: %s", message); - - request.emit('error', { - 'error' : 'remoteError', - 'error_message' : 'Remote reported an error.', - 'remote' : message - }); - } - } else if (message.type === 'serverStatus') { - // This message is only received when online. As we are connected, it is the definative final state. - self._set_state( - Server.online_states.indexOf(message.server_status) !== -1 - ? 'online' - : 'offline'); - } -}; - -Server.prototype._handle_response_subscribe = function (message) -{ - var self = this; - - self._server_status = message.server_status; - - if (Server.online_states.indexOf(message.server_status) !== -1) { - self._set_state('online'); - } -}; - -exports.Server = Server; - -// vim:sw=2:sts=2:ts=8:et diff --git a/src/js/sjcl b/src/js/sjcl deleted file mode 160000 index dbdef434e7..0000000000 --- a/src/js/sjcl +++ /dev/null @@ -1 +0,0 @@ -Subproject commit dbdef434e76c3f16835f3126a7ff1c717b1ce8af diff --git a/src/js/sjcl-custom/sjcl-ecdsa-der.js b/src/js/sjcl-custom/sjcl-ecdsa-der.js deleted file mode 100644 index 30fe439d87..0000000000 --- a/src/js/sjcl-custom/sjcl-ecdsa-der.js +++ /dev/null @@ -1,34 +0,0 @@ -sjcl.ecc.ecdsa.secretKey.prototype.signDER = function(hash, paranoia) { - return this.encodeDER(this.sign(hash, paranoia)); -}; - -sjcl.ecc.ecdsa.secretKey.prototype.encodeDER = function(rs) { - var w = sjcl.bitArray, - R = this._curve.r, - l = R.bitLength(); - - var rb = sjcl.codec.bytes.fromBits(w.bitSlice(rs,0,l)), - sb = sjcl.codec.bytes.fromBits(w.bitSlice(rs,l,2*l)); - - // Drop empty leading bytes - while (!rb[0] && rb.length) rb.shift(); - while (!sb[0] && sb.length) sb.shift(); - - // If high bit is set, prepend an extra zero byte (DER signed integer) - if (rb[0] & 0x80) rb.unshift(0); - if (sb[0] & 0x80) sb.unshift(0); - - var buffer = [].concat( - 0x30, - 4 + rb.length + sb.length, - 0x02, - rb.length, - rb, - 0x02, - sb.length, - sb - ); - - return sjcl.codec.bytes.toBits(buffer); -}; - diff --git a/src/js/sjcl-custom/sjcl-extramath.js b/src/js/sjcl-custom/sjcl-extramath.js deleted file mode 100755 index 03b338b7a4..0000000000 --- a/src/js/sjcl-custom/sjcl-extramath.js +++ /dev/null @@ -1,61 +0,0 @@ -sjcl.bn.ZERO = new sjcl.bn(0); - -/** [ this / that , this % that ] */ -sjcl.bn.prototype.divRem = function (that) { - if (typeof(that) !== "object") { that = new this._class(that); } - var thisa = this.abs(), thata = that.abs(), quot = new this._class(0), - ci = 0; - if (!thisa.greaterEquals(thata)) { - this.initWith(0); - return this; - } else if (thisa.equals(thata)) { - this.initWith(1); - return this; - } - - for (; thisa.greaterEquals(thata); ci++) { - thata.doubleM(); - } - for (; ci > 0; ci--) { - quot.doubleM(); - thata.halveM(); - if (thisa.greaterEquals(thata)) { - quot.addM(1); - thisa.subM(that).normalize(); - } - } - return [quot, thisa]; -}; - -/** this /= that (rounded to nearest int) */ -sjcl.bn.prototype.divRound = function (that) { - var dr = this.divRem(that), quot = dr[0], rem = dr[1]; - - if (rem.doubleM().greaterEquals(that)) { - quot.addM(1); - } - - return quot; -}; - -/** this /= that (rounded down) */ -sjcl.bn.prototype.div = function (that) { - var dr = this.divRem(that); - return dr[0]; -}; - -sjcl.bn.prototype.sign = function () { - return this.greaterEquals(sjcl.bn.ZERO) ? 1 : -1; - }; - -/** -this */ -sjcl.bn.prototype.neg = function () { - return sjcl.bn.ZERO.sub(this); -}; - -/** |this| */ -sjcl.bn.prototype.abs = function () { - if (this.sign() === -1) { - return this.neg(); - } else return this; -}; diff --git a/src/js/sjcl-custom/sjcl-ripemd160.js b/src/js/sjcl-custom/sjcl-ripemd160.js deleted file mode 100755 index 4ee7b9246d..0000000000 --- a/src/js/sjcl-custom/sjcl-ripemd160.js +++ /dev/null @@ -1,207 +0,0 @@ -/** @fileOverview Javascript RIPEMD-160 implementation. - * - * @author Artem S Vybornov - */ -(function() { - -/** - * Context for a RIPEMD-160 operation in progress. - * @constructor - * @class RIPEMD, 160 bits. - */ -sjcl.hash.ripemd160 = function (hash) { - if (hash) { - this._h = hash._h.slice(0); - this._buffer = hash._buffer.slice(0); - this._length = hash._length; - } else { - this.reset(); - } -}; - -/** - * Hash a string or an array of words. - * @static - * @param {bitArray|String} data the data to hash. - * @return {bitArray} The hash value, an array of 5 big-endian words. - */ -sjcl.hash.ripemd160.hash = function (data) { - return (new sjcl.hash.ripemd160()).update(data).finalize(); -}; - -sjcl.hash.ripemd160.prototype = { - /** - * Reset the hash state. - * @return this - */ - reset: function () { - this._h = _h0.slice(0); - this._buffer = []; - this._length = 0; - return this; - }, - - /** - * Reset the hash state. - * @param {bitArray|String} data the data to hash. - * @return this - */ - update: function (data) { - if ( typeof data === "string" ) - data = sjcl.codec.utf8String.toBits(data); - - var i, b = this._buffer = sjcl.bitArray.concat(this._buffer, data), - ol = this._length, - nl = this._length = ol + sjcl.bitArray.bitLength(data); - for (i = 512+ol & -512; i <= nl; i+= 512) { - var words = b.splice(0,16); - for ( var w = 0; w < 16; ++w ) - words[w] = _cvt(words[w]); - - _block.call( this, words ); - } - - return this; - }, - - /** - * Complete hashing and output the hash value. - * @return {bitArray} The hash value, an array of 5 big-endian words. - */ - finalize: function () { - var b = sjcl.bitArray.concat( this._buffer, [ sjcl.bitArray.partial(1,1) ] ), - l = ( this._length + 1 ) % 512, - z = ( l > 448 ? 512 : 448 ) - l % 448, - zp = z % 32; - - if ( zp > 0 ) - b = sjcl.bitArray.concat( b, [ sjcl.bitArray.partial(zp,0) ] ) - for ( ; z >= 32; z -= 32 ) - b.push(0); - - b.push( _cvt( this._length | 0 ) ); - b.push( _cvt( Math.floor(this._length / 0x100000000) ) ); - - while ( b.length ) { - var words = b.splice(0,16); - for ( var w = 0; w < 16; ++w ) - words[w] = _cvt(words[w]); - - _block.call( this, words ); - } - - var h = this._h; - this.reset(); - - for ( var w = 0; w < 5; ++w ) - h[w] = _cvt(h[w]); - - return h; - } -}; - -var _h0 = [ 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0 ]; - -var _k1 = [ 0x00000000, 0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xa953fd4e ]; -var _k2 = [ 0x50a28be6, 0x5c4dd124, 0x6d703ef3, 0x7a6d76e9, 0x00000000 ]; -for ( var i = 4; i >= 0; --i ) { - for ( var j = 1; j < 16; ++j ) { - _k1.splice(i,0,_k1[i]); - _k2.splice(i,0,_k2[i]); - } -} - -var _r1 = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8, - 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12, - 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2, - 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13 ]; -var _r2 = [ 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, - 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2, - 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13, - 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14, - 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11 ]; - -var _s1 = [ 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8, - 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12, - 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5, - 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12, - 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6 ]; -var _s2 = [ 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6, - 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11, - 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5, - 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8, - 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11 ]; - -function _f0(x,y,z) { - return x ^ y ^ z; -}; - -function _f1(x,y,z) { - return (x & y) | (~x & z); -}; - -function _f2(x,y,z) { - return (x | ~y) ^ z; -}; - -function _f3(x,y,z) { - return (x & z) | (y & ~z); -}; - -function _f4(x,y,z) { - return x ^ (y | ~z); -}; - -function _rol(n,l) { - return (n << l) | (n >>> (32-l)); -} - -function _cvt(n) { - return ( (n & 0xff << 0) << 24 ) - | ( (n & 0xff << 8) << 8 ) - | ( (n & 0xff << 16) >>> 8 ) - | ( (n & 0xff << 24) >>> 24 ); -} - -function _block(X) { - var A1 = this._h[0], B1 = this._h[1], C1 = this._h[2], D1 = this._h[3], E1 = this._h[4], - A2 = this._h[0], B2 = this._h[1], C2 = this._h[2], D2 = this._h[3], E2 = this._h[4]; - - var j = 0, T; - - for ( ; j < 16; ++j ) { - T = _rol( A1 + _f0(B1,C1,D1) + X[_r1[j]] + _k1[j], _s1[j] ) + E1; - A1 = E1; E1 = D1; D1 = _rol(C1,10); C1 = B1; B1 = T; - T = _rol( A2 + _f4(B2,C2,D2) + X[_r2[j]] + _k2[j], _s2[j] ) + E2; - A2 = E2; E2 = D2; D2 = _rol(C2,10); C2 = B2; B2 = T; } - for ( ; j < 32; ++j ) { - T = _rol( A1 + _f1(B1,C1,D1) + X[_r1[j]] + _k1[j], _s1[j] ) + E1; - A1 = E1; E1 = D1; D1 = _rol(C1,10); C1 = B1; B1 = T; - T = _rol( A2 + _f3(B2,C2,D2) + X[_r2[j]] + _k2[j], _s2[j] ) + E2; - A2 = E2; E2 = D2; D2 = _rol(C2,10); C2 = B2; B2 = T; } - for ( ; j < 48; ++j ) { - T = _rol( A1 + _f2(B1,C1,D1) + X[_r1[j]] + _k1[j], _s1[j] ) + E1; - A1 = E1; E1 = D1; D1 = _rol(C1,10); C1 = B1; B1 = T; - T = _rol( A2 + _f2(B2,C2,D2) + X[_r2[j]] + _k2[j], _s2[j] ) + E2; - A2 = E2; E2 = D2; D2 = _rol(C2,10); C2 = B2; B2 = T; } - for ( ; j < 64; ++j ) { - T = _rol( A1 + _f3(B1,C1,D1) + X[_r1[j]] + _k1[j], _s1[j] ) + E1; - A1 = E1; E1 = D1; D1 = _rol(C1,10); C1 = B1; B1 = T; - T = _rol( A2 + _f1(B2,C2,D2) + X[_r2[j]] + _k2[j], _s2[j] ) + E2; - A2 = E2; E2 = D2; D2 = _rol(C2,10); C2 = B2; B2 = T; } - for ( ; j < 80; ++j ) { - T = _rol( A1 + _f4(B1,C1,D1) + X[_r1[j]] + _k1[j], _s1[j] ) + E1; - A1 = E1; E1 = D1; D1 = _rol(C1,10); C1 = B1; B1 = T; - T = _rol( A2 + _f0(B2,C2,D2) + X[_r2[j]] + _k2[j], _s2[j] ) + E2; - A2 = E2; E2 = D2; D2 = _rol(C2,10); C2 = B2; B2 = T; } - - T = this._h[1] + C1 + D2; - this._h[1] = this._h[2] + D1 + E2; - this._h[2] = this._h[3] + E1 + A2; - this._h[3] = this._h[4] + A1 + B2; - this._h[4] = this._h[0] + B1 + C2; - this._h[0] = T; -} - -})(); diff --git a/src/js/sjcl-custom/sjcl-secp256k1.js b/src/js/sjcl-custom/sjcl-secp256k1.js deleted file mode 100755 index 4d34db7f17..0000000000 --- a/src/js/sjcl-custom/sjcl-secp256k1.js +++ /dev/null @@ -1,72 +0,0 @@ -// ----- for secp256k1 ------ - -// Overwrite NIST-P256 with secp256k1 so we're on even footing -sjcl.ecc.curves.c256 = new sjcl.ecc.curve( - sjcl.bn.pseudoMersennePrime(256, [[0,-1],[4,-1],[6,-1],[7,-1],[8,-1],[9,-1],[32,-1]]), - "0x14551231950b75fc4402da1722fc9baee", - 0, - 7, - "0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798", - "0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8" -); - -// Replace point addition and doubling algorithms -// NIST-P256 is a=-3, we need algorithms for a=0 -sjcl.ecc.pointJac.prototype.add = function(T) { - var S = this; - if (S.curve !== T.curve) { - throw("sjcl.ecc.add(): Points must be on the same curve to add them!"); - } - - if (S.isIdentity) { - return T.toJac(); - } else if (T.isIdentity) { - return S; - } - - var z1z1 = S.z.square(); - var h = T.x.mul(z1z1).subM(S.x); - var s2 = T.y.mul(S.z).mul(z1z1); - - if (h.equals(0)) { - if (S.y.equals(T.y.mul(z1z1.mul(S.z)))) { - // same point - return S.doubl(); - } else { - // inverses - return new sjcl.ecc.pointJac(S.curve); - } - } - - var hh = h.square(); - var i = hh.copy().doubleM().doubleM(); - var j = h.mul(i); - var r = s2.sub(S.y).doubleM(); - var v = S.x.mul(i); - - var x = r.square().subM(j).subM(v.copy().doubleM()); - var y = r.mul(v.sub(x)).subM(S.y.mul(j).doubleM()); - var z = S.z.add(h).square().subM(z1z1).subM(hh); - - return new sjcl.ecc.pointJac(this.curve,x,y,z); -}; - -sjcl.ecc.pointJac.prototype.doubl = function () { - if (this.isIdentity) { return this; } - - var a = this.x.square(); - var b = this.y.square(); - var c = b.square(); - var d = this.x.add(b).square().subM(a).subM(c).doubleM(); - var e = a.mul(3); - var f = e.square(); - var x = f.sub(d.copy().doubleM()); - var y = e.mul(d.sub(x)).subM(c.doubleM().doubleM().doubleM()); - var z = this.y.mul(this.z).doubleM(); - return new sjcl.ecc.pointJac(this.curve, x, y, z); -}; - -sjcl.ecc.point.prototype.toBytesCompressed = function () { - var header = this.y.mod(2).toString() == "0x0" ? 0x02 : 0x03; - return [header].concat(sjcl.codec.bytes.fromBits(this.x.toBits())) -}; diff --git a/src/js/sjcl-custom/sjcl-validecc.js b/src/js/sjcl-custom/sjcl-validecc.js deleted file mode 100644 index 99ecde393d..0000000000 --- a/src/js/sjcl-custom/sjcl-validecc.js +++ /dev/null @@ -1,30 +0,0 @@ -sjcl.ecc.ecdsa.secretKey.prototype = { - sign: function(hash, paranoia) { - var R = this._curve.r, - l = R.bitLength(), - k = sjcl.bn.random(R.sub(1), paranoia).add(1), - r = this._curve.G.mult(k).x.mod(R), - s = sjcl.bn.fromBits(hash).add(r.mul(this._exponent)).mul(k.inverseMod(R)).mod(R); - - return sjcl.bitArray.concat(r.toBits(l), s.toBits(l)); - } -}; - -sjcl.ecc.ecdsa.publicKey.prototype = { - verify: function(hash, rs) { - var w = sjcl.bitArray, - R = this._curve.r, - l = R.bitLength(), - r = sjcl.bn.fromBits(w.bitSlice(rs,0,l)), - s = sjcl.bn.fromBits(w.bitSlice(rs,l,2*l)), - sInv = s.modInverse(R), - hG = sjcl.bn.fromBits(hash).mul(sInv).mod(R), - hA = r.mul(sInv).mod(R), - r2 = this._curve.G.mult2(hG, hA, this._point).x; - - if (r.equals(0) || s.equals(0) || r.greaterEquals(R) || s.greaterEquals(R) || !r2.equals(r)) { - throw (new sjcl.exception.corrupt("signature didn't check out")); - } - return true; - } -}; diff --git a/src/js/transaction.js b/src/js/transaction.js deleted file mode 100644 index c83ad51da9..0000000000 --- a/src/js/transaction.js +++ /dev/null @@ -1,680 +0,0 @@ -// -// Transactions -// -// Construction: -// remote.transaction() // Build a transaction object. -// .offer_create(...) // Set major parameters. -// .set_flags() // Set optional parameters. -// .on() // Register for events. -// .submit(); // Send to network. -// -// Events: -// 'success' : Transaction submitted without error. -// 'error' : Error submitting transaction. -// 'proposed' : Advisory proposed status transaction. -// - A client should expect 0 to multiple results. -// - Might not get back. The remote might just forward the transaction. -// - A success could be reverted in final. -// - local error: other remotes might like it. -// - malformed error: local server thought it was malformed. -// - The client should only trust this when talking to a trusted server. -// 'final' : Final status of transaction. -// - Only expect a final from dishonest servers after a tesSUCCESS or ter*. -// 'lost' : Gave up looking for on ledger_closed. -// 'pending' : Transaction was not found on ledger_closed. -// 'state' : Follow the state of a transaction. -// 'client_submitted' - Sent to remote -// |- 'remoteError' - Remote rejected transaction. -// \- 'client_proposed' - Remote provisionally accepted transaction. -// |- 'client_missing' - Transaction has not appeared in ledger as expected. -// | |\- 'client_lost' - No longer monitoring missing transaction. -// |/ -// |- 'tesSUCCESS' - Transaction in ledger as expected. -// |- 'ter...' - Transaction failed. -// \- 'tec...' - Transaction claimed fee only. -// -// Notes: -// - All transactions including those with local and malformed errors may be -// forwarded anyway. -// - A malicous server can: -// - give any proposed result. -// - it may declare something correct as incorrect or something correct as incorrect. -// - it may not communicate with the rest of the network. -// - may or may not forward. -// - -var EventEmitter = require('events').EventEmitter; -var util = require('util'); - -var sjcl = require('../../build/sjcl'); - -var Amount = require('./amount').Amount; -var Currency = require('./amount').Currency; -var UInt160 = require('./amount').UInt160; -var Seed = require('./seed').Seed; -var SerializedObject = require('./serializedobject').SerializedObject; - -var config = require('./config'); - -var SUBMIT_MISSING = 4; // Report missing. -var SUBMIT_LOST = 8; // Give up tracking. - -// A class to implement transactions. -// - Collects parameters -// - Allow event listeners to be attached to determine the outcome. -var Transaction = function (remote) { - EventEmitter.call(this); - - // YYY Make private as many variables as possible. - var self = this; - - this.callback = undefined; - this.remote = remote; - this._secret = undefined; - this._build_path = false; - this.tx_json = { // Transaction data. - 'Flags' : 0, // XXX Would be nice if server did not require this. - }; - this.hash = undefined; - this.submit_index = undefined; // ledger_current_index was this when transaction was submited. - this.state = undefined; // Under construction. - this.finalized = false; - - this.on('success', function (message) { - if (message.engine_result) { - self.hash = message.tx_json.hash; - - self.set_state('client_proposed'); - - self.emit('proposed', { - 'tx_json' : message.tx_json, - 'result' : message.engine_result, - 'result_code' : message.engine_result_code, - 'result_message' : message.engine_result_message, - 'rejected' : self.isRejected(message.engine_result_code), // If server is honest, don't expect a final if rejected. - }); - } - }); - - this.on('error', function (message) { - // Might want to give more detailed information. - self.set_state('remoteError'); - }); -}; - -util.inherits(Transaction, EventEmitter); - -// XXX This needs to be determined from the network. -Transaction.fees = { - 'default' : Amount.from_json("10"), - 'nickname_create' : Amount.from_json("1000"), - 'offer' : Amount.from_json("10"), -}; - -Transaction.flags = { - 'OfferCreate' : { - 'Passive' : 0x00010000, - 'ImmediateOrCancel' : 0x00020000, - 'FillOrKill' : 0x00040000, - 'Sell' : 0x00080000, - }, - - 'Payment' : { - 'NoRippleDirect' : 0x00010000, - 'PartialPayment' : 0x00020000, - 'LimitQuality' : 0x00040000, - }, -}; - -Transaction.formats = require('./binformat').tx; - -Transaction.HASH_SIGN = 0x53545800; -Transaction.HASH_SIGN_TESTNET = 0x73747800; - -Transaction.prototype.consts = { - 'telLOCAL_ERROR' : -399, - 'temMALFORMED' : -299, - 'tefFAILURE' : -199, - 'terRETRY' : -99, - 'tesSUCCESS' : 0, - 'tecCLAIMED' : 100, -}; - -Transaction.prototype.isTelLocal = function (ter) { - return ter >= this.consts.telLOCAL_ERROR && ter < this.consts.temMALFORMED; -}; - -Transaction.prototype.isTemMalformed = function (ter) { - return ter >= this.consts.temMALFORMED && ter < this.consts.tefFAILURE; -}; - -Transaction.prototype.isTefFailure = function (ter) { - return ter >= this.consts.tefFAILURE && ter < this.consts.terRETRY; -}; - -Transaction.prototype.isTerRetry = function (ter) { - return ter >= this.consts.terRETRY && ter < this.consts.tesSUCCESS; -}; - -Transaction.prototype.isTepSuccess = function (ter) { - return ter >= this.consts.tesSUCCESS; -}; - -Transaction.prototype.isTecClaimed = function (ter) { - return ter >= this.consts.tecCLAIMED; -}; - -Transaction.prototype.isRejected = function (ter) { - return this.isTelLocal(ter) || this.isTemMalformed(ter) || this.isTefFailure(ter); -}; - -Transaction.prototype.set_state = function (state) { - if (this.state !== state) { - this.state = state; - this.emit('state', state); - } -}; - -/** - * Attempts to complete the transaction for submission. - * - * This function seeks to fill out certain fields, such as Fee and - * SigningPubKey, which can be determined by the library based on network - * information and other fields. - */ -Transaction.prototype.complete = function () { - var tx_json = this.tx_json; - - if (undefined === tx_json.Fee && this.remote.local_fee) { - tx_json.Fee = Transaction.fees['default'].to_json(); - } - - if (undefined === tx_json.SigningPubKey && (!this.remote || this.remote.local_signing)) { - var seed = Seed.from_json(this._secret); - var key = seed.get_key(this.tx_json.Account); - tx_json.SigningPubKey = key.to_hex_pub(); - } -}; - -Transaction.prototype.serialize = function () { - return SerializedObject.from_json(this.tx_json); -}; - -Transaction.prototype.signing_hash = function () { - var prefix = config.testnet - ? Transaction.HASH_SIGN_TESTNET - : Transaction.HASH_SIGN; - - return SerializedObject.from_json(this.tx_json).signing_hash(prefix); -}; - -Transaction.prototype.sign = function () { - var seed = Seed.from_json(this._secret), - hash = this.signing_hash(); - - var key = seed.get_key(this.tx_json.Account), - sig = key.sign(hash, 0), - hex = sjcl.codec.hex.fromBits(sig).toUpperCase(); - - this.tx_json.TxnSignature = hex; -}; - -// Submit a transaction to the network. -// XXX Don't allow a submit without knowing ledger_index. -// XXX Have a network canSubmit(), post events for following. -// XXX Also give broader status for tracking through network disconnects. -// callback = function (status, info) { -// // status is final status. Only works under a ledger_accepting conditions. -// switch status: -// case 'tesSUCCESS': all is well. -// case 'tejSecretUnknown': unable to sign transaction - secret unknown -// case 'tejServerUntrusted': sending secret to untrusted server. -// case 'tejInvalidAccount': locally detected error. -// case 'tejLost': locally gave up looking -// default: some other TER -// } -Transaction.prototype.submit = function (callback) { - var self = this; - var tx_json = this.tx_json; - - this.callback = callback; - - if ('string' !== typeof tx_json.Account) - { - (this.callback || this.emit)('error', { - 'error' : 'tejInvalidAccount', - 'error_message' : 'Bad account.' - }); - return this; - } - - // YYY Might check paths for invalid accounts. - - this.complete(); - - if (this.callback || this.listeners('final').length || this.listeners('lost').length || this.listeners('pending').length) { - // There are listeners for callback, 'final', 'lost', or 'pending' arrange to emit them. - - this.submit_index = this.remote._ledger_current_index; - - // When a ledger closes, look for the result. - var on_ledger_closed = function (message) { - var ledger_hash = message.ledger_hash; - var ledger_index = message.ledger_index; - var stop = false; - -// XXX make sure self.hash is available. - self.remote.request_transaction_entry(self.hash) - .ledger_hash(ledger_hash) - .on('success', function (message) { - if (self.finalized) return; - - self.set_state(message.metadata.TransactionResult); - self.remote.removeListener('ledger_closed', on_ledger_closed); - self.emit('final', message); - self.finalized = true; - - if (self.callback) - self.callback(message.metadata.TransactionResult, message); - }) - .on('error', function (message) { - if (self.finalized) return; - - if ('remoteError' === message.error - && 'transactionNotFound' === message.remote.error) { - if (self.submit_index + SUBMIT_LOST < ledger_index) { - self.set_state('client_lost'); // Gave up. - self.emit('lost'); - - if (self.callback) - self.callback('tejLost', message); - - self.remote.removeListener('ledger_closed', on_ledger_closed); - self.emit('final', message); - self.finalized = true; - } - else if (self.submit_index + SUBMIT_MISSING < ledger_index) { - self.set_state('client_missing'); // We don't know what happened to transaction, still might find. - self.emit('pending'); - } - else { - self.emit('pending'); - } - } - // XXX Could log other unexpectedness. - }) - .request(); - }; - - this.remote.on('ledger_closed', on_ledger_closed); - - if (this.callback) { - this.on('error', function (message) { - self.callback(message.error, message); - }); - } - } - - this.set_state('client_submitted'); - - if (self.remote.local_sequence && !self.tx_json.Sequence) { - self.tx_json.Sequence = this.remote.account_seq(self.tx_json.Account, 'ADVANCE'); - // console.log("Sequence: %s", self.tx_json.Sequence); - - if (!self.tx_json.Sequence) { - // Look in the last closed ledger. - this.remote.account_seq_cache(self.tx_json.Account, false) - .on('success_account_seq_cache', function () { - // Try again. - self.submit(); - }) - .on('error_account_seq_cache', function (message) { - // XXX Maybe be smarter about this. Don't want to trust an untrusted server for this seq number. - - // Look in the current ledger. - self.remote.account_seq_cache(self.tx_json.Account, 'CURRENT') - .on('success_account_seq_cache', function () { - // Try again. - self.submit(); - }) - .on('error_account_seq_cache', function (message) { - // Forward errors. - self.emit('error', message); - }) - .request(); - }) - .request(); - return this; - } - - // If the transaction fails we want to either undo incrementing the sequence - // or submit a noop transaction to consume the sequence remotely. - this.on('success', function (res) { - if (!res || "string" !== typeof res.engine_result) return; - - switch (res.engine_result.slice(0, 3)) { - // Synchronous local error - case 'tej': - self.remote.account_seq(self.tx_json.Account, 'REWIND'); - break; - // XXX: What do we do in case of ter? - case 'tel': - case 'tem': - case 'tef': - // XXX Once we have a transaction submission manager class, we can - // check if there are any other transactions pending. If there are, - // we should submit a dummy transaction to ensure those - // transactions are still valid. - //var noop = self.remote.transaction().account_set(self.tx_json.Account); - //noop.submit(); - - // XXX Hotfix. This only works if no other transactions are pending. - self.remote.account_seq(self.tx_json.Account, 'REWIND'); - break; - } - }); - } - - // Prepare request - - var request = this.remote.request_submit(); - - // Forward successes and errors. - request.on('success', function (message) { - self.emit('success', message); - }); - request.on('error', function (message) { - self.emit('error', message); - }); - - if (!this._secret && !this.tx_json.Signature) { - this.emit('error', { - 'result' : 'tejSecretUnknown', - 'result_message' : "Could not sign transactions because we." - }); - return this; - } else if (this.remote.local_signing) { - this.sign(); - request.tx_blob(this.serialize().to_hex()); - } else { - if (!this.remote.trusted) { - this.emit('error', { - 'result' : 'tejServerUntrusted', - 'result_message' : "Attempt to give a secret to an untrusted server." - }); - return this; - } - - request.secret(this._secret); - request.build_path(this._build_path); - request.tx_json(this.tx_json); - } - - request.request(); - - return this; -} - -// -// Set options for Transactions -// - -// --> build: true, to have server blindly construct a path. -// -// "blindly" because the sender has no idea of the actual cost except that is must be less than send max. -Transaction.prototype.build_path = function (build) { - this._build_path = build; - - return this; -} - -// tag should be undefined or a 32 bit integer. -// YYY Add range checking for tag. -Transaction.prototype.destination_tag = function (tag) { - if (undefined !== tag) - this.tx_json.DestinationTag = tag; - - return this; -} - -Transaction._path_rewrite = function (path) { - var path_new = []; - - for (var i = 0, l = path.length; i < l; i++) { - var node = path[i]; - var node_new = {}; - - if ('account' in node) - node_new.account = UInt160.json_rewrite(node.account); - - if ('issuer' in node) - node_new.issuer = UInt160.json_rewrite(node.issuer); - - if ('currency' in node) - node_new.currency = Currency.json_rewrite(node.currency); - - path_new.push(node_new); - } - - return path_new; -} - -Transaction.prototype.path_add = function (path) { - this.tx_json.Paths = this.tx_json.Paths || []; - this.tx_json.Paths.push(Transaction._path_rewrite(path)); - - return this; -} - -// --> paths: undefined or array of path -// A path is an array of objects containing some combination of: account, currency, issuer -Transaction.prototype.paths = function (paths) { - for (var i = 0, l = paths.length; i < l; i++) { - this.path_add(paths[i]); - } - - return this; -} - -// If the secret is in the config object, it does not need to be provided. -Transaction.prototype.secret = function (secret) { - this._secret = secret; -} - -Transaction.prototype.send_max = function (send_max) { - if (send_max) - this.tx_json.SendMax = Amount.json_rewrite(send_max); - - return this; -} - -// tag should be undefined or a 32 bit integer. -// YYY Add range checking for tag. -Transaction.prototype.source_tag = function (tag) { - if (undefined !== tag) - this.tx_json.SourceTag = tag; - - return this; -} - -// --> rate: In billionths. -Transaction.prototype.transfer_rate = function (rate) { - this.tx_json.TransferRate = Number(rate); - - if (this.tx_json.TransferRate < 1e9) - throw 'invalidTransferRate'; - - return this; -} - -// Add flags to a transaction. -// --> flags: undefined, _flag_, or [ _flags_ ] -Transaction.prototype.set_flags = function (flags) { - if (flags) { - var transaction_flags = Transaction.flags[this.tx_json.TransactionType]; - - if (undefined == this.tx_json.Flags) // We plan to not define this field on new Transaction. - this.tx_json.Flags = 0; - - var flag_set = 'object' === typeof flags ? flags : [ flags ]; - - for (var index in flag_set) { - if (!flag_set.hasOwnProperty(index)) continue; - - var flag = flag_set[index]; - - if (flag in transaction_flags) { - this.tx_json.Flags += transaction_flags[flag]; - } else { - // XXX Immediately report an error or mark it. - } - } - } - - return this; -} - -// -// Transactions -// - -Transaction.prototype._account_secret = function (account) { - // Fill in secret from remote, if available. - return this.remote.secrets[account]; -}; - -// Options: -// .domain() NYI -// .message_key() NYI -// .transfer_rate() -// .wallet_locator() NYI -// .wallet_size() NYI -Transaction.prototype.account_set = function (src) { - this._secret = this._account_secret(src); - this.tx_json.TransactionType = 'AccountSet'; - this.tx_json.Account = UInt160.json_rewrite(src); - - return this; -}; - -Transaction.prototype.claim = function (src, generator, public_key, signature) { - this._secret = this._account_secret(src); - this.tx_json.TransactionType = 'Claim'; - this.tx_json.Generator = generator; - this.tx_json.PublicKey = public_key; - this.tx_json.Signature = signature; - - return this; -}; - -Transaction.prototype.offer_cancel = function (src, sequence) { - this._secret = this._account_secret(src); - this.tx_json.TransactionType = 'OfferCancel'; - this.tx_json.Account = UInt160.json_rewrite(src); - this.tx_json.OfferSequence = Number(sequence); - - return this; -}; - -// Options: -// .set_flags() -// --> expiration : Date or Number -Transaction.prototype.offer_create = function (src, taker_pays, taker_gets, expiration) { - this._secret = this._account_secret(src); - this.tx_json.TransactionType = 'OfferCreate'; - this.tx_json.Account = UInt160.json_rewrite(src); - this.tx_json.TakerPays = Amount.json_rewrite(taker_pays); - this.tx_json.TakerGets = Amount.json_rewrite(taker_gets); - - if (this.remote.local_fee) { - this.tx_json.Fee = Transaction.fees.offer.to_json(); - } - - if (expiration) - this.tx_json.Expiration = Date === expiration.constructor - ? expiration.getTime() - : Number(expiration); - - return this; -}; - -Transaction.prototype.password_fund = function (src, dst) { - this._secret = this._account_secret(src); - this.tx_json.TransactionType = 'PasswordFund'; - this.tx_json.Destination = UInt160.json_rewrite(dst); - - return this; -} - -Transaction.prototype.password_set = function (src, authorized_key, generator, public_key, signature) { - this._secret = this._account_secret(src); - this.tx_json.TransactionType = 'PasswordSet'; - this.tx_json.RegularKey = authorized_key; - this.tx_json.Generator = generator; - this.tx_json.PublicKey = public_key; - this.tx_json.Signature = signature; - - return this; -} - -// Construct a 'payment' transaction. -// -// When a transaction is submitted: -// - If the connection is reliable and the server is not merely forwarding and is not malicious, -// --> src : UInt160 or String -// --> dst : UInt160 or String -// --> deliver_amount : Amount or String. -// -// Options: -// .paths() -// .build_path() -// .destination_tag() -// .path_add() -// .secret() -// .send_max() -// .set_flags() -// .source_tag() -Transaction.prototype.payment = function (src, dst, deliver_amount) { - this._secret = this._account_secret(src); - this.tx_json.TransactionType = 'Payment'; - this.tx_json.Account = UInt160.json_rewrite(src); - this.tx_json.Amount = Amount.json_rewrite(deliver_amount); - this.tx_json.Destination = UInt160.json_rewrite(dst); - - return this; -} - -Transaction.prototype.ripple_line_set = function (src, limit, quality_in, quality_out) { - this._secret = this._account_secret(src); - this.tx_json.TransactionType = 'TrustSet'; - this.tx_json.Account = UInt160.json_rewrite(src); - - // Allow limit of 0 through. - if (undefined !== limit) - this.tx_json.LimitAmount = Amount.json_rewrite(limit); - - if (quality_in) - this.tx_json.QualityIn = quality_in; - - if (quality_out) - this.tx_json.QualityOut = quality_out; - - // XXX Throw an error if nothing is set. - - return this; -}; - -Transaction.prototype.wallet_add = function (src, amount, authorized_key, public_key, signature) { - this._secret = this._account_secret(src); - this.tx_json.TransactionType = 'WalletAdd'; - this.tx_json.Amount = Amount.json_rewrite(amount); - this.tx_json.RegularKey = authorized_key; - this.tx_json.PublicKey = public_key; - this.tx_json.Signature = signature; - - return this; -}; - -exports.Transaction = Transaction; - -// vim:sw=2:sts=2:ts=8:et diff --git a/src/js/uint.js b/src/js/uint.js deleted file mode 100644 index 457e3e9590..0000000000 --- a/src/js/uint.js +++ /dev/null @@ -1,227 +0,0 @@ - -var sjcl = require('../../build/sjcl'); -var utils = require('./utils'); -var config = require('./config'); -var jsbn = require('./jsbn'); - -var BigInteger = jsbn.BigInteger; -var nbi = jsbn.nbi; - -var Base = require('./base').Base; - -// -// Abstract UInt class -// -// Base class for UInt??? classes -// - -var UInt = function () { - // Internal form: NaN or BigInteger - this._value = NaN; -}; - -UInt.json_rewrite = function (j, opts) { - return this.from_json(j).to_json(opts); -}; - -// Return a new UInt from j. -UInt.from_generic = function (j) { - if (j instanceof this) { - return j.clone(); - } else { - return (new this()).parse_generic(j); - } -}; - -// Return a new UInt from j. -UInt.from_hex = function (j) { - if (j instanceof this) { - return j.clone(); - } else { - return (new this()).parse_hex(j); - } -}; - -// Return a new UInt from j. -UInt.from_json = function (j) { - if (j instanceof this) { - return j.clone(); - } else { - return (new this()).parse_json(j); - } -}; - -// Return a new UInt from j. -UInt.from_bits = function (j) { - if (j instanceof this) { - return j.clone(); - } else { - return (new this()).parse_bits(j); - } -}; - -// Return a new UInt from j. -UInt.from_bn = function (j) { - if (j instanceof this) { - return j.clone(); - } else { - return (new this()).parse_bn(j); - } -}; - -UInt.is_valid = function (j) { - return this.from_json(j).is_valid(); -}; - -UInt.prototype.clone = function () { - return this.copyTo(new this.constructor()); -}; - -// Returns copy. -UInt.prototype.copyTo = function (d) { - d._value = this._value; - - return d; -}; - -UInt.prototype.equals = function (d) { - return this._value instanceof BigInteger && d._value instanceof BigInteger && this._value.equals(d._value); -}; - -UInt.prototype.is_valid = function () { - return this._value instanceof BigInteger; -}; - -UInt.prototype.is_zero = function () { - return this._value.equals(BigInteger.ZERO); -}; - -// value = NaN on error. -UInt.prototype.parse_generic = function (j) { - // Canonicalize and validate - if (config.accounts && j in config.accounts) - j = config.accounts[j].account; - - switch (j) { - case undefined: - case "0": - case this.constructor.STR_ZERO: - case this.constructor.ACCOUNT_ZERO: - case this.constructor.HEX_ZERO: - this._value = nbi(); - break; - - case "1": - case this.constructor.STR_ONE: - case this.constructor.ACCOUNT_ONE: - case this.constructor.HEX_ONE: - this._value = new BigInteger([1]); - - break; - - default: - if ('string' !== typeof j) { - this._value = NaN; - } - else if (j[0] === "r") { - this._value = Base.decode_check(Base.VER_ACCOUNT_ID, j); - } - else if (this.constructor.width === j.length) { - this._value = new BigInteger(utils.stringToArray(j), 256); - } - else if ((this.constructor.width*2) === j.length) { - // XXX Check char set! - this._value = new BigInteger(j, 16); - } - else { - this._value = NaN; - } - } - - return this; -}; - -UInt.prototype.parse_hex = function (j) { - if ('string' === typeof j && - j.length === (this.constructor.width * 2)) { - this._value = new BigInteger(j, 16); - } else { - this._value = NaN; - } - - return this; -}; - -UInt.prototype.parse_bits = function (j) { - if (sjcl.bitArray.bitLength(j) !== this.constructor.width * 8) { - this._value = NaN; - } else { - var bytes = sjcl.codec.bytes.fromBits(j); - this._value = new BigInteger(bytes, 256); - } - - return this; -}; - -UInt.prototype.parse_json = UInt.prototype.parse_hex; - -UInt.prototype.parse_bn = function (j) { - if (j instanceof sjcl.bn && - j.bitLength() <= this.constructor.width * 8) { - var bytes = sjcl.codec.bytes.fromBits(j.toBits()); - this._value = new BigInteger(bytes, 256); - } else { - this._value = NaN; - } - - return this; -}; - -// Convert from internal form. -UInt.prototype.to_bytes = function () { - if (!(this._value instanceof BigInteger)) - return null; - - var bytes = this._value.toByteArray(); - bytes = bytes.map(function (b) { return (b+256) % 256; }); - var target = this.constructor.width; - - // XXX Make sure only trim off leading zeros. - bytes = bytes.slice(-target); - while (bytes.length < target) bytes.unshift(0); - - return bytes; -}; - -UInt.prototype.to_hex = function () { - if (!(this._value instanceof BigInteger)) - return null; - - var bytes = this.to_bytes(); - - return sjcl.codec.hex.fromBits(sjcl.codec.bytes.toBits(bytes)).toUpperCase(); -}; - -UInt.prototype.to_json = UInt.prototype.to_hex; - -UInt.prototype.to_bits = function () { - if (!(this._value instanceof BigInteger)) - return null; - - var bytes = this.to_bytes(); - - return sjcl.codec.bytes.toBits(bytes); -}; - -UInt.prototype.to_bn = function () { - if (!(this._value instanceof BigInteger)) - return null; - - var bits = this.to_bits(); - - return sjcl.bn.fromBits(bits); -}; - -exports.UInt = UInt; - -// vim:sw=2:sts=2:ts=8:et diff --git a/src/js/uint160.js b/src/js/uint160.js deleted file mode 100644 index 66c980ec0e..0000000000 --- a/src/js/uint160.js +++ /dev/null @@ -1,70 +0,0 @@ - -var sjcl = require('../../build/sjcl'); -var utils = require('./utils'); -var config = require('./config'); -var jsbn = require('./jsbn'); -var extend = require('extend'); - -var BigInteger = jsbn.BigInteger; -var nbi = jsbn.nbi; - -var UInt = require('./uint').UInt, - Base = require('./base').Base; - -// -// UInt160 support -// - -var UInt160 = extend(function () { - // Internal form: NaN or BigInteger - this._value = NaN; -}, UInt); - -UInt160.width = 20; -UInt160.prototype = extend({}, UInt.prototype); -UInt160.prototype.constructor = UInt160; - -var ACCOUNT_ZERO = UInt160.ACCOUNT_ZERO = "rrrrrrrrrrrrrrrrrrrrrhoLvTp"; -var ACCOUNT_ONE = UInt160.ACCOUNT_ONE = "rrrrrrrrrrrrrrrrrrrrBZbvji"; -var HEX_ZERO = UInt160.HEX_ZERO = "0000000000000000000000000000000000000000"; -var HEX_ONE = UInt160.HEX_ONE = "0000000000000000000000000000000000000001"; -var STR_ZERO = UInt160.STR_ZERO = utils.hexToString(HEX_ZERO); -var STR_ONE = UInt160.STR_ONE = utils.hexToString(HEX_ONE); - -// value = NaN on error. -UInt160.prototype.parse_json = function (j) { - // Canonicalize and validate - if (config.accounts && j in config.accounts) - j = config.accounts[j].account; - - if ('string' !== typeof j) { - this._value = NaN; - } - else if (j[0] === "r") { - this._value = Base.decode_check(Base.VER_ACCOUNT_ID, j); - } - else { - this._value = NaN; - } - - return this; -}; - -// XXX Json form should allow 0 and 1, C++ doesn't currently allow it. -UInt160.prototype.to_json = function (opts) { - opts = opts || {}; - - if (!(this._value instanceof BigInteger)) - return NaN; - - var output = Base.encode_check(Base.VER_ACCOUNT_ID, this.to_bytes()); - - if (opts.gateways && output in opts.gateways) - output = opts.gateways[output]; - - return output; -}; - -exports.UInt160 = UInt160; - -// vim:sw=2:sts=2:ts=8:et diff --git a/src/js/uint256.js b/src/js/uint256.js deleted file mode 100644 index 42b01504a4..0000000000 --- a/src/js/uint256.js +++ /dev/null @@ -1,34 +0,0 @@ - -var sjcl = require('../../build/sjcl'); -var utils = require('./utils'); -var config = require('./config'); -var jsbn = require('./jsbn'); -var extend = require('extend'); - -var BigInteger = jsbn.BigInteger; -var nbi = jsbn.nbi; - -var UInt = require('./uint').UInt, - Base = require('./base').Base; - -// -// UInt256 support -// - -var UInt256 = extend(function () { - // Internal form: NaN or BigInteger - this._value = NaN; -}, UInt); - -UInt256.width = 32; -UInt256.prototype = extend({}, UInt.prototype); -UInt256.prototype.constructor = UInt256; - -var HEX_ZERO = UInt256.HEX_ZERO = "00000000000000000000000000000000" + - "00000000000000000000000000000000"; -var HEX_ONE = UInt256.HEX_ONE = "00000000000000000000000000000000" + - "00000000000000000000000000000001"; -var STR_ZERO = UInt256.STR_ZERO = utils.hexToString(HEX_ZERO); -var STR_ONE = UInt256.STR_ONE = utils.hexToString(HEX_ONE); - -exports.UInt256 = UInt256; diff --git a/src/js/utils.js b/src/js/utils.js deleted file mode 100644 index eafa8bea78..0000000000 --- a/src/js/utils.js +++ /dev/null @@ -1,136 +0,0 @@ -Function.prototype.method = function(name,func) { - this.prototype[name] = func; - - return this; -}; - -var filterErr = function(code, done) { - return function(e) { - done(e.code !== code ? e : undefined); - }; -}; - -var throwErr = function(done) { - return function(e) { - if (e) - throw e; - - done(); - }; -}; - -var trace = function(comment, func) { - return function() { - console.log("%s: %s", trace, arguments.toString); - func(arguments); - }; -}; - -var arraySet = function (count, value) { - var i, a = new Array(count); - - for (i = 0; i < count; i++) { - a[i] = value; - } - - return a; -}; - -var hexToString = function (h) { - var a = []; - var i = 0; - - if (h.length % 2) { - a.push(String.fromCharCode(parseInt(h.substring(0, 1), 16))); - i = 1; - } - - for (; i != h.length; i += 2) { - a.push(String.fromCharCode(parseInt(h.substring(i, i+2), 16))); - } - - return a.join(""); -}; - -var stringToHex = function (s) { - return Array.prototype.map.call(s, function (c) { - var b = c.charCodeAt(0); - - return b < 16 ? "0" + b.toString(16) : b.toString(16); - }).join(""); -}; - -var stringToArray = function (s) { - var a = new Array(s.length); - var i; - - for (i = 0; i != a.length; i += 1) - a[i] = s.charCodeAt(i); - - return a; -}; - -var hexToArray = function (h) { - return stringToArray(hexToString(h)); -} - -var chunkString = function (str, n, leftAlign) { - var ret = []; - var i=0, len=str.length; - if (leftAlign) { - i = str.length % n; - if (i) ret.push(str.slice(0, i)); - } - for(; i < len; i += n) { - ret.push(str.slice(i, n+i)); - } - return ret; -}; - -var logObject = function (msg, obj) { - console.log(msg, JSON.stringify(obj, undefined, 2)); -}; - -var assert = function (assertion, msg) { - if (!assertion) { - throw new Error("Assertion failed" + (msg ? ": "+msg : ".")); - } -}; - -/** - * Return unique values in array. - */ -var arrayUnique = function (arr) { - var u = {}, a = []; - for (var i = 0, l = arr.length; i < l; ++i){ - if (u.hasOwnProperty(arr[i])) { - continue; - } - a.push(arr[i]); - u[arr[i]] = 1; - } - return a; -}; - -/** - * Convert a ripple epoch to a JavaScript timestamp. - * - * JavaScript timestamps are unix epoch in milliseconds. - */ -var toTimestamp = function (rpepoch) { - return (rpepoch + 0x386D4380) * 1000; -}; - -exports.trace = trace; -exports.arraySet = arraySet; -exports.hexToString = hexToString; -exports.hexToArray = hexToArray; -exports.stringToArray = stringToArray; -exports.stringToHex = stringToHex; -exports.chunkString = chunkString; -exports.logObject = logObject; -exports.assert = assert; -exports.arrayUnique = arrayUnique; -exports.toTimestamp = toTimestamp; - -// vim:sw=2:sts=2:ts=8:et diff --git a/src/js/utils.web.js b/src/js/utils.web.js deleted file mode 100644 index b3a49e5025..0000000000 --- a/src/js/utils.web.js +++ /dev/null @@ -1,11 +0,0 @@ -var exports = module.exports = require('./utils.js'); - -// We override this function for browsers, because they print objects nicer -// natively than JSON.stringify can. -exports.logObject = function (msg, obj) { - if (/MSIE/.test(navigator.userAgent)) { - console.log(msg, JSON.stringify(obj)); - } else { - console.log(msg, "", obj); - } -}; diff --git a/test/account_tx-test.js b/test/account_tx-test.js index 7ab54ef76a..6c7a8babec 100644 --- a/test/account_tx-test.js +++ b/test/account_tx-test.js @@ -1,14 +1,14 @@ var async = require("async"); var buster = require("buster"); -var Amount = require("../src/js/amount").Amount; -var Remote = require("../src/js/remote").Remote; -var Transaction = require("../src/js/transaction").Transaction; +var Amount = require("ripple-lib").Amount; +var Remote = require("ripple-lib").Remote; +var Transaction = require("ripple-lib").Transaction; var Server = require("./server").Server; var testutils = require("./testutils"); -require('../src/js/config').load(require('./config')); +require('ripple-lib').config.load(require('./config')); buster.testRunner.timeout = 350000; //This is a very long test! diff --git a/test/amount-test.js b/test/amount-test.js deleted file mode 100644 index fac357ad26..0000000000 --- a/test/amount-test.js +++ /dev/null @@ -1,355 +0,0 @@ -var buster = require("buster"); - -var jsbn = require('../src/js/jsbn'); -var BigInteger = jsbn.BigInteger; -var nbi = jsbn.nbi; - -var Amount = require("../src/js/amount").Amount; -var UInt160 = require("../src/js/uint160").UInt160; - -var config = require('../src/js/config').load(require('./config')); - -// XXX Add test cases that push XRP vs non-XRP behavior. - -buster.testCase("Amount", { - "UInt160" : { - "Parse 0" : function () { - buster.assert.equals(nbi(), UInt160.from_generic("0")._value); - }, - "Parse 0 export" : function () { - buster.assert.equals(UInt160.ACCOUNT_ZERO, UInt160.from_generic("0").to_json()); - }, - "Parse 1" : function () { - buster.assert.equals(new BigInteger([1]), UInt160.from_generic("1")._value); - }, - "Parse rrrrrrrrrrrrrrrrrrrrrhoLvTp export" : function () { - buster.assert.equals(UInt160.ACCOUNT_ZERO, UInt160.from_json("rrrrrrrrrrrrrrrrrrrrrhoLvTp").to_json()); - }, - "Parse rrrrrrrrrrrrrrrrrrrrBZbvji export" : function () { - buster.assert.equals(UInt160.ACCOUNT_ONE, UInt160.from_json("rrrrrrrrrrrrrrrrrrrrBZbvji").to_json()); - }, - "Parse mtgox export" : function () { - buster.assert.equals(config.accounts["mtgox"].account, UInt160.from_json("mtgox").to_json()); - }, - - "is_valid('rrrrrrrrrrrrrrrrrrrrrhoLvTp')" : function () { - buster.assert(UInt160.is_valid("rrrrrrrrrrrrrrrrrrrrrhoLvTp")); - }, - - "!is_valid('rrrrrrrrrrrrrrrrrrrrrhoLvT')" : function () { - buster.refute(UInt160.is_valid("rrrrrrrrrrrrrrrrrrrrrhoLvT")); - }, - }, - - "Amount parsing" : { - "Parse 800/USD/mtgox" : function () { - buster.assert.equals("800/USD/"+config.accounts["mtgox"].account, Amount.from_json("800/USD/mtgox").to_text_full()); - }, - "Parse native 0" : function () { - buster.assert.equals("0/XRP", Amount.from_json("0").to_text_full()); - }, - "Parse native 0.0" : function () { - buster.assert.equals("0/XRP", Amount.from_json("0.0").to_text_full()); - }, - "Parse native -0" : function () { - buster.assert.equals("0/XRP", Amount.from_json("-0").to_text_full()); - }, - "Parse native -0.0" : function () { - buster.assert.equals("0/XRP", Amount.from_json("-0.0").to_text_full()); - }, - "Parse native 1000" : function () { - buster.assert.equals("1000/XRP", Amount.from_json("1000").to_text_full()); - }, - "Parse native 12.3" : function () { - buster.assert.equals("12300000/XRP", Amount.from_json("12.3").to_text_full()); - }, - "Parse native -12.3" : function () { - buster.assert.equals("-12300000/XRP", Amount.from_json("-12.3").to_text_full()); - }, - "Parse 123./USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh" : function () { - buster.assert.equals("123/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", Amount.from_json("123./USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh").to_text_full()); - }, - "Parse 12300/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh" : function () { - buster.assert.equals("12300/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", Amount.from_json("12300/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh").to_text_full()); - }, - "Parse 12.3/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh" : function () { - buster.assert.equals("12.3/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", Amount.from_json("12.3/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh").to_text_full()); - }, - "Parse 1.2300/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh" : function () { - buster.assert.equals("1.23/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", Amount.from_json("1.2300/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh").to_text_full()); - }, - "Parse -0/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh" : function () { - buster.assert.equals("0/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", Amount.from_json("-0/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh").to_text_full()); - }, - "Parse -0.0/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh" : function () { - buster.assert.equals("0/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", Amount.from_json("-0.0/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh").to_text_full()); - }, - }, - "Amount operations" : { - "Negate native 123" : function () { - buster.assert.equals("-123/XRP", Amount.from_json("123").negate().to_text_full()); - }, - "Negate native -123" : function () { - buster.assert.equals("123/XRP", Amount.from_json("-123").negate().to_text_full()); - }, - "Negate non-native 123" : function () { - buster.assert.equals("-123/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", Amount.from_json("123/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh").negate().to_text_full()); - }, - "Negate non-native -123" : function () { - buster.assert.equals("123/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", Amount.from_json("-123/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh").negate().to_text_full()); - }, - "Clone non-native -123" : function () { - buster.assert.equals("-123/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", Amount.from_json("-123/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh").clone().to_text_full()); - }, - "Add XRP to XRP" : function () { - buster.assert.equals("200/XRP", Amount.from_json("150").add(Amount.from_json("50")).to_text_full()); - }, - "Add USD to USD" : function () { - buster.assert.equals("200.52/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", Amount.from_json("150.02/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh").add(Amount.from_json("50.5/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh")).to_text_full()); - }, - "Multiply 0 XRP with 0 XRP" : function () { - buster.assert.equals("0/XRP", Amount.from_json("0").multiply(Amount.from_json("0")).to_text_full()); - }, - "Multiply 0 USD with 0 XRP" : function () { - buster.assert.equals("0/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", Amount.from_json("0/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh").multiply(Amount.from_json("0")).to_text_full()); - }, - "Multiply 0 XRP with 0 USD" : function () { - buster.assert.equals("0/XRP", Amount.from_json("0").multiply(Amount.from_json("0/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh")).to_text_full()); - }, - "Multiply 1 XRP with 0 XRP" : function () { - buster.assert.equals("0/XRP", Amount.from_json("1").multiply(Amount.from_json("0")).to_text_full()); - }, - "Multiply 1 USD with 0 XRP" : function () { - buster.assert.equals("0/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", Amount.from_json("1/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh").multiply(Amount.from_json("0")).to_text_full()); - }, - "Multiply 1 XRP with 0 USD" : function () { - buster.assert.equals("0/XRP", Amount.from_json("1").multiply(Amount.from_json("0/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh")).to_text_full()); - }, - "Multiply 0 XRP with 1 XRP" : function () { - buster.assert.equals("0/XRP", Amount.from_json("0").multiply(Amount.from_json("1")).to_text_full()); - }, - "Multiply 0 USD with 1 XRP" : function () { - buster.assert.equals("0/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", Amount.from_json("0/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh").multiply(Amount.from_json("1")).to_text_full()); - }, - "Multiply 0 XRP with 1 USD" : function () { - buster.assert.equals("0/XRP", Amount.from_json("0").multiply(Amount.from_json("1/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh")).to_text_full()); - }, - "Multiply XRP with USD" : function () { - buster.assert.equals("2000/XRP", Amount.from_json("200").multiply(Amount.from_json("10/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh")).to_text_full()); - }, - "Multiply XRP with USD" : function () { - buster.assert.equals("200000/XRP", Amount.from_json("20000").multiply(Amount.from_json("10/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh")).to_text_full()); - }, - "Multiply XRP with USD" : function () { - buster.assert.equals("20000000/XRP", Amount.from_json("2000000").multiply(Amount.from_json("10/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh")).to_text_full()); - }, - "Multiply XRP with USD, neg" : function () { - buster.assert.equals("-2000/XRP", Amount.from_json("200").multiply(Amount.from_json("-10/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh")).to_text_full()); - }, - "Multiply XRP with USD, neg, frac" : function () { - buster.assert.equals("-222000/XRP", Amount.from_json("-6000").multiply(Amount.from_json("37/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh")).to_text_full()); - }, - "Multiply USD with USD" : function () { - buster.assert.equals("20000/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", Amount.from_json("2000/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh").multiply(Amount.from_json("10/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh")).to_text_full()); - }, - "Multiply USD with USD" : function () { - buster.assert.equals("200000000000/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", Amount.from_json("2000000/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh").multiply(Amount.from_json("100000/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh")).to_text_full()); - }, - "Multiply EUR with USD, result < 1" : function () { - buster.assert.equals("100000/EUR/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", Amount.from_json("100/EUR/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh").multiply(Amount.from_json("1000/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh")).to_text_full()); - }, - "Multiply EUR with USD, neg" : function () { - buster.assert.equals("-48000000/EUR/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", Amount.from_json("-24000/EUR/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh").multiply(Amount.from_json("2000/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh")).to_text_full()); - }, - "Multiply EUR with USD, neg, <1" : function () { - buster.assert.equals("-100/EUR/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", Amount.from_json("0.1/EUR/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh").multiply(Amount.from_json("-1000/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh")).to_text_full()); - }, - "Multiply EUR with XRP, factor < 1" : function () { - buster.assert.equals("100/EUR/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", Amount.from_json("0.05/EUR/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh").multiply(Amount.from_json("2000")).to_text_full()); - }, - "Multiply EUR with XRP, neg" : function () { - buster.assert.equals("-500/EUR/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", Amount.from_json("-100/EUR/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh").multiply(Amount.from_json("5")).to_text_full()); - }, - "Multiply EUR with XRP, neg, <1" : function () { - buster.assert.equals("-100/EUR/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", Amount.from_json("-0.05/EUR/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh").multiply(Amount.from_json("2000")).to_text_full()); - }, - "Multiply XRP with XRP" : function () { - buster.assert.equals("100/XRP", Amount.from_json("10").multiply(Amount.from_json("10")).to_text_full()); - }, - "Divide XRP by USD" : function () { - buster.assert.equals("20/XRP", Amount.from_json("200").divide(Amount.from_json("10/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh")).to_text_full()); - }, - "Divide XRP by USD" : function () { - buster.assert.equals("2000/XRP", Amount.from_json("20000").divide(Amount.from_json("10/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh")).to_text_full()); - }, - "Divide XRP by USD" : function () { - buster.assert.equals("200000/XRP", Amount.from_json("2000000").divide(Amount.from_json("10/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh")).to_text_full()); - }, - "Divide XRP by USD, neg" : function () { - buster.assert.equals("-20/XRP", Amount.from_json("200").divide(Amount.from_json("-10/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh")).to_text_full()); - }, - "Divide XRP by USD, neg, frac" : function () { - buster.assert.equals("-162/XRP", Amount.from_json("-6000").divide(Amount.from_json("37/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh")).to_text_full()); - }, - "Divide USD by USD" : function () { - buster.assert.equals("200/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", Amount.from_json("2000/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh").divide(Amount.from_json("10/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh")).to_text_full()); - }, - "Divide USD by USD, fractional" : function () { - buster.assert.equals("57142.85714285714/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", Amount.from_json("2000000/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh").divide(Amount.from_json("35/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh")).to_text_full()); - }, - "Divide USD by USD" : function () { - buster.assert.equals("20/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", Amount.from_json("2000000/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh").divide(Amount.from_json("100000/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh")).to_text_full()); - }, - "Divide EUR by USD, factor < 1" : function () { - buster.assert.equals("0.1/EUR/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", Amount.from_json("100/EUR/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh").divide(Amount.from_json("1000/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh")).to_text_full()); - }, - "Divide EUR by USD, neg" : function () { - buster.assert.equals("-12/EUR/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", Amount.from_json("-24000/EUR/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh").divide(Amount.from_json("2000/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh")).to_text_full()); - }, - "Divide EUR by USD, neg, <1" : function () { - buster.assert.equals("-0.1/EUR/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", Amount.from_json("100/EUR/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh").divide(Amount.from_json("-1000/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh")).to_text_full()); - }, - "Divide EUR by XRP, result < 1" : function () { - buster.assert.equals("0.05/EUR/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", Amount.from_json("100/EUR/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh").divide(Amount.from_json("2000")).to_text_full()); - }, - "Divide EUR by XRP, neg" : function () { - buster.assert.equals("-20/EUR/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", Amount.from_json("-100/EUR/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh").divide(Amount.from_json("5")).to_text_full()); - }, - "Divide EUR by XRP, neg, <1" : function () { - buster.assert.equals("-0.05/EUR/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", Amount.from_json("-100/EUR/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh").divide(Amount.from_json("2000")).to_text_full()); - } - }, - "Amount comparisons" : { - "0 USD == 0 USD" : function () { - var a = Amount.from_json("0/USD/rNDKeo9RrCiRdfsMG8AdoZvNZxHASGzbZL"); - var b = Amount.from_json("0/USD/rNDKeo9RrCiRdfsMG8AdoZvNZxHASGzbZL"); - buster.assert(a.equals(b)); - buster.refute(a.not_equals_why(b)); - }, - "0 USD == -0 USD" : function () { - var a = Amount.from_json("0/USD/rNDKeo9RrCiRdfsMG8AdoZvNZxHASGzbZL"); - var b = Amount.from_json("-0/USD/rNDKeo9RrCiRdfsMG8AdoZvNZxHASGzbZL"); - buster.assert(a.equals(b)); - buster.refute(a.not_equals_why(b)); - }, - "0 XRP == 0 XRP" : function () { - var a = Amount.from_json("0"); - var b = Amount.from_json("0.0"); - buster.assert(a.equals(b)); - buster.refute(a.not_equals_why(b)); - }, - "0 XRP == -0 XRP" : function () { - var a = Amount.from_json("0"); - var b = Amount.from_json("-0"); - buster.assert(a.equals(b)); - buster.refute(a.not_equals_why(b)); - }, - "10 USD == 10 USD" : function () { - var a = Amount.from_json("10/USD/rNDKeo9RrCiRdfsMG8AdoZvNZxHASGzbZL"); - var b = Amount.from_json("10/USD/rNDKeo9RrCiRdfsMG8AdoZvNZxHASGzbZL"); - buster.assert(a.equals(b)); - buster.refute(a.not_equals_why(b)); - }, - "123.4567 USD == 123.4567 USD" : function () { - var a = Amount.from_json("123.4567/USD/rNDKeo9RrCiRdfsMG8AdoZvNZxHASGzbZL"); - var b = Amount.from_json("123.4567/USD/rNDKeo9RrCiRdfsMG8AdoZvNZxHASGzbZL"); - buster.assert(a.equals(b)); - buster.refute(a.not_equals_why(b)); - }, - "10 XRP == 10 XRP" : function () { - var a = Amount.from_json("10"); - var b = Amount.from_json("10"); - buster.assert(a.equals(b)); - buster.refute(a.not_equals_why(b)); - }, - "1.1 XRP == 1.1 XRP" : function () { - var a = Amount.from_json("1.1"); - var b = Amount.from_json("11.0").ratio_human(10); - buster.assert(a.equals(b)); - buster.refute(a.not_equals_why(b)); - }, - "0 USD == 0 USD (ignore issuer)" : function () { - var a = Amount.from_json("0/USD/rNDKeo9RrCiRdfsMG8AdoZvNZxHASGzbZL"); - var b = Amount.from_json("0/USD/rH5aWQJ4R7v4Mpyf4kDBUvDFT5cbpFq3XP"); - buster.assert(a.equals(b, true)); - buster.refute(a.not_equals_why(b, true)); - }, - "1.1 USD == 1.10 USD (ignore issuer)" : function () { - var a = Amount.from_json("1.1/USD/rNDKeo9RrCiRdfsMG8AdoZvNZxHASGzbZL"); - var b = Amount.from_json("1.10/USD/rH5aWQJ4R7v4Mpyf4kDBUvDFT5cbpFq3XP"); - buster.assert(a.equals(b, true)); - buster.refute(a.not_equals_why(b, true)); - }, - // Exponent mismatch - "10 USD != 100 USD" : function () { - var a = Amount.from_json("10/USD/rNDKeo9RrCiRdfsMG8AdoZvNZxHASGzbZL"); - var b = Amount.from_json("100/USD/rNDKeo9RrCiRdfsMG8AdoZvNZxHASGzbZL"); - buster.refute(a.equals(b)); - buster.assert.equals(a.not_equals_why(b), "Non-XRP value differs."); - }, - "10 XRP != 100 XRP" : function () { - var a = Amount.from_json("10"); - var b = Amount.from_json("100"); - buster.refute(a.equals(b)); - buster.assert.equals(a.not_equals_why(b), "XRP value differs."); - }, - // Mantissa mismatch - "1 USD != 2 USD" : function () { - var a = Amount.from_json("1/USD/rNDKeo9RrCiRdfsMG8AdoZvNZxHASGzbZL"); - var b = Amount.from_json("2/USD/rNDKeo9RrCiRdfsMG8AdoZvNZxHASGzbZL"); - buster.refute(a.equals(b)); - buster.assert.equals(a.not_equals_why(b), "Non-XRP value differs."); - }, - "1 XRP != 2 XRP" : function () { - var a = Amount.from_json("1"); - var b = Amount.from_json("2"); - buster.refute(a.equals(b)); - buster.assert.equals(a.not_equals_why(b), "XRP value differs."); - }, - "0.1 USD != 0.2 USD" : function () { - var a = Amount.from_json("0.1/USD/rNDKeo9RrCiRdfsMG8AdoZvNZxHASGzbZL"); - var b = Amount.from_json("0.2/USD/rNDKeo9RrCiRdfsMG8AdoZvNZxHASGzbZL"); - buster.refute(a.equals(b)); - buster.assert.equals(a.not_equals_why(b), "Non-XRP value differs."); - }, - // Sign mismatch - "1 USD != -1 USD" : function () { - var a = Amount.from_json("1/USD/rNDKeo9RrCiRdfsMG8AdoZvNZxHASGzbZL"); - var b = Amount.from_json("-1/USD/rNDKeo9RrCiRdfsMG8AdoZvNZxHASGzbZL"); - buster.refute(a.equals(b)); - buster.assert.equals(a.not_equals_why(b), "Non-XRP sign differs."); - }, - "1 XRP != -1 XRP" : function () { - var a = Amount.from_json("1"); - var b = Amount.from_json("-1"); - buster.refute(a.equals(b)); - buster.assert.equals(a.not_equals_why(b), "XRP sign differs."); - }, - "1 USD != 1 USD (issuer mismatch)" : function () { - var a = Amount.from_json("1/USD/rNDKeo9RrCiRdfsMG8AdoZvNZxHASGzbZL"); - var b = Amount.from_json("1/USD/rH5aWQJ4R7v4Mpyf4kDBUvDFT5cbpFq3XP"); - buster.refute(a.equals(b)); - buster.assert.equals(a.not_equals_why(b), "Non-XRP issuer differs: rH5aWQJ4R7v4Mpyf4kDBUvDFT5cbpFq3XP/rNDKeo9RrCiRdfsMG8AdoZvNZxHASGzbZL"); - }, - "1 USD != 1 EUR" : function () { - var a = Amount.from_json("1/USD/rNDKeo9RrCiRdfsMG8AdoZvNZxHASGzbZL"); - var b = Amount.from_json("1/EUR/rNDKeo9RrCiRdfsMG8AdoZvNZxHASGzbZL"); - buster.refute(a.equals(b)); - buster.assert.equals(a.not_equals_why(b), "Non-XRP currency differs."); - }, - "1 USD != 1 XRP" : function () { - var a = Amount.from_json("1/USD/rNDKeo9RrCiRdfsMG8AdoZvNZxHASGzbZL"); - var b = Amount.from_json("1"); - buster.refute(a.equals(b)); - buster.assert.equals(a.not_equals_why(b), "Native mismatch."); - }, - "1 XRP != 1 USD" : function () { - var a = Amount.from_json("1"); - var b = Amount.from_json("1/USD/rNDKeo9RrCiRdfsMG8AdoZvNZxHASGzbZL"); - buster.refute(a.equals(b)); - buster.assert.equals(a.not_equals_why(b), "Native mismatch."); - } - } -}); - -// vim:sw=2:sts=2:ts=8:et diff --git a/test/base58-test.js b/test/base58-test.js deleted file mode 100644 index c143de7b84..0000000000 --- a/test/base58-test.js +++ /dev/null @@ -1,20 +0,0 @@ -var buster = require("buster"); - -var Seed = require("../src/js/seed").Seed; - -var config = require('../src/js/config').load(require('./config')); - -buster.testCase("Base58", { - "Seed" : { - "saESc82Vun7Ta5EJRzGJbrXb5HNYk" : function () { - var seed = Seed.from_json("saESc82Vun7Ta5EJRzGJbrXb5HNYk"); - buster.assert.equals(seed.to_hex(), "FF1CF838D02B2CF7B45BAC27F5F24F4F"); - }, - "sp6iDHnmiPN7tQFHm5sCW59ax3hfE" : function () { - var seed = Seed.from_json("sp6iDHnmiPN7tQFHm5sCW59ax3hfE"); - buster.assert.equals(seed.to_hex(), "00AD8DA764C3C8AF5F9B8D51C94B9E49"); - } - } -}); - -// vim:sw=2:sts=2:ts=8:et diff --git a/test/jsonrpc-test.js b/test/jsonrpc-test.js index 5140bdb2ea..c19c2636e1 100644 --- a/test/jsonrpc-test.js +++ b/test/jsonrpc-test.js @@ -4,13 +4,13 @@ var http = require("http"); var jsonrpc = require("simple-jsonrpc"); var EventEmitter = require('events').EventEmitter; -var Amount = require("../src/js/amount").Amount; -var Remote = require("../src/js/remote").Remote; +var Amount = require("ripple-lib").Amount; +var Remote = require("ripple-lib").Remote; var Server = require("./server").Server; var testutils = require("./testutils"); -var config = require('../src/js/config').load(require('./config')); +var config = require('ripple-lib').config.load(require('./config')); // How long to wait for server to start. var serverDelay = 1500; diff --git a/test/monitor-test.js b/test/monitor-test.js index ecb3e5bac2..342dd7e4fb 100644 --- a/test/monitor-test.js +++ b/test/monitor-test.js @@ -1,13 +1,13 @@ var async = require("async"); var buster = require("buster"); -var Amount = require("../src/js/amount").Amount; -var Remote = require("../src/js/remote").Remote; +var Amount = require("ripple-lib").Amount; +var Remote = require("ripple-lib").Remote; var Server = require("./server").Server; var testutils = require("./testutils"); -require('../src/js/config').load(require('./config')); +require('ripple-lib').config.load(require('./config')); buster.testRunner.timeout = 5000; diff --git a/src/js/nodeutils.js b/test/nodeutils.js similarity index 97% rename from src/js/nodeutils.js rename to test/nodeutils.js index f57334699c..53859f7019 100644 --- a/src/js/nodeutils.js +++ b/test/nodeutils.js @@ -2,7 +2,7 @@ var async = require("async"); var fs = require("fs"); var path = require("path"); -var utils = require("./utils.js"); +var utils = require("ripple-lib").utils; // Empty a directory. // done(err) : err = true if an error occured. diff --git a/test/offer-test.js b/test/offer-test.js index 113d6b0000..c747c6d4ca 100644 --- a/test/offer-test.js +++ b/test/offer-test.js @@ -2,14 +2,14 @@ var async = require("async"); var buster = require("buster"); -var Amount = require("../src/js/amount").Amount; -var Remote = require("../src/js/remote").Remote; -var Transaction = require("../src/js/transaction").Transaction; +var Amount = require("ripple-lib").Amount; +var Remote = require("ripple-lib").Remote; +var Transaction = require("ripple-lib").Transaction; var Server = require("./server").Server; var testutils = require("./testutils"); -require('../src/js/config').load(require('./config')); +require('ripple-lib').config.load(require('./config')); buster.testRunner.timeout = 5000; diff --git a/test/path-test.js b/test/path-test.js index 00587a2c1f..31aea5f4a6 100644 --- a/test/path-test.js +++ b/test/path-test.js @@ -1,14 +1,14 @@ var async = require("async"); var buster = require("buster"); -var Amount = require("../src/js/amount.js").Amount; -var Remote = require("../src/js/remote.js").Remote; -var Transaction = require("../src/js/transaction.js").Transaction; -var Server = require("./server.js").Server; +var Amount = require("ripple-lib").Amount; +var Remote = require("ripple-lib").Remote; +var Transaction = require("ripple-lib").Transaction; +var Server = require("./server").Server; -var testutils = require("./testutils.js"); +var testutils = require("./testutils"); -require('../src/js/config').load(require('./config')); +require('ripple-lib').config.load(require('./config')); buster.testRunner.timeout = 5000; diff --git a/test/remote-test.js b/test/remote-test.js index b3fe6d97b7..841f3df0d0 100644 --- a/test/remote-test.js +++ b/test/remote-test.js @@ -1,12 +1,12 @@ var buster = require("buster"); -var Amount = require("../src/js/amount.js").Amount; -var Remote = require("../src/js/remote.js").Remote; +var Amount = require("ripple-lib").Amount; +var Remote = require("ripple-lib").Remote; var Server = require("./server.js").Server; var testutils = require("./testutils.js"); -var config = require('../src/js/config').load(require('./config')); +var config = require('ripple-lib').config.load(require('./config')); // How long to wait for server to start. var serverDelay = 1500; // XXX Not implemented. diff --git a/test/send-test.js b/test/send-test.js index 7e2c251d69..1253ce2178 100644 --- a/test/send-test.js +++ b/test/send-test.js @@ -1,13 +1,13 @@ var async = require("async"); var buster = require("buster"); -var Amount = require("../src/js/amount.js").Amount; -var Remote = require("../src/js/remote.js").Remote; -var Server = require("./server.js").Server; +var Amount = require("ripple-lib").Amount; +var Remote = require("ripple-lib").Remote; +var Server = require("./server").Server; -var testutils = require("./testutils.js"); +var testutils = require("./testutils"); -var config = require('../src/js/config').load(require('./config')); +var config = require('ripple-lib').config.load(require('./config')); // How long to wait for server to start. var serverDelay = 1500; diff --git a/test/server.js b/test/server.js index bb0936ca3a..80853fd1d7 100644 --- a/test/server.js +++ b/test/server.js @@ -22,8 +22,8 @@ var path = require("path"); var util = require("util"); var EventEmitter = require('events').EventEmitter; -var config = require("./config.js"); -var nodeutils = require("../src/js/nodeutils.js"); +var config = require("./config"); +var nodeutils = require("./nodeutils"); // Create a server object var Server = function (name, config, verbose) { diff --git a/test/sign-test.js b/test/sign-test.js deleted file mode 100644 index 405c8ba531..0000000000 --- a/test/sign-test.js +++ /dev/null @@ -1,24 +0,0 @@ -var buster = require("buster"); - -var Seed = require("../src/js/seed").Seed; - -var config = require('../src/js/config').load(require('./config')); - -buster.testCase("Signing", { - "Keys" : { - "SigningPubKey 1 (ripple-client issue #245)" : function () { - var seed = Seed.from_json("saESc82Vun7Ta5EJRzGJbrXb5HNYk"); - var key = seed.get_key("rBZ4j6MsoctipM6GEyHSjQKzXG3yambDnZ"); - var pub = key.to_hex_pub(); - buster.assert.equals(pub, "0396941B22791A448E5877A44CE98434DB217D6FB97D63F0DAD23BE49ED45173C9"); - }, - "SigningPubKey 2 (master seed)" : function () { - var seed = Seed.from_json("snoPBrXtMeMyMHUVTgbuqAfg1SUTb"); - var key = seed.get_key("rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh"); - var pub = key.to_hex_pub(); - buster.assert.equals(pub, "0330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD020"); - } - } -}); - -// vim:sw=2:sts=2:ts=8:et diff --git a/test/testutils.js b/test/testutils.js index 0799ee97bc..54092a19fa 100644 --- a/test/testutils.js +++ b/test/testutils.js @@ -1,10 +1,10 @@ var async = require("async"); -var Amount = require("../src/js/amount").Amount; -var Remote = require("../src/js/remote").Remote; +var Amount = require("ripple-lib").Amount; +var Remote = require("ripple-lib").Remote; var Server = require("./server").Server; -var config = require('../src/js/config').load(require('./config')); +var config = require('ripple-lib').config.load(require('./config')); var account_dump = function (remote, account, callback) { var self = this; diff --git a/test/utils-test.js b/test/utils-test.js deleted file mode 100644 index c1f8f8f967..0000000000 --- a/test/utils-test.js +++ /dev/null @@ -1,26 +0,0 @@ -var fs = require("fs"); -var buster = require("buster"); - -var utils = require("../src/js/utils.js"); - -buster.testCase("Utils", { - "hexToString and stringToHex" : { - "Even: 123456" : function () { - buster.assert.equals("123456", utils.stringToHex(utils.hexToString("123456"))); - }, - "Odd: 12345" : function () { - buster.assert.equals("012345", utils.stringToHex(utils.hexToString("12345"))); - }, - "Under 10: 0" : function () { - buster.assert.equals("00", utils.stringToHex(utils.hexToString("0"))); - }, - "Under 10: 1" : function () { - buster.assert.equals("01", utils.stringToHex(utils.hexToString("1"))); - }, - "Empty" : function () { - buster.assert.equals("", utils.stringToHex(utils.hexToString(""))); - } - } -}); - -// vim:sw=2:sts=2:ts=8:et diff --git a/test/websocket-test.js b/test/websocket-test.js index b16493b633..e0a9704984 100644 --- a/test/websocket-test.js +++ b/test/websocket-test.js @@ -1,9 +1,9 @@ var buster = require("buster"); var Server = require("./server").Server; -var Remote = require("../src/js/remote").Remote; +var Remote = require("ripple-lib").Remote; -var config = require('../src/js/config').load(require('./config')); +var config = require('ripple-lib').config.load(require('./config')); buster.testRunner.timeout = 5000;