From 424a2a424baf5072689d379ceaf1e22d40847c69 Mon Sep 17 00:00:00 2001 From: Arthur Britto Date: Thu, 4 Oct 2012 12:36:56 -0700 Subject: [PATCH 1/7] WS: revise ledger and ledger_index to indicate current or closed ledger. --- src/WSDoor.cpp | 69 +++++++++++++++++++++++++++++++------------------- 1 file changed, 43 insertions(+), 26 deletions(-) diff --git a/src/WSDoor.cpp b/src/WSDoor.cpp index 208c5c71c3..f45299ec32 100644 --- a/src/WSDoor.cpp +++ b/src/WSDoor.cpp @@ -89,8 +89,8 @@ public: void doAccountTransactionSubscribe(Json::Value& jvResult, const Json::Value& jvRequest); void doAccountTransactionUnsubscribe(Json::Value& jvResult, const Json::Value& jvRequest); - void doLedgerSubcribe(Json::Value& jvResult, const Json::Value& jvRequest); - void doLedgerUnsubscribe(Json::Value& jvResult, const Json::Value& jvRequest); + void doServerSubscribe(Json::Value& jvResult, const Json::Value& jvRequest); + void doServerUnsubscribe(Json::Value& jvResult, const Json::Value& jvRequest); void doLedgerAccountsSubcribe(Json::Value& jvResult, const Json::Value& jvRequest); void doLedgerAccountsUnsubscribe(Json::Value& jvResult, const Json::Value& jvRequest); void doTransactionSubcribe(Json::Value& jvResult, const Json::Value& jvRequest); @@ -311,10 +311,10 @@ Json::Value WSConnection::invokeCommand(const Json::Value& jvRequest) { "account_info_unsubscribe", &WSConnection::doAccountInfoUnsubscribe }, { "account_transaction_subscribe", &WSConnection::doAccountTransactionSubscribe }, { "account_transaction_unsubscribe", &WSConnection::doAccountTransactionUnsubscribe }, - { "ledger_subscribe", &WSConnection::doLedgerSubcribe }, - { "ledger_unsubscribe", &WSConnection::doLedgerUnsubscribe }, { "ledger_accounts_subscribe", &WSConnection::doLedgerAccountsSubcribe }, { "ledger_accounts_unsubscribe", &WSConnection::doLedgerAccountsUnsubscribe }, + { "server_subscribe", &WSConnection::doServerSubscribe }, + { "server_unsubscribe", &WSConnection::doServerUnsubscribe }, { "transaction_subscribe", &WSConnection::doTransactionSubcribe }, { "transaction_unsubscribe", &WSConnection::doTransactionUnsubscribe }, }; @@ -523,22 +523,6 @@ void WSConnection::doAccountTransactionUnsubscribe(Json::Value& jvResult, const } } -void WSConnection::doLedgerSubcribe(Json::Value& jvResult, const Json::Value& jvRequest) -{ - if (!theApp->getOPs().subLedger(this)) - { - jvResult["error"] = "ledgerSubscribed"; - } -} - -void WSConnection::doLedgerUnsubscribe(Json::Value& jvResult, const Json::Value& jvRequest) -{ - if (!theApp->getOPs().unsubLedger(this)) - { - jvResult["error"] = "ledgerNotSubscribed"; - } -} - void WSConnection::doLedgerAccountsSubcribe(Json::Value& jvResult, const Json::Value& jvRequest) { if (!theApp->getOPs().subLedgerAccounts(this)) @@ -559,13 +543,13 @@ void WSConnection::doLedgerClosed(Json::Value& jvResult, const Json::Value& jvRe { uint256 uLedger = theApp->getOPs().getClosedLedger(); - jvResult["ledger_index"] = theApp->getOPs().getLedgerID(uLedger); - jvResult["ledger"] = uLedger.ToString(); + jvResult["ledger_closed_index"] = theApp->getOPs().getLedgerID(uLedger); + jvResult["ledger_closed"] = uLedger.ToString(); } void WSConnection::doLedgerCurrent(Json::Value& jvResult, const Json::Value& jvRequest) { - jvResult["ledger_index"] = theApp->getOPs().getCurrentLedgerID(); + jvResult["ledger_current_index"] = theApp->getOPs().getCurrentLedgerID(); } void WSConnection::doLedgerEntry(Json::Value& jvResult, const Json::Value& jvRequest) @@ -606,10 +590,17 @@ void WSConnection::doLedgerEntry(Json::Value& jvResult, const Json::Value& jvReq uLedgerIndex = lpLedger->getLedgerSeq(); // Set the current index. } - if (!!uLedger) - jvResult["ledger"] = uLedger.ToString(); + if (lpLedger->isClosed()) + { + if (!!uLedger) + jvResult["ledger_closed"] = uLedger.ToString(); - jvResult["ledger_index"] = uLedgerIndex; + jvResult["ledger_closed_index"] = uLedgerIndex; + } + else + { + jvResult["ledger_current_index"] = uLedgerIndex; + } uint256 uNodeIndex; bool bNodeBinary = false; @@ -788,6 +779,32 @@ void WSConnection::doLedgerEntry(Json::Value& jvResult, const Json::Value& jvReq } } +void WSConnection::doServerSubscribe(Json::Value& jvResult, const Json::Value& jvRequest) +{ + if (!theApp->getOPs().subLedger(this)) + { + jvResult["error"] = "serverSubscribed"; + } + else + { + if (theConfig.RUN_STANDALONE) + jvResult["stand_alone"] = 1; + + // XXX Make sure these values are available before returning them. + // XXX return connected status. + jvResult["ledger_closed"] = theApp->getOPs().getClosedLedger().ToString(); + jvResult["ledger_current_index"] = theApp->getOPs().getCurrentLedgerID(); + } +} + +void WSConnection::doServerUnsubscribe(Json::Value& jvResult, const Json::Value& jvRequest) +{ + if (!theApp->getOPs().unsubLedger(this)) + { + jvResult["error"] = "serverNotSubscribed"; + } +} + void WSConnection::doTransactionSubcribe(Json::Value& jvResult, const Json::Value& jvRequest) { if (!theApp->getOPs().subTransaction(this)) From f7562efa855f130118cbc8a746f138f3fcce145c Mon Sep 17 00:00:00 2001 From: Arthur Britto Date: Thu, 4 Oct 2012 17:38:58 -0700 Subject: [PATCH 2/7] UT: Add accounts to config. --- test/config.js | 42 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/test/config.js b/test/config.js index 0610373db9..86867dc716 100644 --- a/test/config.js +++ b/test/config.js @@ -10,7 +10,7 @@ exports.newcoind = path.join(process.cwd(), "newcoind"); // Configuration for servers. exports.servers = { // A local test server. - alpha : { + 'alpha' : { 'trusted' : true, // "peer_ip" : "0.0.0.0", // "peer_port" : 51235, @@ -22,4 +22,44 @@ exports.servers = { 'validators' : "n9L8LZZCwsdXzKUN9zoVxs4YznYXZ9hEhsQZY7aVpxtFaSceiyDZ beta" } }; + +// Configuration for test accounts. +exports.accounts = { + // Users + 'alice' : { + 'account' : 'iG1QQv2nh2gi7RCZ1P8YYcBUKCCN633jCn', + 'passphrase' : 'alice', + }, + 'bob' : { + 'account' : 'iPMh7Pr9ct699rZUTWaytJUoHcJ7cgyzrK', + 'passphrase' : 'bob', + }, + 'carol' : { + 'account' : 'iH4KEcG9dEwGwpn6AyoWK9cZPLL4RLSmWW', + 'passphrase' : 'carol', + }, + + // Nexuses + 'bitstamp' : { + 'account' : 'i4jKmc2nQb5yEU6eycefrNKGHTU5NQJASx', + 'passphrase' : 'bitstamp', + }, + 'mtgox' : { + 'account' : 'iGrhwhaqU8g7ahwAvTq6rX5ivsfcbgZw6v', + 'passphrase' : 'mtgox', + }, + + // Merchants + 'amazon' : { + 'account' : 'ihheXqX7bDnXePJeMHhubDDvw2uUTtenPd', + 'passphrase' : 'amazon', + }, + + // Master account + 'root' : { + 'account' : 'iHb9CJAWyB4ij91VRWn96DkukG4bwdtyTh', + 'passphrase' : 'masterpassphrase', + }, +}; + // vim:ts=4 From ef81dd7caf8ab2d58dc4d91c1efd2eca517bb757 Mon Sep 17 00:00:00 2001 From: Arthur Britto Date: Thu, 4 Oct 2012 17:40:10 -0700 Subject: [PATCH 3/7] UT: retab test/config.js --- test/config.js | 90 +++++++++++++++++++++++++------------------------- 1 file changed, 45 insertions(+), 45 deletions(-) diff --git a/test/config.js b/test/config.js index 86867dc716..10d084a532 100644 --- a/test/config.js +++ b/test/config.js @@ -9,57 +9,57 @@ exports.newcoind = path.join(process.cwd(), "newcoind"); // Configuration for servers. exports.servers = { - // A local test server. - 'alpha' : { - 'trusted' : true, - // "peer_ip" : "0.0.0.0", - // "peer_port" : 51235, - 'rpc_ip' : "0.0.0.0", - 'rpc_port' : 5005, - 'websocket_ip' : "127.0.0.1", - 'websocket_port' : 6005, - 'validation_seed' : "shhDFVsmS2GSu5vUyZSPXYfj1r79h", - 'validators' : "n9L8LZZCwsdXzKUN9zoVxs4YznYXZ9hEhsQZY7aVpxtFaSceiyDZ beta" - } + // A local test server. + 'alpha' : { + 'trusted' : true, + // "peer_ip" : "0.0.0.0", + // "peer_port" : 51235, + 'rpc_ip' : "0.0.0.0", + 'rpc_port' : 5005, + 'websocket_ip' : "127.0.0.1", + 'websocket_port' : 6005, + 'validation_seed' : "shhDFVsmS2GSu5vUyZSPXYfj1r79h", + 'validators' : "n9L8LZZCwsdXzKUN9zoVxs4YznYXZ9hEhsQZY7aVpxtFaSceiyDZ beta" + } }; // Configuration for test accounts. exports.accounts = { - // Users - 'alice' : { - 'account' : 'iG1QQv2nh2gi7RCZ1P8YYcBUKCCN633jCn', - 'passphrase' : 'alice', - }, - 'bob' : { - 'account' : 'iPMh7Pr9ct699rZUTWaytJUoHcJ7cgyzrK', - 'passphrase' : 'bob', - }, - 'carol' : { - 'account' : 'iH4KEcG9dEwGwpn6AyoWK9cZPLL4RLSmWW', - 'passphrase' : 'carol', - }, + // Users + 'alice' : { + 'account' : 'iG1QQv2nh2gi7RCZ1P8YYcBUKCCN633jCn', + 'passphrase' : 'alice', + }, + 'bob' : { + 'account' : 'iPMh7Pr9ct699rZUTWaytJUoHcJ7cgyzrK', + 'passphrase' : 'bob', + }, + 'carol' : { + 'account' : 'iH4KEcG9dEwGwpn6AyoWK9cZPLL4RLSmWW', + 'passphrase' : 'carol', + }, - // Nexuses - 'bitstamp' : { - 'account' : 'i4jKmc2nQb5yEU6eycefrNKGHTU5NQJASx', - 'passphrase' : 'bitstamp', - }, - 'mtgox' : { - 'account' : 'iGrhwhaqU8g7ahwAvTq6rX5ivsfcbgZw6v', - 'passphrase' : 'mtgox', - }, + // Nexuses + 'bitstamp' : { + 'account' : 'i4jKmc2nQb5yEU6eycefrNKGHTU5NQJASx', + 'passphrase' : 'bitstamp', + }, + 'mtgox' : { + 'account' : 'iGrhwhaqU8g7ahwAvTq6rX5ivsfcbgZw6v', + 'passphrase' : 'mtgox', + }, - // Merchants - 'amazon' : { - 'account' : 'ihheXqX7bDnXePJeMHhubDDvw2uUTtenPd', - 'passphrase' : 'amazon', - }, + // Merchants + 'amazon' : { + 'account' : 'ihheXqX7bDnXePJeMHhubDDvw2uUTtenPd', + 'passphrase' : 'amazon', + }, - // Master account - 'root' : { - 'account' : 'iHb9CJAWyB4ij91VRWn96DkukG4bwdtyTh', - 'passphrase' : 'masterpassphrase', - }, + // Master account + 'root' : { + 'account' : 'iHb9CJAWyB4ij91VRWn96DkukG4bwdtyTh', + 'passphrase' : 'masterpassphrase', + }, }; -// vim:ts=4 +// vim:sw=2:sts=2:ts=8 From 534b5980a10628f033620f2b9cdf8b188a611853 Mon Sep 17 00:00:00 2001 From: Arthur Britto Date: Thu, 4 Oct 2012 17:50:46 -0700 Subject: [PATCH 4/7] JS: Rework remote framework. --- js/remote.js | 401 +++++++++++++++++++++++++++------------- test/standalone-test.js | 279 ++++++++++++++-------------- 2 files changed, 417 insertions(+), 263 deletions(-) diff --git a/js/remote.js b/js/remote.js index ffab43eaad..75e932979b 100644 --- a/js/remote.js +++ b/js/remote.js @@ -12,194 +12,347 @@ var util = require('util'); var WebSocket = require('ws'); // --> trusted: truthy, if remote is trusted -var Remote = function(trusted, websocket_ip, websocket_port, trace) { - this.trusted = trusted; - this.websocket_ip = websocket_ip; - this.websocket_port = websocket_port; - this.id = 0; - this.trace = trace; +var Remote = function (trusted, websocket_ip, websocket_port, trace) { + this.trusted = trusted; + this.websocket_ip = websocket_ip; + this.websocket_port = websocket_port; + this.id = 0; + this.trace = trace; + this.ledger_closed = undefined; + this.ledger_current_index = undefined; + this.stand_alone = undefined; + + // Cache information for accounts. + this.accounts = { + }; + + // Cache for various ledgers. + // XXX Clear when ledger advances. + this.ledgers = { + 'current' : {} + }; }; -var remoteConfig = function(config, server, trace) { - var serverConfig = config.servers[server]; +var remoteConfig = function (config, server, trace) { + var serverConfig = config.servers[server]; - return new Remote(serverConfig.trusted, serverConfig.websocket_ip, serverConfig.websocket_port, trace); + return new Remote(serverConfig.trusted, serverConfig.websocket_ip, serverConfig.websocket_port, trace); }; -Remote.method('connect_helper', function() { - var self = this; +// XXX This needs to be determined from the network. +var fees = { + 'default' : 100, + 'account_create' : 1000, + 'nickname_create' : 1000, + 'offer' : 100, +}; - if (this.trace) - console.log("remote: connect: %s", this.url); +// For accounts we cache things like sequence numbers. +var 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. - this.ws = new WebSocket(this.url); +// acount : { seq : __ } +}; - var ws = this.ws; +Remote.method('connect_helper', function () { + var self = this; - ws.response = {}; + if (this.trace) + console.log("remote: connect: %s", this.url); - ws.onopen = function() { + this.ws = new WebSocket(this.url); + + var ws = this.ws; + + ws.response = {}; + + ws.onopen = function () { + if (this.trace) + console.log("remote: onopen: %s", ws.readyState); + + ws.onclose = undefined; + ws.onerror = undefined; + + self.done(ws.readyState); + }; + + ws.onerror = function () { + if (this.trace) + console.log("remote: onerror: %s", ws.readyState); + + ws.onclose = undefined; + + if (self.expire) { + if (this.trace) + console.log("remote: was expired"); + + self.done(ws.readyState); + } + else + { + // Delay and retry. + setTimeout(function () { if (this.trace) - console.log("remote: onopen: %s", ws.readyState); + console.log("remote: retry"); - ws.onclose = undefined; - ws.onerror = undefined; + self.connect_helper(); + }, 50); // Retry rate 50ms. + } + }; - self.done(ws.readyState); - }; + // Covers failure to open. + ws.onclose = function () { + if (this.trace) + console.log("remote: onclose: %s", ws.readyState); - ws.onerror = function() { - if (this.trace) - console.log("remote: onerror: %s", ws.readyState); + ws.onerror = undefined; - ws.onclose = undefined; + self.done(ws.readyState); + }; - if (self.expire) { - if (this.trace) - console.log("remote: was expired"); + // Node's ws module doesn't pass arguments to onmessage. + ws.on('message', function (json, flags) { + var message = JSON.parse(json); + // console.log("message: %s", json); - self.done(ws.readyState); - } - else - { - // Delay and retry. - setTimeout(function() { - if (this.trace) - console.log("remote: retry"); + if (message.type !== 'response') { + console.log("unexpected message: %s", json); - self.connect_helper(); - }, 50); // Retry rate 50ms. - } - }; + } else { + var done = ws.response[message.id]; - // Covers failure to open. - ws.onclose = function() { - if (this.trace) - console.log("remote: onclose: %s", ws.readyState); + if (done) { + done(message); - ws.onerror = undefined; - - self.done(ws.readyState); - }; - - // Node's ws module doesn't pass arguments to onmessage. - ws.on('message', function(json, flags) { - var message = JSON.parse(json); - // console.log("message: %s", json); - - if (message.type !== 'response') { - console.log("unexpected message: %s", json); - - } else { - var done = ws.response[message.id]; - - if (done) { - done(message); - - } else { - console.log("unexpected message id: %s", json); - } - } - }); + } else { + console.log("unexpected message id: %s", json); + } + } + }); }); // Target state is connectted. // done(readyState): // --> readyState: OPEN, CLOSED -Remote.method('connect', function(done, timeout) { - var self = this; +Remote.method('connect', function (done, timeout) { + var self = this; - this.url = util.format("ws://%s:%s", this.websocket_ip, this.websocket_port); - this.done = done; + this.url = util.format("ws://%s:%s", this.websocket_ip, this.websocket_port); + this.done = done; - if (timeout) { + if (timeout) { + if (this.trace) + console.log("remote: expire: false"); + + this.expire = false; + + setTimeout(function () { if (this.trace) - console.log("remote: expire: false"); + console.log("remote: expire: timeout"); - this.expire = false; + self.expire = true; + }, timeout); + } + else { + if (this.trace) + console.log("remote: expire: false"); - setTimeout(function () { - if (this.trace) - console.log("remote: expire: timeout"); + this.expire = true; + } - self.expire = true; - }, timeout); - } - else { - if (this.trace) - console.log("remote: expire: false"); - - this.expire = true; - } - - this.connect_helper(); + this.connect_helper(); }); // Target stated is disconnected. -Remote.method('disconnect', function(done) { - var ws = this.ws; +Remote.method('disconnect', function (done) { + var ws = this.ws; - ws.onclose = function() { - if (this.trace) - console.log("remote: onclose: %s", ws.readyState); + ws.onclose = function () { + if (this.trace) + console.log("remote: onclose: %s", ws.readyState); - done(ws.readyState); - }; + done(ws.readyState); + }; - ws.close(); + ws.close(); }); // Send a command. The comman should lack the id. // <-> command: what to send, consumed. -Remote.method('request', function(command, done) { - this.id += 1; // Advance id. +Remote.method('request', function (request, onDone, onFailure) { + this.id += 1; // Advance id. - var ws = this.ws; + var ws = this.ws; - command.id = this.id; + request.id = this.id; - ws.response[command.id] = done; + ws.response[request.id] = function (response) { + if (this.trace) + console.log("remote: response: %s", JSON.stringify(response)); - if (this.trace) - console.log("remote: send: %s", JSON.stringify(command)); + if (onFailure && response.error) + { + onFailure(response); + } + else + { + onDone(response); + } + }; - ws.send(JSON.stringify(command)); + if (this.trace) + console.log("remote: request: %s", JSON.stringify(request)); + + ws.send(JSON.stringify(request)); }); -Remote.method('ledger_closed', function(done) { - assert(this.trusted); // If not trusted, need to check proof. +Remote.method('request_ledger_closed', function (onDone, onFailure) { + assert(this.trusted); // If not trusted, need to check proof. - this.request({ 'command' : 'ledger_closed' }, done); + this.request({ 'command' : 'ledger_closed' }, onDone, onFailure); }); // Get the current proposed ledger entry. May be closed (and revised) at any time (even before returning). // Only for use by unit tests. -Remote.method('ledger_current', function(done) { - this.request({ 'command' : 'ledger_current' }, done); +Remote.method('request_ledger_current', function (onDone, onFailure) { + this.request({ 'command' : 'ledger_current' }, onDone, onFailure); }); -// <-> params: -// --> ledger : optional -// --> ledger_index : optional -Remote.method('ledger_entry', function(params, done) { - assert(this.trusted); // If not trusted, need to check proof, maybe talk packet protocol. +// <-> request: +// --> ledger : optional +// --> ledger_index : optional +// --> type +Remote.method('request_ledger_entry', function (req, onDone, onFailure) { + assert(this.trusted); // If not trusted, need to check proof, maybe talk packet protocol. - params.command = 'ledger_entry'; + req.command = 'ledger_entry'; - this.request(params, done); + if (req.ledger_closed) + { + // XXX Initial implementation no caching. + + this.request(req, onDone, onFailure); + } + else if (req.ledger_index) + { + // Current + // XXX Only allow with standalone mode. Must sync response with advance. + var entry; + + switch (req.type) { + case 'account_root': + var cache = this.ledgers.current.account_root; + + if (!cache) + { + cache = this.ledgers.current.account_root = {}; + } + + var entry = this.ledgers.current.account_root[req.account]; + break; + + default: + // This type not cached. + } + + if (entry) + { + onDone(entry); + } + else + { + // Not cached. + + // Submit request + this.request(req, function (r) { + // Got result. + switch (req.type) { + case 'account_root': + this.ledgers.current.account_root.account = r; + break; + + default: + // This type not cached. + } + onDone(r); + }, onFailure); + } + } }); // Submit a json transaction. // done(value) // <-> value: { 'status', status, 'result' : result, ... } // done may be called up to 3 times. -Remote.method('submit', function(json, done) { -// this.request(..., function() { -// }); +Remote.method('submit', function (json, private_key, onDone, onFailure) { + var req = {}; + + req.command = 'submit'; + req.json = json; + + if (private_key && !this.trusted) + { + onFailure({ 'error' : 'untrustedSever', 'request' : req }); + } + else + { + this.request(req, onDone, onFailure); + } }); -exports.Remote = Remote; -exports.remoteConfig = remoteConfig; +// +// Higher level functions. +// -// vim:ts=4 +// Subscribe to a server to get the current and closed ledger. +// XXX Set up routine to update on notification. +Remote.method('server_subscribe', function (onDone, onFailure) { + this.request({ + 'command' : 'server_subscribe' + }, function (r) { + this.ledger_current_index = r.ledger_current_index; + this.ledger_closed = r.ledger_closed; + this.stand_alone = r.stand_alone; + + onDone(); + }, onFailure); +}); + +// Refresh accounts[account].seq +// done(result); +Remote.method('account_seq', function (account, onDone, onFailure) { + var account_root_entry = this.accounts[account]; + + if (account_root_entry && account_root_entry.seq) + { + onDone(account_root_entry.seq); + } + else + { + // Need to get the ledger entry. + this.request_ledger_entry({ + 'ledger' : this.ledger_closed, + 'account_root' : account + }, function (r) { + // Extract the seqence number from the account root entry. + this.accounts[account].seq = r.seq; + + onDone(r.seq); + + }, onFailure); + } +}); + +// A submit that fills in the sequence number. +Remote.method('submit_seq', function (onDone, onFailure) { + +}); + +exports.Remote = Remote; +exports.remoteConfig = remoteConfig; +exports.fees = fees; +exports.accounts = accounts; + +// vim:sw=2:sts=2:ts=8 diff --git a/test/standalone-test.js b/test/standalone-test.js index 6a18592a42..600e0a9df6 100644 --- a/test/standalone-test.js +++ b/test/standalone-test.js @@ -11,178 +11,179 @@ var serverDelay = 1500; buster.testRunner.timeout = 5000; buster.testCase("Standalone server startup", { - "server start and stop": function(done) { - server.start("alpha", - function(e) { - buster.refute(e); - server.stop("alpha", function(e) { - buster.refute(e); - done(); - }); - }); - } + "server start and stop": function (done) { + server.start("alpha", + function (e) { + buster.refute(e); + server.stop("alpha", function (e) { + buster.refute(e); + done(); + }); + }); + } }); buster.testCase("WebSocket connection", { - 'setUp' : - function(done) { - server.start("alpha", - function(e) { - buster.refute(e); - done(); - } - ); - }, + 'setUp' : + function (done) { + server.start("alpha", + function (e) { + buster.refute(e); + done(); + } + ); + }, - 'tearDown' : - function(done) { - server.stop("alpha", function(e) { - buster.refute(e); - done(); - }); - }, + 'tearDown' : + function (done) { + server.stop("alpha", function (e) { + buster.refute(e); + done(); + }); + }, - "websocket connect and disconnect" : - function(done) { - var alpha = remote.remoteConfig(config, "alpha"); + "websocket connect and disconnect" : + function (done) { + var alpha = remote.remoteConfig(config, "alpha"); - alpha.connect(function(stat) { - buster.assert(1 == stat); // OPEN + alpha.connect(function (stat) { + buster.assert(1 == stat); // OPEN - alpha.disconnect(function(stat) { - buster.assert(3 == stat); // CLOSED - done(); - }); - }, serverDelay); - }, + alpha.disconnect(function (stat) { + buster.assert(3 == stat); // CLOSED + done(); + }); + }, serverDelay); + }, }); buster.testCase("Websocket commands", { - 'setUp' : - function(done) { - server.start("alpha", - function(e) { - buster.refute(e); + 'setUp' : + function (done) { + server.start("alpha", + function (e) { + buster.refute(e); - alpha = remote.remoteConfig(config, "alpha"); + alpha = remote.remoteConfig(config, "alpha"); - alpha.connect(function(stat) { - buster.assert(1 == stat); // OPEN + alpha.connect(function (stat) { + buster.assert(1 == stat); // OPEN + done(); + }, serverDelay); + }); + }, - done(); - }, serverDelay); - }); - }, + 'tearDown' : + function (done) { + alpha.disconnect(function (stat) { + buster.assert(3 == stat); // CLOSED - 'tearDown' : - function(done) { - alpha.disconnect(function(stat) { - buster.assert(3 == stat); // CLOSED + server.stop("alpha", function (e) { + buster.refute(e); + done(); + }); + }); + }, - server.stop("alpha", function(e) { - buster.refute(e); + 'ledger_current' : + function (done) { + alpha.request_ledger_current(function (r) { + console.log(r); - done(); - }); - }); - }, + buster.assert.equals(r.ledger_current_index, 3); + done(); + }); + }, - 'ledger_current' : - function(done) { - alpha.ledger_current(function (r) { - console.log(r); + '// ledger_closed' : + function (done) { + alpha.request_ledger_closed(function (r) { + console.log("result: %s", JSON.stringify(r)); - buster.assert.equals(r.ledger_index, 3); - done(); - }); - }, + buster.assert.equals(r.ledger_closed_index, 2); + done(); + }); + }, - '// ledger_closed' : - function(done) { - alpha.ledger_closed(function (r) { - console.log("result: %s", JSON.stringify(r)); + 'account_root success' : + function (done) { + alpha.request_ledger_closed(function (r) { + // console.log("result: %s", JSON.stringify(r)); - buster.assert.equals(r.ledger_index, 2); - done(); - }); - }, + buster.refute(r.error); - 'account_root success' : - function(done) { - alpha.ledger_closed(function (r) { - // console.log("result: %s", JSON.stringify(r)); + alpha.request_ledger_entry({ + 'ledger_closed' : r.ledger_closed, + 'type' : 'account_root', + 'account_root' : 'iHb9CJAWyB4ij91VRWn96DkukG4bwdtyTh' + } , function (r) { + // console.log("account_root: %s", JSON.stringify(r)); - buster.refute('error' in r); + buster.assert('node' in r); + done(); + }); + }); + }, - alpha.ledger_entry({ - 'ledger_index' : r.ledger_index, - 'account_root' : 'iHb9CJAWyB4ij91VRWn96DkukG4bwdtyTh' - } , function (r) { - // console.log("account_root: %s", JSON.stringify(r)); + 'account_root malformedAddress' : + function (done) { + alpha.request_ledger_closed(function (r) { + // console.log("result: %s", JSON.stringify(r)); - buster.assert('node' in r); - done(); - }); - }); - }, + buster.refute(r.error); - 'account_root malformedAddress' : - function(done) { - alpha.ledger_closed(function (r) { - // console.log("result: %s", JSON.stringify(r)); + alpha.request_ledger_entry({ + 'ledger_closed' : r.ledger_closed, + 'type' : 'account_root', + 'account_root' : 'foobar' + } , function (r) { + // console.log("account_root: %s", JSON.stringify(r)); - buster.refute('error' in r); + buster.assert.equals(r.error, 'malformedAddress'); + done(); + }); + }); + }, - alpha.ledger_entry({ - 'ledger_index' : r.ledger_index, - 'account_root' : 'foobar' - } , function (r) { - // console.log("account_root: %s", JSON.stringify(r)); + 'account_root entryNotFound' : + function (done) { + alpha.request_ledger_closed(function (r) { + console.log("result: %s", JSON.stringify(r)); - buster.assert.equals(r.error, 'malformedAddress'); - done(); - }); - }); - }, + buster.refute(r.error); - 'account_root entryNotFound' : - function(done) { - alpha.ledger_closed(function (r) { - // console.log("result: %s", JSON.stringify(r)); + alpha.request_ledger_entry({ + 'ledger_closed' : r.ledger_closed, + 'type' : 'account_root', + 'account_root' : 'iG1QQv2nh2gi7RCZ1P8YYcBUKCCN633jCn' + }, function (r) { + console.log("account_root: %s", JSON.stringify(r)); - buster.refute('error' in r); + buster.assert.equals(r.error, 'entryNotFound'); + done(); + }); + }); + }, - alpha.ledger_entry({ - 'ledger_index' : r.ledger_index, - 'account_root' : 'iG1QQv2nh2gi7RCZ1P8YYcBUKCCN633jCn' - } , function (r) { - // console.log("account_root: %s", JSON.stringify(r)); + 'ledger_entry index' : + function (done) { + alpha.request_ledger_closed(function (r) { + // console.log("result: %s", JSON.stringify(r)); - buster.assert.equals(r.error, 'entryNotFound'); - done(); - }); - }); - }, + buster.refute(r.error); - 'ledger_entry index' : - function(done) { - alpha.ledger_closed(function (r) { - // console.log("result: %s", JSON.stringify(r)); - - buster.refute('error' in r); - - alpha.ledger_entry({ - 'ledger_index' : r.ledger_index, - 'index' : "2B6AC232AA4C4BE41BF49D2459FA4A0347E1B543A4C92FCEE0821C0201E2E9A8", - } , function (r) { - console.log("node: %s", JSON.stringify(r)); - - buster.assert('node_binary' in r); - done(); - }); - }); - }, + alpha.request_ledger_entry({ + 'ledger_closed' : r.ledger_closed, + 'type' : 'account_root', + 'index' : "2B6AC232AA4C4BE41BF49D2459FA4A0347E1B543A4C92FCEE0821C0201E2E9A8", + } , function (r) { + console.log("node: %s", JSON.stringify(r)); + buster.assert('node_binary' in r); + done(); + }); + }); + }, }); -// vim:ts=4 +// vim:sw=2:sts=2:ts=8 From 0e3b4cc1a8ddff2bd9ac66f9d326a414d215159f Mon Sep 17 00:00:00 2001 From: Andrey Fedorov Date: Thu, 4 Oct 2012 21:04:19 -0400 Subject: [PATCH 5/7] a few formatting changes --- js/remote.js | 114 +++++++++++++++++++++++---------------------------- 1 file changed, 52 insertions(+), 62 deletions(-) diff --git a/js/remote.js b/js/remote.js index 75e932979b..f8f78e2a68 100644 --- a/js/remote.js +++ b/js/remote.js @@ -20,86 +20,76 @@ var Remote = function (trusted, websocket_ip, websocket_port, trace) { this.trace = trace; this.ledger_closed = undefined; this.ledger_current_index = undefined; - this.stand_alone = undefined; - + this.stand_alone = undefined; + // Cache information for accounts. - this.accounts = { - }; + this.account = {}; // Cache for various ledgers. // XXX Clear when ledger advances. - this.ledgers = { - 'current' : {} - }; + this.ledgers = { + 'current' : {} + }; }; var remoteConfig = function (config, server, trace) { - var serverConfig = config.servers[server]; - - return new Remote(serverConfig.trusted, serverConfig.websocket_ip, serverConfig.websocket_port, trace); + var serverConfig = config.servers[server]; + + return new Remote(serverConfig.trusted, serverConfig.websocket_ip, serverConfig.websocket_port, trace); }; // XXX This needs to be determined from the network. -var fees = { - 'default' : 100, - 'account_create' : 1000, - 'nickname_create' : 1000, - 'offer' : 100, +var fees = { + 'default' : 100, + 'account_create' : 1000, + 'nickname_create' : 1000, + 'offer' : 100, }; // For accounts we cache things like sequence numbers. var 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. - -// acount : { seq : __ } + // Consider sequence numbers stable if you know you're not generating bad transactions. + // Otherwise, clear it to have it automatically refreshed from the network. + + // acount : { seq : __ } }; Remote.method('connect_helper', function () { - var self = this; + var self = this; + + if (this.trace) console.log("remote: connect: %s", this.url); + + this.ws = new WebSocket(this.url); + + var ws = this.ws; + + ws.response = {}; + + ws.onopen = function () { + if (this.trace) console.log("remote: onopen: %s", ws.readyState); + + ws.onclose = undefined; + ws.onerror = undefined; + + self.done(ws.readyState); + }; - if (this.trace) - console.log("remote: connect: %s", this.url); - - this.ws = new WebSocket(this.url); - - var ws = this.ws; - - ws.response = {}; - - ws.onopen = function () { - if (this.trace) - console.log("remote: onopen: %s", ws.readyState); - - ws.onclose = undefined; - ws.onerror = undefined; - - self.done(ws.readyState); - }; - - ws.onerror = function () { - if (this.trace) - console.log("remote: onerror: %s", ws.readyState); - - ws.onclose = undefined; - - if (self.expire) { - if (this.trace) - console.log("remote: was expired"); - - self.done(ws.readyState); - } - else - { - // Delay and retry. - setTimeout(function () { - if (this.trace) - console.log("remote: retry"); - - self.connect_helper(); - }, 50); // Retry rate 50ms. - } - }; + ws.onerror = function () { + if (this.trace) console.log("remote: onerror: %s", ws.readyState); + + ws.onclose = undefined; + + if (self.expire) { + if (this.trace) console.log("remote: was expired"); + self.done(ws.readyState); + } else { + // Delay and retry. + setTimeout(function () { + if (this.trace) console.log("remote: retry"); + self.connect_helper(); + }, 50); // Retry rate 50ms. + } + }; // Covers failure to open. ws.onclose = function () { From 0076130be17634dc959705e8bdfcd8ec0ae348fe Mon Sep 17 00:00:00 2001 From: Andrey Fedorov Date: Thu, 4 Oct 2012 21:17:40 -0400 Subject: [PATCH 6/7] a few formatting changes --- js/remote.js | 255 ++++++++++++++++++++++++--------------------------- 1 file changed, 118 insertions(+), 137 deletions(-) diff --git a/js/remote.js b/js/remote.js index f8f78e2a68..de94590e37 100644 --- a/js/remote.js +++ b/js/remote.js @@ -13,14 +13,14 @@ var WebSocket = require('ws'); // --> trusted: truthy, if remote is trusted var Remote = function (trusted, websocket_ip, websocket_port, trace) { - this.trusted = trusted; - this.websocket_ip = websocket_ip; - this.websocket_port = websocket_port; - this.id = 0; - this.trace = trace; - this.ledger_closed = undefined; + this.trusted = trusted; + this.websocket_ip = websocket_ip; + this.websocket_port = websocket_port; + this.id = 0; + this.trace = trace; + this.ledger_closed = undefined; this.ledger_current_index = undefined; - this.stand_alone = undefined; + this.stand_alone = undefined; // Cache information for accounts. this.account = {}; @@ -34,7 +34,6 @@ var Remote = function (trusted, websocket_ip, websocket_port, trace) { var remoteConfig = function (config, server, trace) { var serverConfig = config.servers[server]; - return new Remote(serverConfig.trusted, serverConfig.websocket_ip, serverConfig.websocket_port, trace); }; @@ -59,9 +58,7 @@ Remote.method('connect_helper', function () { if (this.trace) console.log("remote: connect: %s", this.url); - this.ws = new WebSocket(this.url); - - var ws = this.ws; + var ws = this.ws = new WebSocket(this.url);; ws.response = {}; @@ -73,7 +70,7 @@ Remote.method('connect_helper', function () { self.done(ws.readyState); }; - + ws.onerror = function () { if (this.trace) console.log("remote: onerror: %s", ws.readyState); @@ -90,98 +87,82 @@ Remote.method('connect_helper', function () { }, 50); // Retry rate 50ms. } }; - - // Covers failure to open. - ws.onclose = function () { - if (this.trace) - console.log("remote: onclose: %s", ws.readyState); - - ws.onerror = undefined; - - self.done(ws.readyState); - }; - - // Node's ws module doesn't pass arguments to onmessage. - ws.on('message', function (json, flags) { - var message = JSON.parse(json); - // console.log("message: %s", json); - - if (message.type !== 'response') { - console.log("unexpected message: %s", json); - - } else { - var done = ws.response[message.id]; - - if (done) { - done(message); - - } else { - console.log("unexpected message id: %s", json); - } - } - }); + + // Covers failure to open. + ws.onclose = function () { + if (this.trace) console.log("remote: onclose: %s", ws.readyState); + ws.onerror = undefined; + self.done(ws.readyState); + }; + + // Node's ws module doesn't pass arguments to onmessage. + ws.on('message', function (json, flags) { + var message = JSON.parse(json); + // console.log("message: %s", json); + + if (message.type !== 'response') { + console.log("unexpected message: %s", json); + } else { + var done = ws.response[message.id]; + if (done) { + done(message); + } else { + console.log("unexpected message id: %s", json); + } + } + }); }); // Target state is connectted. // done(readyState): // --> readyState: OPEN, CLOSED Remote.method('connect', function (done, timeout) { - var self = this; - - this.url = util.format("ws://%s:%s", this.websocket_ip, this.websocket_port); - this.done = done; - - if (timeout) { - if (this.trace) - console.log("remote: expire: false"); - - this.expire = false; - - setTimeout(function () { - if (this.trace) - console.log("remote: expire: timeout"); - - self.expire = true; - }, timeout); - } - else { - if (this.trace) - console.log("remote: expire: false"); - - this.expire = true; - } - - this.connect_helper(); - + var self = this; + + this.url = util.format("ws://%s:%s", this.websocket_ip, this.websocket_port); + this.done = done; + + if (timeout) { + if (this.trace) console.log("remote: expire: false"); + + this.expire = false; + + setTimeout(function () { + if (this.trace) console.log("remote: expire: timeout"); + self.expire = true; + }, timeout); + } else { + if (this.trace) console.log("remote: expire: false"); + this.expire = true; + } + + this.connect_helper(); }); // Target stated is disconnected. Remote.method('disconnect', function (done) { - var ws = this.ws; - - ws.onclose = function () { - if (this.trace) - console.log("remote: onclose: %s", ws.readyState); - - done(ws.readyState); - }; - - ws.close(); + var ws = this.ws; + + ws.onclose = function () { + if (this.trace) console.log("remote: onclose: %s", ws.readyState); + done(ws.readyState); + }; + + ws.close(); }); // Send a command. The comman should lack the id. // <-> command: what to send, consumed. Remote.method('request', function (request, onDone, onFailure) { this.id += 1; // Advance id. - + var ws = this.ws; - - request.id = this.id; - + + request.id = this.id; + ws.response[request.id] = function (response) { - if (this.trace) - console.log("remote: response: %s", JSON.stringify(response)); - + if (this.trace) console.log("remote: response: %s", JSON.stringify(response)); + if (onFailure && response.error) { onFailure(response); @@ -191,16 +172,14 @@ Remote.method('request', function (request, onDone, onFailure) { onDone(response); } }; - - if (this.trace) - console.log("remote: request: %s", JSON.stringify(request)); - + + if (this.trace) console.log("remote: request: %s", JSON.stringify(request)); + ws.send(JSON.stringify(request)); }); Remote.method('request_ledger_closed', function (onDone, onFailure) { assert(this.trusted); // If not trusted, need to check proof. - this.request({ 'command' : 'ledger_closed' }, onDone, onFailure); }); @@ -211,18 +190,17 @@ Remote.method('request_ledger_current', function (onDone, onFailure) { }); // <-> request: -// --> ledger : optional -// --> ledger_index : optional -// --> type +// --> ledger : optional +// --> ledger_index : optional +// --> type Remote.method('request_ledger_entry', function (req, onDone, onFailure) { assert(this.trusted); // If not trusted, need to check proof, maybe talk packet protocol. - - req.command = 'ledger_entry'; - + + req.command = 'ledger_entry'; + if (req.ledger_closed) { // XXX Initial implementation no caching. - this.request(req, onDone, onFailure); } else if (req.ledger_index) @@ -230,23 +208,23 @@ Remote.method('request_ledger_entry', function (req, onDone, onFailure) { // Current // XXX Only allow with standalone mode. Must sync response with advance. var entry; - + switch (req.type) { case 'account_root': var cache = this.ledgers.current.account_root; - + if (!cache) { cache = this.ledgers.current.account_root = {}; } - - var entry = this.ledgers.current.account_root[req.account]; + + var entry = this.ledgers.current.account_root[req.account]; break; - + default: // This type not cached. } - + if (entry) { onDone(entry); @@ -254,20 +232,20 @@ Remote.method('request_ledger_entry', function (req, onDone, onFailure) { else { // Not cached. - + // Submit request this.request(req, function (r) { - // Got result. - switch (req.type) { - case 'account_root': - this.ledgers.current.account_root.account = r; - break; - - default: - // This type not cached. - } - onDone(r); - }, onFailure); + // Got result. + switch (req.type) { + case 'account_root': + this.ledgers.current.account_root.account = r; + break; + + default: + // This type not cached. + } + onDone(r); + }, onFailure); } } }); @@ -279,13 +257,13 @@ Remote.method('request_ledger_entry', function (req, onDone, onFailure) { Remote.method('submit', function (json, private_key, onDone, onFailure) { var req = {}; - req.command = 'submit'; - req.json = json; + req.command = 'submit'; + req.json = json; if (private_key && !this.trusted) { onFailure({ 'error' : 'untrustedSever', 'request' : req }); - } + } else { this.request(req, onDone, onFailure); @@ -299,22 +277,23 @@ Remote.method('submit', function (json, private_key, onDone, onFailure) { // Subscribe to a server to get the current and closed ledger. // XXX Set up routine to update on notification. Remote.method('server_subscribe', function (onDone, onFailure) { - this.request({ - 'command' : 'server_subscribe' - }, function (r) { + this.request( + { 'command' : 'server_subscribe' }, + function (r) { this.ledger_current_index = r.ledger_current_index; - this.ledger_closed = r.ledger_closed; - this.stand_alone = r.stand_alone; - + this.ledger_closed = r.ledger_closed; + this.stand_alone = r.stand_alone; onDone(); - }, onFailure); + }, + onFailure + ); }); // Refresh accounts[account].seq // done(result); Remote.method('account_seq', function (account, onDone, onFailure) { - var account_root_entry = this.accounts[account]; - + var account_root_entry = this.accounts[account]; + if (account_root_entry && account_root_entry.seq) { onDone(account_root_entry.seq); @@ -322,16 +301,18 @@ Remote.method('account_seq', function (account, onDone, onFailure) { else { // Need to get the ledger entry. - this.request_ledger_entry({ + this.request_ledger_entry( + { 'ledger' : this.ledger_closed, 'account_root' : account - }, function (r) { + }, + function (r) { // Extract the seqence number from the account root entry. this.accounts[account].seq = r.seq; - onDone(r.seq); - - }, onFailure); + }, + onFailure + ); } }); @@ -340,9 +321,9 @@ Remote.method('submit_seq', function (onDone, onFailure) { }); -exports.Remote = Remote; -exports.remoteConfig = remoteConfig; -exports.fees = fees; -exports.accounts = accounts; +exports.Remote = Remote; +exports.remoteConfig = remoteConfig; +exports.fees = fees; +exports.accounts = accounts; // vim:sw=2:sts=2:ts=8 From 50a993e9215020aa85b65499041ce8576a751456 Mon Sep 17 00:00:00 2001 From: MJK Date: Thu, 4 Oct 2012 18:21:05 -0700 Subject: [PATCH 7/7] Ripple tentatively implemented --- src/Pathfinder.cpp | 73 ++++++++++++++++++++++++++++++++--------- src/RPCServer.cpp | 8 ++--- src/RippleLines.cpp | 7 ++++ src/RippleLines.h | 3 +- src/SerializedTypes.cpp | 35 ++++++++++++++++++++ src/SerializedTypes.h | 12 +++++-- 6 files changed, 113 insertions(+), 25 deletions(-) diff --git a/src/Pathfinder.cpp b/src/Pathfinder.cpp index 4f0276a451..9290f921ae 100644 --- a/src/Pathfinder.cpp +++ b/src/Pathfinder.cpp @@ -84,24 +84,65 @@ Pathfinder::Pathfinder(NewcoinAddress& srcAccountID, NewcoinAddress& dstAccountI bool Pathfinder::findPaths(int maxSearchSteps, int maxPay, STPathSet& retPathSet) { - if(mLedger) - { - PathOption::pointer head(new PathOption(mSrcAccountID,mSrcCurrencyID,mDstAmount.getCurrency())); - addOptions(head); + if(mLedger) { + std::queue pqueue; + STPathElement ele(mSrcAccountID, + mSrcCurrencyID, + uint160()); + STPath path; + path.addElement(ele); + pqueue.push(path); + while(pqueue.size()) { - for(int n=0; n tempPaths=mBuildingPaths; - mBuildingPaths.clear(); - BOOST_FOREACH(PathOption::pointer path,tempPaths) - { - addOptions(path); - } - if(checkComplete(retPathSet)) return(true); - } - } + STPath path = pqueue.front(); + pqueue.pop(); + // get the first path from the queue - return(false); + ele = path.mPath.back(); + // get the last node from the path + + if (ele.mAccountID == mDstAccountID) { + path.mPath.erase(path.mPath.begin()); + path.mPath.erase(path.mPath.begin() + path.mPath.size()-1); + retPathSet.addPath(path); + return true; + } + // found the destination + + if (!ele.mCurrencyID) { + BOOST_FOREACH(OrderBook::pointer book,mOrderBook.getXNSInBooks()) + { + //if (!path.hasSeen(line->getAccountIDPeer().getAccountID())) + { + + STPath new_path(path); + STPathElement new_ele(uint160(), book->getCurrencyOut(), book->getIssuerOut()); + new_path.mPath.push_back(new_ele); + pqueue.push(new_path); + } + } + + } else { + RippleLines rippleLines(ele.mAccountID); + BOOST_FOREACH(RippleState::pointer line,rippleLines.getLines()) + { + if (!path.hasSeen(line->getAccountIDPeer().getAccountID())) + { + STPath new_path(path); + STPathElement new_ele(line->getAccountIDPeer().getAccountID(), + ele.mCurrencyID, + uint160()); + + new_path.mPath.push_back(new_ele); + pqueue.push(new_path); + } + } + } + // enumerate all adjacent nodes, construct a new path and push it into the queue + } // While + } // if there is a ledger + + return false; } bool Pathfinder::checkComplete(STPathSet& retPathSet) diff --git a/src/RPCServer.cpp b/src/RPCServer.cpp index 3790691058..4b5de9ef8d 100644 --- a/src/RPCServer.cpp +++ b/src/RPCServer.cpp @@ -1890,20 +1890,16 @@ Json::Value RPCServer::doSend(const Json::Value& params) // XXX Don't allow send to self of same currency. Transaction::pointer trans; - if (asDst) { // Destination exists, ordinary send. - STPathSet spsPaths; - uint160 srcCurrencyID; -// bool ret_b; -// ret_b = false; + STPathSet spsPaths; + uint160 srcCurrencyID; if (!saSrcAmountMax.isNative() || !saDstAmount.isNative()) { STAmount::currencyFromString(srcCurrencyID, sSrcCurrency); Pathfinder pf(naSrcAccountID, naDstAccountID, srcCurrencyID, saDstAmount); -// ret_b = pf.findPaths(5, 1, spsPaths); pf.findPaths(5, 1, spsPaths); } diff --git a/src/RippleLines.cpp b/src/RippleLines.cpp index bae60414b1..e9a8ad25fa 100644 --- a/src/RippleLines.cpp +++ b/src/RippleLines.cpp @@ -8,6 +8,13 @@ RippleLines::RippleLines(const uint160& accountID, Ledger::pointer ledger) fillLines(accountID,ledger); } +void RippleLines::printRippleLines() { + for (int i =0; i < mLines.size(); i++) { + std::cout << i << ": " << mLines[i]->getAccountID().humanAccountID() << std::endl; + } + std::cout << std::endl; +} + RippleLines::RippleLines(const uint160& accountID ) { fillLines(accountID,theApp->getMasterLedger().getCurrentLedger()); diff --git a/src/RippleLines.h b/src/RippleLines.h index 13ea7f5dc4..00373838dd 100644 --- a/src/RippleLines.h +++ b/src/RippleLines.h @@ -16,4 +16,5 @@ public: RippleLines(const uint160& accountID ); // looks in the current ledger std::vector& getLines(){ return(mLines); } -}; \ No newline at end of file + void printRippleLines(); +}; diff --git a/src/SerializedTypes.cpp b/src/SerializedTypes.cpp index 92316d8b96..32fab92f21 100644 --- a/src/SerializedTypes.cpp +++ b/src/SerializedTypes.cpp @@ -10,10 +10,35 @@ #include "Log.h" #include "NewcoinAddress.h" #include "utils.h" +#include "NewcoinAddress.h" STAmount saZero(CURRENCY_ONE, ACCOUNT_ONE, 0); STAmount saOne(CURRENCY_ONE, ACCOUNT_ONE, 1); +void STPathSet::printDebug() { + for (int i = 0; i < value.size(); i++) { + std::cout << i << ": "; + for (int j = 0; j < value[i].mPath.size(); j++) { + //STPathElement pe = value[i].mPath[j]; + NewcoinAddress nad; + nad.setAccountID(value[i].mPath[j].mAccountID); + std::cout << " " << nad.humanAccountID(); + //std::cout << " " << pe.mAccountID.GetHex(); + } + std::cout << std::endl; + } + +} + +void STPath::printDebug() { + std::cout << "STPath:" << std::endl; + for(int i =0; i < mPath.size(); i++) { + NewcoinAddress nad; + nad.setAccountID(mPath[i].mAccountID); + std::cout << " " << i << ": " << nad.humanAccountID() << std::endl; + } +} + std::string SerializedType::getFullText() const { std::string ret; @@ -331,6 +356,16 @@ bool STPathSet::isEquivalent(const SerializedType& t) const return v && (value == v->value); } +bool STPath::hasSeen(const uint160 &acct) { + + for (int i = 0; i < mPath.size();i++) { + STPathElement ele = getElement(i); + if (ele.getAccountID() == acct) + return true; + } + + return false; +} int STPath::getSerializeSize() const { int iBytes = 0; diff --git a/src/SerializedTypes.h b/src/SerializedTypes.h index 0c1cd3bac2..cee687a7fd 100644 --- a/src/SerializedTypes.h +++ b/src/SerializedTypes.h @@ -518,6 +518,9 @@ public: class STPathElement { + friend class STPathSet; + friend class STPath; + friend class Pathfinder; public: enum { typeEnd = 0x00, @@ -567,6 +570,8 @@ public: class STPath { + friend class STPathSet; + friend class Pathfinder; protected: std::vector mPath; @@ -574,12 +579,14 @@ public: STPath() { ; } STPath(const std::vector& p) : mPath(p) { ; } + void printDebug(); int getElementCount() const { return mPath.size(); } bool isEmpty() const { return mPath.empty(); } const STPathElement& getElement(int offset) const { return mPath[offset]; } const STPathElement& getElemet(int offset) { return mPath[offset]; } - void addElement(const STPathElement& e) { mPath.push_back(e); } + void addElement(const STPathElement &e) { mPath.push_back(e); } void clear() { mPath.clear(); } + bool hasSeen(const uint160 &acct); int getSerializeSize() const; // std::string getText() const; Json::Value getJson(int) const; @@ -636,7 +643,6 @@ protected: static STPathSet* construct(SerializerIterator&, SField::ref); public: - STPathSet() { ; } STPathSet(SField::ref n) : SerializedType(n) { ; } STPathSet(const std::vector& v) : value(v) { ; } @@ -658,6 +664,8 @@ public: virtual bool isEquivalent(const SerializedType& t) const; + void printDebug(); + std::vector::iterator begin() { return value.begin(); } std::vector::iterator end() { return value.end(); } std::vector::const_iterator begin() const { return value.begin(); }