From b3d87e99d1a547fb44873519f8e6cd86927696b0 Mon Sep 17 00:00:00 2001 From: Stefan Thomas Date: Wed, 7 Nov 2012 13:25:17 -0800 Subject: [PATCH 1/6] Fix path to rippled in test config. --- test/config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/config.js b/test/config.js index d9e6eb5846..42ce8bea47 100644 --- a/test/config.js +++ b/test/config.js @@ -5,7 +5,7 @@ var path = require("path"); // Where to find the binary. -exports.rippled = path.join(process.cwd(), "rippled"); +exports.rippled = path.join(process.cwd(), "build/rippled"); exports.server_default = "alpha"; From da42c64de7e154d0030794b7e9456b33fe17508c Mon Sep 17 00:00:00 2001 From: Stefan Thomas Date: Wed, 7 Nov 2012 13:28:03 -0800 Subject: [PATCH 2/6] Ignore dirty SJCL working directory. --- .gitmodules | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitmodules b/.gitmodules index 79ccb098e0..a88cf8bc62 100644 --- a/.gitmodules +++ b/.gitmodules @@ -7,3 +7,4 @@ [submodule "src/js/sjcl"] path = src/js/sjcl url = git://github.com/bitwiseshiftleft/sjcl.git + ignore = dirty From c04b94f7813499175e60ca08afaad7877076f285 Mon Sep 17 00:00:00 2001 From: Stefan Thomas Date: Wed, 7 Nov 2012 14:01:43 -0800 Subject: [PATCH 3/6] Custom events.js not actually needed anymore. --- src/js/events.js | 291 ----------------------------------------------- src/js/remote.js | 2 +- 2 files changed, 1 insertion(+), 292 deletions(-) delete mode 100644 src/js/events.js diff --git a/src/js/events.js b/src/js/events.js deleted file mode 100644 index 6caac53aef..0000000000 --- a/src/js/events.js +++ /dev/null @@ -1,291 +0,0 @@ -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - -var isArray = Array.isArray; -var domain; - -function EventEmitter() { - if (exports.usingDomains) { - // if there is an active domain, then attach to it. - domain = domain || require('domain'); - if (domain.active && !(this instanceof domain.Domain)) { - this.domain = domain.active; - } - } -} -exports.EventEmitter = EventEmitter; - -// By default EventEmitters will print a warning if more than -// 10 listeners are added to it. This is a useful default which -// helps finding memory leaks. -// -// Obviously not all Emitters should be limited to 10. This function allows -// that to be increased. Set to zero for unlimited. -var defaultMaxListeners = 10; -EventEmitter.prototype.setMaxListeners = function(n) { - if (!this._events) this._events = {}; - this._maxListeners = n; -}; - -// non-global reference, for speed. -var PROCESS; - -EventEmitter.prototype.emit = function() { - var type = arguments[0]; - // If there is no 'error' event listener then throw. - if (type === 'error') { - if (!this._events || !this._events.error || - (isArray(this._events.error) && !this._events.error.length)) - { - if (this.domain) { - var er = arguments[1]; - er.domain_emitter = this; - er.domain = this.domain; - er.domain_thrown = false; - this.domain.emit('error', er); - return false; - } - - if (arguments[1] instanceof Error) { - throw arguments[1]; // Unhandled 'error' event - } else { - throw new Error("Uncaught, unspecified 'error' event."); - } - return false; - } - } - - if (!this._events) return false; - var handler = this._events[type]; - if (!handler) return false; - - if (typeof handler == 'function') { - if (this.domain) { - PROCESS = PROCESS || process; - if (this !== PROCESS) { - this.domain.enter(); - } - } - switch (arguments.length) { - // fast cases - case 1: - handler.call(this); - break; - case 2: - handler.call(this, arguments[1]); - break; - case 3: - handler.call(this, arguments[1], arguments[2]); - break; - // slower - default: - var l = arguments.length; - var args = new Array(l - 1); - for (var i = 1; i < l; i++) args[i - 1] = arguments[i]; - handler.apply(this, args); - } - if (this.domain && this !== PROCESS) { - this.domain.exit(); - } - return true; - - } else if (isArray(handler)) { - if (this.domain) { - PROCESS = PROCESS || process; - if (this !== PROCESS) { - this.domain.enter(); - } - } - var l = arguments.length; - var args = new Array(l - 1); - for (var i = 1; i < l; i++) args[i - 1] = arguments[i]; - - var listeners = handler.slice(); - for (var i = 0, l = listeners.length; i < l; i++) { - listeners[i].apply(this, args); - } - if (this.domain && this !== PROCESS) { - this.domain.exit(); - } - return true; - - } else { - return false; - } -}; - -EventEmitter.prototype.addListener = function(type, listener) { - if ('function' !== typeof listener) { - throw new Error('addListener only takes instances of Function'); - } - - if (!this._events) this._events = {}; - - // To avoid recursion in the case that type == "newListeners"! Before - // adding it to the listeners, first emit "newListeners". - if (this._events.newListener) { - this.emit('newListener', type, typeof listener.listener === 'function' ? - listener.listener : listener); - } - - if (!this._events[type]) { - // Optimize the case of one listener. Don't need the extra array object. - this._events[type] = listener; - } else if (isArray(this._events[type])) { - - // If we've already got an array, just append. - this._events[type].push(listener); - - } else { - // Adding the second element, need to change to array. - this._events[type] = [this._events[type], listener]; - - } - - // Check for listener leak - if (isArray(this._events[type]) && !this._events[type].warned) { - var m; - if (this._maxListeners !== undefined) { - m = this._maxListeners; - } else { - m = defaultMaxListeners; - } - - if (m && m > 0 && this._events[type].length > m) { - this._events[type].warned = true; - console.error('(node) warning: possible EventEmitter memory ' + - 'leak detected. %d listeners added. ' + - 'Use emitter.setMaxListeners() to increase limit.', - this._events[type].length); - console.trace(); - } - } - - return this; -}; - -EventEmitter.prototype.on = EventEmitter.prototype.addListener; - -EventEmitter.prototype.once = function(type, listener) { - if ('function' !== typeof listener) { - throw new Error('.once only takes instances of Function'); - } - - var self = this; - function g() { - self.removeListener(type, g); - listener.apply(this, arguments); - }; - - g.listener = listener; - self.on(type, g); - - return this; -}; - -// emits a 'removeListener' event iff the listener was removed -EventEmitter.prototype.removeListener = function(type, listener) { - if ('function' !== typeof listener) { - throw new Error('removeListener only takes instances of Function'); - } - - // does not use listeners(), so no side effect of creating _events[type] - if (!this._events || !this._events[type]) return this; - - var list = this._events[type]; - - if (isArray(list)) { - var position = -1; - for (var i = 0, length = list.length; i < length; i++) { - if (list[i] === listener || - (list[i].listener && list[i].listener === listener)) - { - position = i; - break; - } - } - - if (position < 0) return this; - list.splice(position, 1); - if (list.length == 0) - delete this._events[type]; - - if (this._events.removeListener) { - this.emit('removeListener', type, listener); - } - } else if (list === listener || - (list.listener && list.listener === listener)) - { - delete this._events[type]; - - if (this._events.removeListener) { - this.emit('removeListener', type, listener); - } - } - - return this; -}; - -EventEmitter.prototype.removeAllListeners = function(type) { - if (!this._events) return this; - - // fast path - if (!this._events.removeListener) { - if (arguments.length === 0) { - this._events = {}; - } else if (type && this._events && this._events[type]) { - this._events[type] = null; - } - return this; - } - - // slow(ish) path, emit 'removeListener' events for all removals - if (arguments.length === 0) { - for (var key in this._events) { - if (key === 'removeListener') continue; - this.removeAllListeners(key); - } - this.removeAllListeners('removeListener'); - this._events = {}; - return this; - } - - var listeners = this._events[type]; - if (isArray(listeners)) { - while (listeners.length) { - // LIFO order - this.removeListener(type, listeners[listeners.length - 1]); - } - } else if (listeners) { - this.removeListener(type, listeners); - } - this._events[type] = null; - - return this; -}; - -EventEmitter.prototype.listeners = function(type) { - if (!this._events || !this._events[type]) return []; - if (!isArray(this._events[type])) { - return [this._events[type]]; - } - return this._events[type].slice(0); -}; \ No newline at end of file diff --git a/src/js/remote.js b/src/js/remote.js index eecc7a1582..3ab91051b7 100644 --- a/src/js/remote.js +++ b/src/js/remote.js @@ -17,7 +17,7 @@ // npm var WebSocket = require('ws'); -var EventEmitter = require('./events').EventEmitter; +var EventEmitter = require('events').EventEmitter; var Amount = require('./amount.js').Amount; var UInt160 = require('./amount.js').UInt160; From b2711925477e6c4edc12e1bedea4de0aa236261c Mon Sep 17 00:00:00 2001 From: Arthur Britto Date: Wed, 7 Nov 2012 16:03:39 -0800 Subject: [PATCH 4/6] Rework config.js to not be add to web pack. --- src/js/amount.js | 11 +++++------ src/js/remote.js | 9 +++------ test/amount-test.js | 2 ++ test/offer-test.js | 3 +++ test/remote-test.js | 3 +++ test/send-test.js | 3 +++ test/testutils.js | 3 +++ test/websocket-test.js | 2 ++ 8 files changed, 24 insertions(+), 12 deletions(-) diff --git a/src/js/amount.js b/src/js/amount.js index e9426d461f..3fd7c357d7 100644 --- a/src/js/amount.js +++ b/src/js/amount.js @@ -6,13 +6,10 @@ var bn = require('./sjcl/core.js').bn; var utils = require('./utils.js'); var jsbn = require('./jsbn.js'); -// Don't include in browser context. -var config = require('../../test/config.js'); - var BigInteger = jsbn.BigInteger; var nbi = jsbn.nbi; -var alphabets = { +var alphabets = { 'ripple' : "rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz", 'bitcoin' : "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz" }; @@ -158,8 +155,8 @@ UInt160.prototype.equals = function(d) { // 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 (exports.config.accounts && j in exports.config.accounts) + j = exports.config.accounts[j].account; switch (j) { case undefined: @@ -603,6 +600,8 @@ exports.Amount = Amount; exports.Currency = Currency; exports.UInt160 = UInt160; +exports.config = {}; + exports.consts = { 'address_xns' : "rrrrrrrrrrrrrrrrrrrrrhoLvTp", 'address_one' : "rrrrrrrrrrrrrrrrrrrrBZbvji", diff --git a/src/js/remote.js b/src/js/remote.js index 3ab91051b7..44ed3b38bb 100644 --- a/src/js/remote.js +++ b/src/js/remote.js @@ -21,9 +21,6 @@ var EventEmitter = require('events').EventEmitter; var Amount = require('./amount.js').Amount; var UInt160 = require('./amount.js').UInt160; -// Don't include in browser context. -var config = require('../../test/config.js'); - // Request events emmitted: // 'success' : Request successful. // 'error' : Request failed. @@ -159,7 +156,6 @@ var Remote = function (trusted, websocket_ip, websocket_port, trace) { this.state = 'offline'; // 'online', 'offline' this.retry_timer = undefined; this.retry = undefined; - this.config = config || { 'accounts' : {}}; // Cache information for accounts. this.accounts = { @@ -182,7 +178,7 @@ var Remote = function (trusted, websocket_ip, websocket_port, trace) { Remote.prototype = new EventEmitter; Remote.from_config = function (name, trace) { - var serverConfig = config.servers[name]; + var serverConfig = exports.config.servers[name]; return new Remote(serverConfig.trusted, serverConfig.websocket_ip, serverConfig.websocket_port, trace); }; @@ -1141,7 +1137,7 @@ Transaction.prototype.set_flags = function (flags) { Transaction.prototype._account_secret = function (account) { // Fill in secret from config, if needed. - return this.remote.config.accounts[account] ? this.remote.config.accounts[account].secret : undefined; + return exports.config.accounts && exports.config.accounts[account] ? exports.config.accounts[account].secret : undefined; }; // Options: @@ -1268,6 +1264,7 @@ Transaction.prototype.wallet_add = function (src, amount, authorized_key, public return this; }; +exports.config = {}; exports.Remote = Remote; // vim:sw=2:sts=2:ts=8 diff --git a/test/amount-test.js b/test/amount-test.js index 4c7388708b..841b07893f 100644 --- a/test/amount-test.js +++ b/test/amount-test.js @@ -8,6 +8,8 @@ var amount = require("../src/js/amount.js"); var Amount = require("../src/js/amount.js").Amount; var UInt160 = require("../src/js/amount.js").UInt160; +require("../src/js/amount.js").config = require("./config.js"); + var config = require('./config.js'); buster.testCase("Amount", { diff --git a/test/offer-test.js b/test/offer-test.js index b4b5e437eb..10ec4444bf 100644 --- a/test/offer-test.js +++ b/test/offer-test.js @@ -8,6 +8,9 @@ var Server = require("./server.js").Server; var testutils = require("./testutils.js"); +require("../src/js/amount.js").config = require("./config.js"); +require("../src/js/remote.js").config = require("./config.js"); + buster.testRunner.timeout = 5000; buster.testCase("Offer tests", { diff --git a/test/remote-test.js b/test/remote-test.js index f2596cbfb2..ab5d2c9b09 100644 --- a/test/remote-test.js +++ b/test/remote-test.js @@ -6,6 +6,9 @@ var Server = require("./server.js").Server; var testutils = require("./testutils.js"); +require("../src/js/amount.js").config = require("./config.js"); +require("../src/js/remote.js").config = require("./config.js"); + var fastTearDown = true; // How long to wait for server to start. diff --git a/test/send-test.js b/test/send-test.js index ad316ffa3b..5061414538 100644 --- a/test/send-test.js +++ b/test/send-test.js @@ -7,6 +7,9 @@ var Server = require("./server.js").Server; var testutils = require("./testutils.js"); +require("../src/js/amount.js").config = require("./config.js"); +require("../src/js/remote.js").config = require("./config.js"); + // How long to wait for server to start. var serverDelay = 1500; diff --git a/test/testutils.js b/test/testutils.js index 94883eaf4b..a82cc1a415 100644 --- a/test/testutils.js +++ b/test/testutils.js @@ -5,6 +5,9 @@ var Amount = require("../src/js/amount.js").Amount; var Remote = require("../src/js/remote.js").Remote; var Server = require("./server.js").Server; +require("../src/js/amount.js").config = require("./config.js"); +require("../src/js/remote.js").config = require("./config.js"); + var config = require("./config.js"); /** diff --git a/test/websocket-test.js b/test/websocket-test.js index 1afccc943d..c401165302 100644 --- a/test/websocket-test.js +++ b/test/websocket-test.js @@ -3,6 +3,8 @@ var buster = require("buster"); var Server = require("./server.js").Server; var Remote = require("../src/js/remote.js").Remote; +require("../src/js/remote.js").config = require("./config.js"); + // How long to wait for server to start. var serverDelay = 1500; From af7ee234a4813fb14ffe965a34d80dee9890857f Mon Sep 17 00:00:00 2001 From: Stefan Thomas Date: Wed, 7 Nov 2012 15:21:40 -0800 Subject: [PATCH 5/6] Fix building JS code as exported library. --- webpack.js | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/webpack.js b/webpack.js index a1ff10ddbe..d4cd814415 100644 --- a/webpack.js +++ b/webpack.js @@ -16,15 +16,11 @@ var builds = [{ minimize: true }]; - -async.series(builds.map(build), function (err) { - if (err) { - console.error(err); - } -}); - var defaultOpts = { - library: 'ripple', + // [sic] Yes, this is the spelling upstream. + libary: 'ripple', + // However, it's fixed in webpack 0.8, so we include the correct spelling too: + library: 'ripple' }; function build(opts) { var opts = extend({}, defaultOpts, opts); @@ -37,3 +33,9 @@ function build(opts) { }); } } + +async.series(builds.map(build), function (err) { + if (err) { + console.error(err); + } +}); From b96f9bacdd978d7c2bbcf13df25e6b9fcd48d168 Mon Sep 17 00:00:00 2001 From: Stefan Thomas Date: Wed, 7 Nov 2012 17:38:42 -0800 Subject: [PATCH 6/6] Store secrets on the remote object, rather than accessing the config directly. --- src/js/remote.js | 35 +++++++++++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/src/js/remote.js b/src/js/remote.js index 44ed3b38bb..793db9311e 100644 --- a/src/js/remote.js +++ b/src/js/remote.js @@ -165,7 +165,14 @@ var Remote = function (trusted, websocket_ip, websocket_port, trace) { // account : { seq : __ } }; - + + // 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 = { @@ -180,7 +187,21 @@ Remote.prototype = new EventEmitter; Remote.from_config = function (name, trace) { var serverConfig = exports.config.servers[name]; - return new Remote(serverConfig.trusted, serverConfig.websocket_ip, serverConfig.websocket_port, trace); + var remote = new Remote(serverConfig.trusted, serverConfig.websocket_ip, serverConfig.websocket_port, trace); + + for (var account in exports.config.accounts) { + var accountInfo = exports.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) { @@ -774,6 +795,12 @@ Remote.prototype.dirty_account_root = function (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 @@ -1136,8 +1163,8 @@ Transaction.prototype.set_flags = function (flags) { // Transaction.prototype._account_secret = function (account) { - // Fill in secret from config, if needed. - return exports.config.accounts && exports.config.accounts[account] ? exports.config.accounts[account].secret : undefined; + // Fill in secret from remote, if available. + return this.remote.secrets[account]; }; // Options: