From 73e4a73f954d9a270db9ab2d870683550bc29407 Mon Sep 17 00:00:00 2001 From: Arthur Britto Date: Wed, 26 Sep 2012 14:07:07 -0700 Subject: [PATCH 01/10] getLedgerID to NetworkOPs. --- src/NetworkOPs.cpp | 5 +++++ src/NetworkOPs.h | 1 + 2 files changed, 6 insertions(+) diff --git a/src/NetworkOPs.cpp b/src/NetworkOPs.cpp index 0433892263..38a43580db 100644 --- a/src/NetworkOPs.cpp +++ b/src/NetworkOPs.cpp @@ -67,6 +67,11 @@ void NetworkOPs::closeTimeOffset(int offset) Log(lsINFO) << "Close time offset now " << mCloseTimeOffset; } +uint32 NetworkOPs::getLedgerID(const uint256& hash) +{ + return mLedgerMaster->getLedgerByHash(hash)->getLedgerSeq(); +} + uint32 NetworkOPs::getCurrentLedgerID() { return mLedgerMaster->getCurrentLedger()->getLedgerSeq(); diff --git a/src/NetworkOPs.h b/src/NetworkOPs.h index 43b7da9f4e..b62a362bec 100644 --- a/src/NetworkOPs.h +++ b/src/NetworkOPs.h @@ -96,6 +96,7 @@ public: uint32 getValidationTimeNC(); void closeTimeOffset(int); boost::posix_time::ptime getNetworkTimePT(); + uint32 getLedgerID(const uint256& hash); uint32 getCurrentLedgerID(); OperatingMode getOperatingMode() { return mMode; } inline bool available() { From 4cec959e78cf1830eebe547130ef37924a025848 Mon Sep 17 00:00:00 2001 From: Arthur Britto Date: Wed, 26 Sep 2012 14:08:10 -0700 Subject: [PATCH 02/10] WS add command ledger_closed and revise ledger_current. --- src/WSDoor.cpp | 54 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 52 insertions(+), 2 deletions(-) diff --git a/src/WSDoor.cpp b/src/WSDoor.cpp index bea4e7ed27..a44ee9098e 100644 --- a/src/WSDoor.cpp +++ b/src/WSDoor.cpp @@ -76,7 +76,9 @@ public: boost::unordered_set parseAccountIds(const Json::Value& jvArray); // Request-Response Commands + void doLedgerClosed(Json::Value& jvResult, const Json::Value& jvRequest); void doLedgerCurrent(Json::Value& jvResult, const Json::Value& jvRequest); + void doLedgerEntry(Json::Value& jvResult, const Json::Value& jvRequest); // Streaming Commands void doAccountInfoSubscribe(Json::Value& jvResult, const Json::Value& jvRequest); @@ -297,7 +299,9 @@ Json::Value WSConnection::invokeCommand(const Json::Value& jvRequest) doFuncPtr dfpFunc; } commandsA[] = { // Request-Response Commands: - { "ledger_current", &WSConnection::doLedgerCurrent }, + { "ledger_closed", &WSConnection::doLedgerClosed }, + { "ledger_current", &WSConnection::doLedgerCurrent }, + { "ledger_entry", &WSConnection::doLedgerEntry }, // Streaming commands: { "account_info_subscribe", &WSConnection::doAccountInfoSubscribe }, @@ -548,9 +552,55 @@ void WSConnection::doLedgerAccountsUnsubscribe(Json::Value& jvResult, const Json } } +void WSConnection::doLedgerClosed(Json::Value& jvResult, const Json::Value& jvRequest) +{ + uint256 uLedger = theApp->getOPs().getClosedLedger(); + + jvResult["ledger_index"] = theApp->getOPs().getLedgerID(uLedger); + jvResult["ledger"] = uLedger.ToString(); +} + void WSConnection::doLedgerCurrent(Json::Value& jvResult, const Json::Value& jvRequest) { - jvResult["ledger"] = theApp->getOPs().getCurrentLedgerID(); + jvResult["ledger_index"] = theApp->getOPs().getCurrentLedgerID(); +} + +void WSConnection::doLedgerEntry(Json::Value& jvResult, const Json::Value& jvRequest) +{ + // Get from request. + uint256 uLedger; + + jvResult["ledger_index"] = theApp->getOPs().getLedgerID(uLedger); + jvResult["ledger"] = uLedger.ToString(); + + if (jvRequest.isMember("index")) + { + jvResult["error"] = "notImplemented"; + } + else if (jvRequest.isMember("account_root")) + { + jvResult["error"] = "notImplemented"; + } + else if (jvRequest.isMember("directory")) + { + jvResult["error"] = "notImplemented"; + } + else if (jvRequest.isMember("generator")) + { + jvResult["error"] = "notImplemented"; + } + else if (jvRequest.isMember("offer")) + { + jvResult["error"] = "notImplemented"; + } + else if (jvRequest.isMember("ripple_state")) + { + jvResult["error"] = "notImplemented"; + } + else + { + jvResult["error"] = "unknownOption"; + } } void WSConnection::doTransactionSubcribe(Json::Value& jvResult, const Json::Value& jvRequest) From 8993c8f26838f9773f5d68f9f6ed80870b458fb7 Mon Sep 17 00:00:00 2001 From: Arthur Britto Date: Wed, 26 Sep 2012 14:08:56 -0700 Subject: [PATCH 03/10] UT add testing for ledger_closed and update ledger_current. --- js/remote.js | 10 +++++-- test/standalone-test.js | 66 +++++++++++++++++++++++++++++++++++++++-- 2 files changed, 70 insertions(+), 6 deletions(-) diff --git a/js/remote.js b/js/remote.js index d1fa4430cc..c98129d102 100644 --- a/js/remote.js +++ b/js/remote.js @@ -82,7 +82,7 @@ Remote.method('connect_helper', function() { self.done(ws.readyState); }; - // XXX Why doesn't onmessage work? + // 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); @@ -167,12 +167,16 @@ Remote.method('request', function(command, done) { ws.send(JSON.stringify(command)); }); -// Get the current ledger entry (may be live or not). +Remote.method('ledger_closed', function(done) { + this.request({ 'command' : 'ledger_closed' }, done); +}); + +// 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); }); - // Submit a json transaction. // done(value) // <-> value: { 'status', status, 'result' : result, ... } diff --git a/test/standalone-test.js b/test/standalone-test.js index 2a725dffac..92289ffcfc 100644 --- a/test/standalone-test.js +++ b/test/standalone-test.js @@ -92,15 +92,75 @@ buster.testCase("Websocket commands", { }); }, - "ledger_current" : + 'ledger_closed' : + function(done) { + alpha.ledger_closed(function (r) { + console.log(r); + + buster.assert(r.ledger === 1); + done(); + }); + }, + + 'ledger_current' : function(done) { alpha.ledger_current(function (r) { console.log(r); - buster.assert(r.ledger === 2); + buster.assert.equals(r.ledger_index, 2); done(); }); - } + }, + + 'ledger_closed' : + function(done) { + alpha.ledger_closed(function (r) { + console.log("result: %s", JSON.stringify(r)); + + buster.assert.equals(r.ledger_index, 1); + done(); + }); + }, }); +buster.testCase("// Work in progress", { + 'setUp' : + function(done) { + server.start("alpha", + function(e) { + buster.refute(e); + + alpha = remote.remoteConfig(config, "alpha"); + + alpha.connect(function(stat) { + buster.assert(1 == stat); // OPEN + + done(); + }, serverDelay); + }); + }, + + 'tearDown' : + function(done) { + alpha.disconnect(function(stat) { + buster.assert(3 == stat); // CLOSED + + server.stop("alpha", function(e) { + buster.refute(e); + + done(); + }); + }); + }, + + 'ledger_closed' : + function(done) { + alpha.ledger_closed(function (r) { + console.log("result: %s", JSON.stringify(r)); + + buster.assert.equals(r.ledger_index, 1); + done(); + }); + }, +}); // vim:ts=4 From f3f116117a13897a1bb93f8d457884c1a8438ee3 Mon Sep 17 00:00:00 2001 From: Arthur Britto Date: Wed, 26 Sep 2012 15:01:21 -0700 Subject: [PATCH 04/10] Make genesis ledger 1. --- src/Ledger.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ledger.cpp b/src/Ledger.cpp index b419a493fc..e650f9b94f 100644 --- a/src/Ledger.cpp +++ b/src/Ledger.cpp @@ -21,7 +21,7 @@ #include "Log.h" -Ledger::Ledger(const NewcoinAddress& masterID, uint64 startAmount) : mTotCoins(startAmount), mLedgerSeq(0), +Ledger::Ledger(const NewcoinAddress& masterID, uint64 startAmount) : mTotCoins(startAmount), mLedgerSeq(1), mCloseTime(0), mParentCloseTime(0), mCloseResolution(LEDGER_TIME_ACCURACY), mCloseFlags(0), mClosed(false), mValidHash(false), mAccepted(false), mImmutable(false), mTransactionMap(new SHAMap()), mAccountStateMap(new SHAMap()) From be54bf070c06d3c4786e6a9464b98734ee9d508d Mon Sep 17 00:00:00 2001 From: Arthur Britto Date: Wed, 26 Sep 2012 15:02:17 -0700 Subject: [PATCH 05/10] Make getLedgerByHash(0) return the current ledger. --- src/LedgerMaster.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/LedgerMaster.h b/src/LedgerMaster.h index 37db69c5c2..76e6327381 100644 --- a/src/LedgerMaster.h +++ b/src/LedgerMaster.h @@ -66,10 +66,15 @@ public: Ledger::pointer getLedgerByHash(const uint256& hash) { + if (!hash) + return mCurrentLedger; + if (mCurrentLedger && (mCurrentLedger->getHash() == hash)) return mCurrentLedger; + if (mFinalizedLedger && (mFinalizedLedger->getHash() == hash)) return mFinalizedLedger; + return mLedgerHistory.getLedgerByHash(hash); } From cae6ea1c3356d91191614062340bafb61093b334 Mon Sep 17 00:00:00 2001 From: Arthur Britto Date: Wed, 26 Sep 2012 15:03:19 -0700 Subject: [PATCH 06/10] Remove useless NetworkOPs::getClosedLedger. --- src/NetworkOPs.cpp | 4 ++- src/NetworkOPs.h | 5 --- src/RPCServer.cpp | 82 ++++++++++++++++++---------------------------- 3 files changed, 35 insertions(+), 56 deletions(-) diff --git a/src/NetworkOPs.cpp b/src/NetworkOPs.cpp index 38a43580db..9988a03925 100644 --- a/src/NetworkOPs.cpp +++ b/src/NetworkOPs.cpp @@ -69,7 +69,9 @@ void NetworkOPs::closeTimeOffset(int offset) uint32 NetworkOPs::getLedgerID(const uint256& hash) { - return mLedgerMaster->getLedgerByHash(hash)->getLedgerSeq(); + Ledger::ref lrLedger = mLedgerMaster->getLedgerByHash(hash); + + return lrLedger ? lrLedger->getLedgerSeq() : 0; } uint32 NetworkOPs::getCurrentLedgerID() diff --git a/src/NetworkOPs.h b/src/NetworkOPs.h index b62a362bec..c22c6b63cd 100644 --- a/src/NetworkOPs.h +++ b/src/NetworkOPs.h @@ -107,11 +107,6 @@ public: uint256 getClosedLedger() { return mLedgerMaster->getClosedLedger()->getHash(); } - // FIXME: This function is basically useless since the hash is constantly changing and the ledger - // is ephemeral and mutable. - uint256 getCurrentLedger() - { return mLedgerMaster->getCurrentLedger()->getHash(); } - // // Transaction operations // diff --git a/src/RPCServer.cpp b/src/RPCServer.cpp index cd79010c4a..a2d81512ab 100644 --- a/src/RPCServer.cpp +++ b/src/RPCServer.cpp @@ -422,7 +422,6 @@ Json::Value RPCServer::doAccountDomainSet(const Json::Value ¶ms) { NewcoinAddress naSrcAccountID; NewcoinAddress naSeed; - uint256 uLedger = mNetOps->getCurrentLedger(); if (!naSeed.setSeedGeneric(params[0u].asString())) { @@ -438,7 +437,7 @@ Json::Value RPCServer::doAccountDomainSet(const Json::Value ¶ms) NewcoinAddress naAccountPrivate; AccountState::pointer asSrc; STAmount saSrcBalance; - Json::Value obj = authorize(uLedger, naSeed, naSrcAccountID, naAccountPublic, naAccountPrivate, + Json::Value obj = authorize(uint256(0), naSeed, naSrcAccountID, naAccountPublic, naAccountPrivate, saSrcBalance, theConfig.FEE_DEFAULT, asSrc, naVerifyGenerator); if (!obj.empty()) @@ -476,7 +475,6 @@ Json::Value RPCServer::doAccountEmailSet(const Json::Value ¶ms) { NewcoinAddress naSrcAccountID; NewcoinAddress naSeed; - uint256 uLedger = mNetOps->getCurrentLedger(); if (!naSeed.setSeedGeneric(params[0u].asString())) { @@ -492,7 +490,7 @@ Json::Value RPCServer::doAccountEmailSet(const Json::Value ¶ms) NewcoinAddress naAccountPrivate; AccountState::pointer asSrc; STAmount saSrcBalance; - Json::Value obj = authorize(uLedger, naSeed, naSrcAccountID, naAccountPublic, naAccountPrivate, + Json::Value obj = authorize(uint256(0), naSeed, naSrcAccountID, naAccountPublic, naAccountPrivate, saSrcBalance, theConfig.FEE_DEFAULT, asSrc, naVerifyGenerator); if (!obj.empty()) @@ -569,12 +567,11 @@ Json::Value RPCServer::doAccountInfo(const Json::Value ¶ms) ret["accepted"] = jAccepted; - uint256 uCurrent = mNetOps->getCurrentLedger(); - Json::Value jCurrent = accountFromString(uCurrent, naAccount, bIndex, strIdent, iIndex); + Json::Value jCurrent = accountFromString(uint256(0), naAccount, bIndex, strIdent, iIndex); if (jCurrent.empty()) { - AccountState::pointer asCurrent = mNetOps->getAccountState(uCurrent, naAccount); + AccountState::pointer asCurrent = mNetOps->getAccountState(uint256(0), naAccount); if (asCurrent) asCurrent->addJson(jCurrent); @@ -598,7 +595,6 @@ Json::Value RPCServer::doAccountInfo(const Json::Value ¶ms) Json::Value RPCServer::doAccountMessageSet(const Json::Value& params) { NewcoinAddress naSrcAccountID; NewcoinAddress naSeed; - uint256 uLedger = mNetOps->getCurrentLedger(); NewcoinAddress naMessagePubKey; if (!naSeed.setSeedGeneric(params[0u].asString())) @@ -619,7 +615,7 @@ Json::Value RPCServer::doAccountMessageSet(const Json::Value& params) { NewcoinAddress naAccountPrivate; AccountState::pointer asSrc; STAmount saSrcBalance; - Json::Value obj = authorize(uLedger, naSeed, naSrcAccountID, naAccountPublic, naAccountPrivate, + Json::Value obj = authorize(uint256(0), naSeed, naSrcAccountID, naAccountPublic, naAccountPrivate, saSrcBalance, theConfig.FEE_DEFAULT, asSrc, naVerifyGenerator); std::vector vucDomain; @@ -659,7 +655,6 @@ Json::Value RPCServer::doAccountPublishSet(const Json::Value ¶ms) { NewcoinAddress naSrcAccountID; NewcoinAddress naSeed; - uint256 uLedger = mNetOps->getCurrentLedger(); if (!naSeed.setSeedGeneric(params[0u].asString())) { @@ -675,7 +670,7 @@ Json::Value RPCServer::doAccountPublishSet(const Json::Value ¶ms) NewcoinAddress naAccountPrivate; AccountState::pointer asSrc; STAmount saSrcBalance; - Json::Value obj = authorize(uLedger, naSeed, naSrcAccountID, naAccountPublic, naAccountPrivate, + Json::Value obj = authorize(uint256(0), naSeed, naSrcAccountID, naAccountPublic, naAccountPrivate, saSrcBalance, theConfig.FEE_DEFAULT, asSrc, naVerifyGenerator); if (!obj.empty()) @@ -717,7 +712,6 @@ Json::Value RPCServer::doAccountRateSet(const Json::Value ¶ms) { NewcoinAddress naSrcAccountID; NewcoinAddress naSeed; - uint256 uLedger = mNetOps->getCurrentLedger(); if (!naSeed.setSeedGeneric(params[0u].asString())) { @@ -733,7 +727,7 @@ Json::Value RPCServer::doAccountRateSet(const Json::Value ¶ms) NewcoinAddress naAccountPrivate; AccountState::pointer asSrc; STAmount saSrcBalance; - Json::Value obj = authorize(uLedger, naSeed, naSrcAccountID, naAccountPublic, naAccountPrivate, + Json::Value obj = authorize(uint256(0), naSeed, naSrcAccountID, naAccountPublic, naAccountPrivate, saSrcBalance, theConfig.FEE_DEFAULT, asSrc, naVerifyGenerator); if (!obj.empty()) @@ -773,7 +767,6 @@ Json::Value RPCServer::doAccountRateSet(const Json::Value ¶ms) Json::Value RPCServer::doAccountWalletSet(const Json::Value& params) { NewcoinAddress naSrcAccountID; NewcoinAddress naSeed; - uint256 uLedger = mNetOps->getCurrentLedger(); if (!naSeed.setSeedGeneric(params[0u].asString())) { @@ -789,7 +782,7 @@ Json::Value RPCServer::doAccountWalletSet(const Json::Value& params) { NewcoinAddress naAccountPrivate; AccountState::pointer asSrc; STAmount saSrcBalance; - Json::Value obj = authorize(uLedger, naSeed, naSrcAccountID, naAccountPublic, naAccountPrivate, + Json::Value obj = authorize(uint256(0), naSeed, naSrcAccountID, naAccountPublic, naAccountPrivate, saSrcBalance, theConfig.FEE_DEFAULT, asSrc, naMasterGenerator); std::vector vucDomain; @@ -921,8 +914,6 @@ Json::Value RPCServer::doDataStore(const Json::Value& params) // Note: Nicknames are not automatically looked up by commands as they are advisory and can be changed. Json::Value RPCServer::doNicknameInfo(const Json::Value& params) { - uint256 uLedger = mNetOps->getCurrentLedger(); - std::string strNickname = params[0u].asString(); boost::trim(strNickname); @@ -931,7 +922,7 @@ Json::Value RPCServer::doNicknameInfo(const Json::Value& params) return RPCError(rpcNICKNAME_MALFORMED); } - NicknameState::pointer nsSrc = mNetOps->getNicknameState(uLedger, strNickname); + NicknameState::pointer nsSrc = mNetOps->getNicknameState(uint256(0), strNickname); if (!nsSrc) { return RPCError(rpcNICKNAME_MISSING); @@ -951,7 +942,6 @@ Json::Value RPCServer::doNicknameSet(const Json::Value& params) { NewcoinAddress naSrcAccountID; NewcoinAddress naSeed; - uint256 uLedger = mNetOps->getCurrentLedger(); if (!naSeed.setSeedGeneric(params[0u].asString())) { @@ -979,7 +969,7 @@ Json::Value RPCServer::doNicknameSet(const Json::Value& params) } STAmount saFee; - NicknameState::pointer nsSrc = mNetOps->getNicknameState(uLedger, strNickname); + NicknameState::pointer nsSrc = mNetOps->getNicknameState(uint256(0), strNickname); if (!nsSrc) { @@ -1002,7 +992,7 @@ Json::Value RPCServer::doNicknameSet(const Json::Value& params) NewcoinAddress naAccountPrivate; AccountState::pointer asSrc; STAmount saSrcBalance; - Json::Value obj = authorize(uLedger, naSeed, naSrcAccountID, naAccountPublic, naAccountPrivate, + Json::Value obj = authorize(uint256(0), naSeed, naSrcAccountID, naAccountPublic, naAccountPrivate, saSrcBalance, saFee, asSrc, naMasterGenerator); if (!obj.empty()) @@ -1068,7 +1058,7 @@ Json::Value RPCServer::doOfferCreate(const Json::Value ¶ms) NewcoinAddress naAccountPrivate; AccountState::pointer asSrc; STAmount saSrcBalance; - Json::Value obj = authorize(mNetOps->getCurrentLedger(), naSeed, naSrcAccountID, naAccountPublic, naAccountPrivate, + Json::Value obj = authorize(uint256(0), naSeed, naSrcAccountID, naAccountPublic, naAccountPrivate, saSrcBalance, theConfig.FEE_DEFAULT, asSrc, naMasterGenerator); if (!obj.empty()) @@ -1114,7 +1104,7 @@ Json::Value RPCServer::doOfferCancel(const Json::Value ¶ms) NewcoinAddress naAccountPrivate; AccountState::pointer asSrc; STAmount saSrcBalance; - Json::Value obj = authorize(mNetOps->getCurrentLedger(), naSeed, naSrcAccountID, naAccountPublic, naAccountPrivate, + Json::Value obj = authorize(uint256(0), naSeed, naSrcAccountID, naAccountPublic, naAccountPrivate, saSrcBalance, theConfig.FEE_DEFAULT, asSrc, naMasterGenerator); if (!obj.empty()) @@ -1154,10 +1144,9 @@ Json::Value RPCServer::doOwnerInfo(const Json::Value& params) ret["accepted"] = jAccepted.empty() ? mNetOps->getOwnerInfo(uAccepted, naAccount) : jAccepted; - uint256 uCurrent = mNetOps->getCurrentLedger(); - Json::Value jCurrent = accountFromString(uCurrent, naAccount, bIndex, strIdent, iIndex); + Json::Value jCurrent = accountFromString(uint256(0), naAccount, bIndex, strIdent, iIndex); - ret["current"] = jCurrent.empty() ? mNetOps->getOwnerInfo(uCurrent, naAccount) : jCurrent; + ret["current"] = jCurrent.empty() ? mNetOps->getOwnerInfo(uint256(0), naAccount) : jCurrent; return ret; } @@ -1168,7 +1157,6 @@ Json::Value RPCServer::doPasswordFund(const Json::Value ¶ms) NewcoinAddress naSrcAccountID; NewcoinAddress naDstAccountID; NewcoinAddress naSeed; - uint256 uLedger = mNetOps->getCurrentLedger(); if (!naSeed.setSeedGeneric(params[0u].asString())) { @@ -1188,7 +1176,7 @@ Json::Value RPCServer::doPasswordFund(const Json::Value ¶ms) NewcoinAddress naAccountPrivate; AccountState::pointer asSrc; STAmount saSrcBalance; - Json::Value obj = authorize(uLedger, naSeed, naSrcAccountID, naAccountPublic, naAccountPrivate, + Json::Value obj = authorize(uint256(0), naSeed, naSrcAccountID, naAccountPublic, naAccountPrivate, saSrcBalance, theConfig.FEE_DEFAULT, asSrc, naMasterGenerator); if (!obj.empty()) @@ -1494,8 +1482,7 @@ Json::Value RPCServer::doRipple(const Json::Value ¶ms) return RPCError(rpcDST_AMT_MALFORMED); } - uint256 uLedger = mNetOps->getCurrentLedger(); - AccountState::pointer asDst = mNetOps->getAccountState(uLedger, naDstAccountID); + AccountState::pointer asDst = mNetOps->getAccountState(uint256(0), naDstAccountID); STAmount saFee = theConfig.FEE_DEFAULT; NewcoinAddress naVerifyGenerator; @@ -1503,7 +1490,7 @@ Json::Value RPCServer::doRipple(const Json::Value ¶ms) NewcoinAddress naAccountPrivate; AccountState::pointer asSrc; STAmount saSrcBalance; - Json::Value obj = authorize(uLedger, naSeed, naSrcAccountID, naAccountPublic, naAccountPrivate, + Json::Value obj = authorize(uint256(0), naSeed, naSrcAccountID, naAccountPublic, naAccountPrivate, saSrcBalance, saFee, asSrc, naVerifyGenerator); if (!obj.empty()) @@ -1556,7 +1543,6 @@ Json::Value RPCServer::doRippleLineSet(const Json::Value& params) NewcoinAddress naSrcAccountID; NewcoinAddress naDstAccountID; STAmount saLimitAmount; - uint256 uLedger = mNetOps->getCurrentLedger(); bool bLimitAmount = true; bool bQualityIn = params.size() >= 6; bool bQualityOut = params.size() >= 7; @@ -1594,7 +1580,7 @@ Json::Value RPCServer::doRippleLineSet(const Json::Value& params) NewcoinAddress naAccountPrivate; AccountState::pointer asSrc; STAmount saSrcBalance; - Json::Value obj = authorize(uLedger, naSeed, naSrcAccountID, naAccountPublic, naAccountPrivate, + Json::Value obj = authorize(uint256(0), naSeed, naSrcAccountID, naAccountPublic, naAccountPrivate, saSrcBalance, theConfig.FEE_DEFAULT, asSrc, naMasterGenerator); if (!obj.empty()) @@ -1627,7 +1613,6 @@ Json::Value RPCServer::doRippleLineSet(const Json::Value& params) Json::Value RPCServer::doRippleLinesGet(const Json::Value ¶ms) { // uint256 uAccepted = mNetOps->getClosedLedger(); - uint256 uCurrent = mNetOps->getCurrentLedger(); std::string strIdent = params[0u].asString(); bool bIndex; @@ -1637,7 +1622,7 @@ Json::Value RPCServer::doRippleLinesGet(const Json::Value ¶ms) Json::Value ret; - ret = accountFromString(uCurrent, naAccount, bIndex, strIdent, iIndex); + ret = accountFromString(uint256(0), naAccount, bIndex, strIdent, iIndex); if (!ret.empty()) return ret; @@ -1649,7 +1634,7 @@ Json::Value RPCServer::doRippleLinesGet(const Json::Value ¶ms) if (bIndex) ret["index"] = iIndex; - AccountState::pointer as = mNetOps->getAccountState(uCurrent, naAccount); + AccountState::pointer as = mNetOps->getAccountState(uint256(0), naAccount); if (as) { Json::Value jsonLines(Json::arrayValue); @@ -1739,8 +1724,7 @@ Json::Value RPCServer::doSend(const Json::Value& params) } else { - uint256 uLedger = mNetOps->getCurrentLedger(); - AccountState::pointer asDst = mNetOps->getAccountState(uLedger, naDstAccountID); + AccountState::pointer asDst = mNetOps->getAccountState(uint256(0), naDstAccountID); bool bCreate = !asDst; STAmount saFee = bCreate ? theConfig.FEE_ACCOUNT_CREATE : theConfig.FEE_DEFAULT; @@ -1749,7 +1733,7 @@ Json::Value RPCServer::doSend(const Json::Value& params) NewcoinAddress naAccountPrivate; AccountState::pointer asSrc; STAmount saSrcBalance; - Json::Value obj = authorize(uLedger, naSeed, naSrcAccountID, naAccountPublic, naAccountPrivate, + Json::Value obj = authorize(uint256(0), naSeed, naSrcAccountID, naAccountPublic, naAccountPrivate, saSrcBalance, saFee, asSrc, naVerifyGenerator); // Log(lsINFO) << boost::str(boost::format("doSend: sSrcIssuer=%s sDstIssuer=%s saSrcAmountMax=%s saDstAmount=%s") @@ -2081,7 +2065,6 @@ Json::Value RPCServer::accounts(const uint256& uLedger, const NewcoinAddress& na Json::Value RPCServer::doWalletAccounts(const Json::Value& params) { NewcoinAddress naSeed; - uint256 uLedger = mNetOps->getCurrentLedger(); if (!naSeed.setSeedGeneric(params[0u].asString())) { @@ -2091,17 +2074,17 @@ Json::Value RPCServer::doWalletAccounts(const Json::Value& params) // Try the seed as a master seed. NewcoinAddress naMasterGenerator = NewcoinAddress::createGeneratorPublic(naSeed); - Json::Value jsonAccounts = accounts(uLedger, naMasterGenerator); + Json::Value jsonAccounts = accounts(uint256(0), naMasterGenerator); if (jsonAccounts.empty()) { // No account via seed as master, try seed a regular. - Json::Value ret = getMasterGenerator(uLedger, naSeed, naMasterGenerator); + Json::Value ret = getMasterGenerator(uint256(0), naSeed, naMasterGenerator); if (!ret.empty()) return ret; - ret["accounts"] = accounts(uLedger, naMasterGenerator); + ret["accounts"] = accounts(uint256(0), naMasterGenerator); return ret; } @@ -2124,7 +2107,6 @@ Json::Value RPCServer::doWalletAdd(const Json::Value& params) NewcoinAddress naSrcAccountID; STAmount saAmount; std::string sDstCurrency; - uint256 uLedger = mNetOps->getCurrentLedger(); if (!naRegularSeed.setSeedGeneric(params[0u].asString())) { @@ -2151,7 +2133,7 @@ Json::Value RPCServer::doWalletAdd(const Json::Value& params) NewcoinAddress naAccountPrivate; AccountState::pointer asSrc; STAmount saSrcBalance; - Json::Value obj = authorize(uLedger, naRegularSeed, naSrcAccountID, naAccountPublic, naAccountPrivate, + Json::Value obj = authorize(uint256(0), naRegularSeed, naSrcAccountID, naAccountPublic, naAccountPrivate, saSrcBalance, theConfig.FEE_ACCOUNT_CREATE, asSrc, naMasterGenerator); if (!obj.empty()) @@ -2177,7 +2159,7 @@ Json::Value RPCServer::doWalletAdd(const Json::Value& params) ++iIndex; naNewAccountPublic.setAccountPublic(naMasterGenerator, iIndex); - asNew = mNetOps->getAccountState(uLedger, naNewAccountPublic); + asNew = mNetOps->getAccountState(uint256(0), naNewAccountPublic); if (!asNew) bAgain = false; } while (bAgain); @@ -2312,7 +2294,6 @@ Json::Value RPCServer::doWalletCreate(const Json::Value& params) NewcoinAddress naSrcAccountID; NewcoinAddress naDstAccountID; NewcoinAddress naSeed; - uint256 uLedger = mNetOps->getCurrentLedger(); if (!naSeed.setSeedGeneric(params[0u].asString())) { @@ -2326,7 +2307,7 @@ Json::Value RPCServer::doWalletCreate(const Json::Value& params) { return RPCError(rpcDST_ACT_MALFORMED); } - else if (mNetOps->getAccountState(uLedger, naDstAccountID)) + else if (mNetOps->getAccountState(uint256(0), naDstAccountID)) { return RPCError(rpcACT_EXISTS); } @@ -2339,7 +2320,7 @@ Json::Value RPCServer::doWalletCreate(const Json::Value& params) NewcoinAddress naAccountPrivate; AccountState::pointer asSrc; STAmount saSrcBalance; - Json::Value obj = authorize(uLedger, naSeed, naSrcAccountID, naAccountPublic, naAccountPrivate, + Json::Value obj = authorize(uint256(0), naSeed, naSrcAccountID, naAccountPublic, naAccountPrivate, saSrcBalance, theConfig.FEE_ACCOUNT_CREATE, asSrc, naMasterGenerator); if (!obj.empty()) @@ -2602,7 +2583,8 @@ Json::Value RPCServer::doCommand(const std::string& command, Json::Value& params { return RPCError(rpcNO_NETWORK); } - else if ((commandsA[i].iOptions & optCurrent) && mNetOps->getCurrentLedger().isZero()) + // XXX Should verify we have a current ledger. + else if ((commandsA[i].iOptions & optCurrent) && false) { return RPCError(rpcNO_CURRENT); } From 20815377b47b3b140575da3712751d9afad261a7 Mon Sep 17 00:00:00 2001 From: Arthur Britto Date: Wed, 26 Sep 2012 15:07:03 -0700 Subject: [PATCH 07/10] Adjust UTs for genesis 1. --- test/standalone-test.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/standalone-test.js b/test/standalone-test.js index 92289ffcfc..ffa593840d 100644 --- a/test/standalone-test.js +++ b/test/standalone-test.js @@ -107,7 +107,7 @@ buster.testCase("Websocket commands", { alpha.ledger_current(function (r) { console.log(r); - buster.assert.equals(r.ledger_index, 2); + buster.assert.equals(r.ledger_index, 3); done(); }); }, @@ -117,7 +117,7 @@ buster.testCase("Websocket commands", { alpha.ledger_closed(function (r) { console.log("result: %s", JSON.stringify(r)); - buster.assert.equals(r.ledger_index, 1); + buster.assert.equals(r.ledger_index, 2); done(); }); }, @@ -158,7 +158,7 @@ buster.testCase("// Work in progress", { alpha.ledger_closed(function (r) { console.log("result: %s", JSON.stringify(r)); - buster.assert.equals(r.ledger_index, 1); + buster.assert.equals(r.ledger_index, 2); done(); }); }, From b491b9925521d8577ec5b8d5d40baf02a2295a4d Mon Sep 17 00:00:00 2001 From: Arthur Britto Date: Thu, 27 Sep 2012 13:08:59 -0700 Subject: [PATCH 08/10] Rework NetworkOPs to return Ledger:pointer. --- src/NetworkOPs.h | 6 ++++++ src/NewcoinAddress.h | 3 +++ 2 files changed, 9 insertions(+) diff --git a/src/NetworkOPs.h b/src/NetworkOPs.h index c22c6b63cd..cc84f9f89a 100644 --- a/src/NetworkOPs.h +++ b/src/NetworkOPs.h @@ -104,9 +104,15 @@ public: return mMode >= omTRACKING; } + Ledger::pointer getCurrentLedger() { return mLedgerMaster->getCurrentLedger(); } + Ledger::pointer getLedgerByHash(const uint256& hash) { return mLedgerMaster->getLedgerByHash(hash); } + Ledger::pointer getLedgerBySeq(const uint32 seq) { return mLedgerMaster->getLedgerBySeq(seq); } + uint256 getClosedLedger() { return mLedgerMaster->getClosedLedger()->getHash(); } + SLE::pointer getSLE(Ledger::pointer lpLedger, const uint256& uHash) { return lpLedger->getSLE(uHash); } + // // Transaction operations // diff --git a/src/NewcoinAddress.h b/src/NewcoinAddress.h index 369b609d04..707a976c52 100644 --- a/src/NewcoinAddress.h +++ b/src/NewcoinAddress.h @@ -73,6 +73,9 @@ public: bool setAccountID(const std::string& strAccountID); void setAccountID(const uint160& hash160In); + static NewcoinAddress createAccountID(const std::string& strAccountID) + { NewcoinAddress na; na.setAccountID(strAccountID); return na; } + static NewcoinAddress createAccountID(const uint160& uiAccountID); static std::string createHumanAccountID(const uint160& uiAccountID) From ff245609ac4ead2b7b329d7306fed9c9551d548c Mon Sep 17 00:00:00 2001 From: Arthur Britto Date: Thu, 27 Sep 2012 13:09:57 -0700 Subject: [PATCH 09/10] WS: Add support for ledger_entry to return an account_root. --- js/remote.js | 23 ++++++----- src/WSDoor.cpp | 66 ++++++++++++++++++++++++++++--- test/standalone-test.js | 88 +++++++++++++++++++++-------------------- 3 files changed, 119 insertions(+), 58 deletions(-) diff --git a/js/remote.js b/js/remote.js index c98129d102..ffab43eaad 100644 --- a/js/remote.js +++ b/js/remote.js @@ -168,6 +168,8 @@ Remote.method('request', function(command, done) { }); Remote.method('ledger_closed', function(done) { + assert(this.trusted); // If not trusted, need to check proof. + this.request({ 'command' : 'ledger_closed' }, done); }); @@ -177,6 +179,17 @@ Remote.method('ledger_current', function(done) { this.request({ 'command' : 'ledger_current' }, done); }); +// <-> 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. + + params.command = 'ledger_entry'; + + this.request(params, done); +}); + // Submit a json transaction. // done(value) // <-> value: { 'status', status, 'result' : result, ... } @@ -186,16 +199,6 @@ Remote.method('submit', function(json, done) { // }); }); -// done(value) -// --> value: { 'status', status, 'result' : result, ... } -// done may be called up to 3 times. -Remote.method('account_root', function(account_id, done) { - this.request({ - 'command' : 'ledger_current', - }, function() { - }); -}); - exports.Remote = Remote; exports.remoteConfig = remoteConfig; diff --git a/src/WSDoor.cpp b/src/WSDoor.cpp index a44ee9098e..ae63b02129 100644 --- a/src/WSDoor.cpp +++ b/src/WSDoor.cpp @@ -567,11 +567,46 @@ void WSConnection::doLedgerCurrent(Json::Value& jvResult, const Json::Value& jvR void WSConnection::doLedgerEntry(Json::Value& jvResult, const Json::Value& jvRequest) { - // Get from request. - uint256 uLedger; + NetworkOPs& noNetwork = theApp->getOPs(); + uint256 uLedger = jvRequest.isMember("ledger") ? uint256(jvRequest["ledger"].asString()) : 0; + uint32 uLedgerIndex = jvRequest.isMember("ledger_index") && jvRequest["ledger_index"].isNumeric() ? jvRequest["ledger_index"].asUInt() : 0; - jvResult["ledger_index"] = theApp->getOPs().getLedgerID(uLedger); - jvResult["ledger"] = uLedger.ToString(); + Ledger::pointer lpLedger; + + if (!!uLedger) + { + // Ledger directly specified. + lpLedger = noNetwork.getLedgerByHash(uLedger); + + if (!lpLedger) + { + jvResult["error"] = "ledgerNotFound"; + return; + } + + uLedgerIndex = lpLedger->getLedgerSeq(); // Set the current index, override if needed. + } + else if (!!uLedgerIndex) + { + lpLedger = noNetwork.getLedgerBySeq(uLedgerIndex); + + if (!lpLedger) + { + jvResult["error"] = "ledgerNotFound"; // ledger_index from future? + return; + } + } + else + { + // Default to current ledger. + lpLedger = noNetwork.getCurrentLedger(); + uLedgerIndex = lpLedger->getLedgerSeq(); // Set the current index. + } + + if (!!uLedger) + jvResult["ledger"] = uLedger.ToString(); + + jvResult["ledger_index"] = uLedgerIndex; if (jvRequest.isMember("index")) { @@ -579,7 +614,28 @@ void WSConnection::doLedgerEntry(Json::Value& jvResult, const Json::Value& jvReq } else if (jvRequest.isMember("account_root")) { - jvResult["error"] = "notImplemented"; + NewcoinAddress naAccount = NewcoinAddress::createAccountID(jvRequest["account_root"].asString()); + + if (!naAccount.isValid()) + { + jvResult["error"] = "malformedAddress"; + return; + } + + uint256 accountRootIndex = Ledger::getAccountRootIndex(naAccount.getAccountID()); + + SLE::pointer sleNode = noNetwork.getSLE(lpLedger, accountRootIndex); + + if (!sleNode) + { + // Not found. + // XXX We should also provide proof. + jvResult["error"] = "entryNotFound"; + } + else + { + jvResult["node"] = sleNode->getJson(0); + } } else if (jvRequest.isMember("directory")) { diff --git a/test/standalone-test.js b/test/standalone-test.js index ffa593840d..a3fb947498 100644 --- a/test/standalone-test.js +++ b/test/standalone-test.js @@ -1,5 +1,3 @@ -// console.log("standalone-test.js>"); - var fs = require("fs"); var buster = require("buster"); @@ -59,9 +57,6 @@ buster.testCase("WebSocket connection", { }, }); -// XXX Figure out a way to stuff this into the test case. -var alpha; - buster.testCase("Websocket commands", { 'setUp' : function(done) { @@ -92,16 +87,6 @@ buster.testCase("Websocket commands", { }); }, - 'ledger_closed' : - function(done) { - alpha.ledger_closed(function (r) { - console.log(r); - - buster.assert(r.ledger === 1); - done(); - }); - }, - 'ledger_current' : function(done) { alpha.ledger_current(function (r) { @@ -112,7 +97,7 @@ buster.testCase("Websocket commands", { }); }, - 'ledger_closed' : + '// ledger_closed' : function(done) { alpha.ledger_closed(function (r) { console.log("result: %s", JSON.stringify(r)); @@ -121,46 +106,63 @@ buster.testCase("Websocket commands", { done(); }); }, -}); -buster.testCase("// Work in progress", { - 'setUp' : + 'account_root success' : function(done) { - server.start("alpha", - function(e) { - buster.refute(e); + alpha.ledger_closed(function (r) { + // console.log("result: %s", JSON.stringify(r)); - alpha = remote.remoteConfig(config, "alpha"); + buster.refute('error' in r); - alpha.connect(function(stat) { - buster.assert(1 == stat); // OPEN + alpha.ledger_entry({ + 'ledger_index' : r.ledger_index, + 'account_root' : 'iHb9CJAWyB4ij91VRWn96DkukG4bwdtyTh' + } , function (r) { + // console.log("account_root: %s", JSON.stringify(r)); + buster.assert('node' in r); done(); - }, serverDelay); - }); - }, - - 'tearDown' : - function(done) { - alpha.disconnect(function(stat) { - buster.assert(3 == stat); // CLOSED - - server.stop("alpha", function(e) { - buster.refute(e); - - done(); - }); + }); }); }, - 'ledger_closed' : + 'account_root malformedAddress' : function(done) { alpha.ledger_closed(function (r) { - console.log("result: %s", JSON.stringify(r)); + // console.log("result: %s", JSON.stringify(r)); - buster.assert.equals(r.ledger_index, 2); - done(); + buster.refute('error' in r); + + alpha.ledger_entry({ + 'ledger_index' : r.ledger_index, + 'account_root' : 'foobar' + } , function (r) { + // console.log("account_root: %s", JSON.stringify(r)); + + buster.assert.equals(r.error, 'malformedAddress'); + done(); + }); + }); + }, + + 'account_root entryNotFound' : + 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, + 'account_root' : 'iG1QQv2nh2gi7RCZ1P8YYcBUKCCN633jCn' + } , function (r) { + // console.log("account_root: %s", JSON.stringify(r)); + + buster.assert.equals(r.error, 'entryNotFound'); + done(); + }); }); }, }); + // vim:ts=4 From 22c22bd734e0dd04da84a46a34065c8d8be49779 Mon Sep 17 00:00:00 2001 From: Arthur Britto Date: Thu, 27 Sep 2012 13:36:04 -0700 Subject: [PATCH 10/10] WS: Add support ledger_entry to return a ripple_state. --- src/Amount.cpp | 1 + src/WSDoor.cpp | 58 ++++++++++++++++++++++++++++++++++++-------------- 2 files changed, 43 insertions(+), 16 deletions(-) diff --git a/src/Amount.cpp b/src/Amount.cpp index f0692f2af7..637d4ef52d 100644 --- a/src/Amount.cpp +++ b/src/Amount.cpp @@ -12,6 +12,7 @@ uint64 STAmount::uRateOne = STAmount::getRate(STAmount(1), STAmount(1)); +// --> sCurrency: "", "XNS", or three letter ISO code. bool STAmount::currencyFromString(uint160& uDstCurrency, const std::string& sCurrency) { bool bSuccess = true; diff --git a/src/WSDoor.cpp b/src/WSDoor.cpp index ae63b02129..7e6960b831 100644 --- a/src/WSDoor.cpp +++ b/src/WSDoor.cpp @@ -608,33 +608,23 @@ void WSConnection::doLedgerEntry(Json::Value& jvResult, const Json::Value& jvReq jvResult["ledger_index"] = uLedgerIndex; + uint256 uNodeIndex; + if (jvRequest.isMember("index")) { jvResult["error"] = "notImplemented"; } else if (jvRequest.isMember("account_root")) { - NewcoinAddress naAccount = NewcoinAddress::createAccountID(jvRequest["account_root"].asString()); + NewcoinAddress naAccount; - if (!naAccount.isValid()) + if (!naAccount.setAccountID(jvRequest["account_root"].asString())) { jvResult["error"] = "malformedAddress"; - return; - } - - uint256 accountRootIndex = Ledger::getAccountRootIndex(naAccount.getAccountID()); - - SLE::pointer sleNode = noNetwork.getSLE(lpLedger, accountRootIndex); - - if (!sleNode) - { - // Not found. - // XXX We should also provide proof. - jvResult["error"] = "entryNotFound"; } else { - jvResult["node"] = sleNode->getJson(0); + uNodeIndex = Ledger::getAccountRootIndex(naAccount.getAccountID()); } } else if (jvRequest.isMember("directory")) @@ -651,12 +641,48 @@ void WSConnection::doLedgerEntry(Json::Value& jvResult, const Json::Value& jvReq } else if (jvRequest.isMember("ripple_state")) { - jvResult["error"] = "notImplemented"; + NewcoinAddress naA; + NewcoinAddress naB; + uint160 uCurrency; + + if (!jvRequest.isMember("accounts") + || !jvRequest.isMember("currency") + || !jvRequest["accounts"].isArray() + || 2 != jvRequest["accounts"].size()) { + jvResult["error"] = "malformedRequest"; + } + else if (!naA.setAccountID(jvRequest["accounts"][0u].asString()) + || !naB.setAccountID(jvRequest["accounts"][1u].asString())) { + jvResult["error"] = "malformedAddress"; + } + else if (!STAmount::currencyFromString(uCurrency, jvRequest["currency"].asString())) { + jvResult["error"] = "malformedCurrency"; + } + else + { + uNodeIndex = Ledger::getRippleStateIndex(naA, naB, uCurrency); + } } else { jvResult["error"] = "unknownOption"; } + + if (!!uNodeIndex) + { + SLE::pointer sleNode = noNetwork.getSLE(lpLedger, uNodeIndex); + + if (!sleNode) + { + // Not found. + // XXX We should also provide proof. + jvResult["error"] = "entryNotFound"; + } + else + { + jvResult["node"] = sleNode->getJson(0); + } + } } void WSConnection::doTransactionSubcribe(Json::Value& jvResult, const Json::Value& jvRequest)