diff --git a/js/remote.js b/js/remote.js new file mode 100644 index 000000000..ffab43eaa --- /dev/null +++ b/js/remote.js @@ -0,0 +1,205 @@ +// Remote access to a server. +// - We never send binary data. +// - We use the W3C interface for node and browser compatibility: +// http://www.w3.org/TR/websockets/#the-websocket-interface +// +// YYY Will later provide a network access which use multiple instances of this. +// YYY A better model might be to allow requesting a target state: keep connected or not. +// + +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 remoteConfig = function(config, server, trace) { + var serverConfig = config.servers[server]; + + return new Remote(serverConfig.trusted, serverConfig.websocket_ip, serverConfig.websocket_port, trace); +}; + +Remote.method('connect_helper', function() { + 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); + }; + + 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() { + 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(); + +}); + +// 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(); +}); + +// 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. + + var ws = this.ws; + + command.id = this.id; + + ws.response[command.id] = done; + + if (this.trace) + console.log("remote: send: %s", JSON.stringify(command)); + + ws.send(JSON.stringify(command)); +}); + +Remote.method('ledger_closed', function(done) { + assert(this.trusted); // If not trusted, need to check proof. + + 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); +}); + +// <-> 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, ... } +// done may be called up to 3 times. +Remote.method('submit', function(json, done) { +// this.request(..., function() { +// }); +}); + +exports.Remote = Remote; +exports.remoteConfig = remoteConfig; + +// vim:ts=4 diff --git a/js/serializer.js b/js/serializer.js new file mode 100644 index 000000000..00f9e070b --- /dev/null +++ b/js/serializer.js @@ -0,0 +1,44 @@ +// + +var serializer = {}; + +serializer.addUInt16 = function(value) { + switch (typeof value) { + case 'string': + addUInt16(value.charCodeAt(0)); + break; + + case 'integer': + for (i = 16/8; i; i -=1) { + raw.push(value & 255); + value >>= 8; + } + break; + + default: + throw 'UNEXPECTED_TYPE'; + } +}; + +serializer.addUInt160 = function(value) { + switch (typeof value) { + case 'array': + raw.concat(value); + break; + + case 'integer': + for (i = 160/8; i; i -=1) { + raw.push(value & 255); + value >>= 8; + } + break; + + default: + throw 'UNEXPECTED_TYPE'; + } +}; + +serializer.getSHA512Half = function() { +}; + +// vim:ts=4 diff --git a/newcoind.cfg b/newcoind.cfg index ac87d7aa8..689b27692 100644 --- a/newcoind.cfg +++ b/newcoind.cfg @@ -119,7 +119,7 @@ 1 [debug_logfile] -debug.log +log/debug.log [sntp_servers] time.windows.com diff --git a/src/Amount.cpp b/src/Amount.cpp index f0692f2af..637d4ef52 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/Application.cpp b/src/Application.cpp index 00aea956a..2011ca8e7 100644 --- a/src/Application.cpp +++ b/src/Application.cpp @@ -73,7 +73,8 @@ void Application::run() boost::thread auxThread(boost::bind(&boost::asio::io_service::run, &mAuxService)); auxThread.detach(); - mSNTPClient.init(theConfig.SNTP_SERVERS); + if (!theConfig.RUN_STANDALONE) + mSNTPClient.init(theConfig.SNTP_SERVERS); // // Construct databases. diff --git a/src/Conversion.cpp b/src/Conversion.cpp deleted file mode 100644 index 7f9de9029..000000000 --- a/src/Conversion.cpp +++ /dev/null @@ -1,50 +0,0 @@ -#include "Conversion.h" -#include "base58.h" -using namespace std; - -#if 0 - -uint160 protobufTo160(const std::string& buf) -{ - uint160 ret; - // TODO: - return(ret); -} - -uint256 protobufTo256(const std::string& hash) -{ - uint256 ret; - // TODO: - return(ret); -} - -uint160 humanTo160(const std::string& buf) -{ - vector retVec; - DecodeBase58(buf,retVec); - uint160 ret; - memcpy(ret.begin(), &retVec[0], ret.GetSerializeSize()); - - - return(ret); -} - -bool humanToPK(const std::string& buf,std::vector& retVec) -{ - return(DecodeBase58(buf,retVec)); -} - -bool u160ToHuman(uint160& buf, std::string& retStr) -{ - retStr=EncodeBase58(buf.begin(),buf.end()); - return(true); -} - -#endif - -base_uint256 uint160::to256() const -{ - uint256 m; - memcpy(m.begin(), begin(), size()); - return m; -} diff --git a/src/Conversion.h b/src/Conversion.h deleted file mode 100644 index c2ceb5339..000000000 --- a/src/Conversion.h +++ /dev/null @@ -1,11 +0,0 @@ -#include "uint256.h" -#include - -extern uint160 protobufTo160(const std::string& buf); -extern uint256 protobufTo256(const std::string& hash); -extern uint160 humanTo160(const std::string& buf); -extern bool humanToPK(const std::string& buf,std::vector& retVec); - - -extern bool u160ToHuman(uint160& buf, std::string& retStr); - diff --git a/src/Ledger.cpp b/src/Ledger.cpp index b419a493f..8d7dec92b 100644 --- a/src/Ledger.cpp +++ b/src/Ledger.cpp @@ -13,7 +13,6 @@ #include "../obj/src/newcoin.pb.h" #include "PackedMessage.h" #include "Config.h" -#include "Conversion.h" #include "BitcoinUtil.h" #include "Wallet.h" #include "LedgerTiming.h" @@ -21,7 +20,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()) diff --git a/src/LedgerEntrySet.cpp b/src/LedgerEntrySet.cpp index dbb364ebc..8588f8f29 100644 --- a/src/LedgerEntrySet.cpp +++ b/src/LedgerEntrySet.cpp @@ -394,10 +394,9 @@ void LedgerEntrySet::calcRawMeta(Serializer& s) if (origNode->getType() == ltRIPPLE_STATE) { - metaNode.addAccount(TMSLowID, origNode->getIValueFieldAccount(sfLowID)); - metaNode.addAccount(TMSHighID, origNode->getIValueFieldAccount(sfHighID)); + metaNode.addAccount(TMSLowID, NewcoinAddress::createAccountID(origNode->getIValueFieldAmount(sfLowLimit).getIssuer())); + metaNode.addAccount(TMSHighID, NewcoinAddress::createAccountID(origNode->getIValueFieldAmount(sfHighLimit).getIssuer())); } - } if (origNode->getType() == ltOFFER) @@ -1011,6 +1010,7 @@ STAmount LedgerEntrySet::rippleTransferFee(const uint160& uSenderID, const uint1 void LedgerEntrySet::rippleCredit(const uint160& uSenderID, const uint160& uReceiverID, const STAmount& saAmount, bool bCheckIssuer) { uint160 uIssuerID = saAmount.getIssuer(); + uint160 uCurrencyID = saAmount.getCurrency(); assert(!bCheckIssuer || uSenderID == uIssuerID || uReceiverID == uIssuerID); @@ -1024,14 +1024,16 @@ void LedgerEntrySet::rippleCredit(const uint160& uSenderID, const uint160& uRece STAmount saBalance = saAmount; + saBalance.setIssuer(ACCOUNT_ONE); + sleRippleState = entryCreate(ltRIPPLE_STATE, uIndex); if (!bFlipped) saBalance.negate(); sleRippleState->setIFieldAmount(sfBalance, saBalance); - sleRippleState->setIFieldAccount(bFlipped ? sfHighID : sfLowID, uSenderID); - sleRippleState->setIFieldAccount(bFlipped ? sfLowID : sfHighID, uReceiverID); + sleRippleState->setIFieldAmount(bFlipped ? sfHighLimit : sfLowLimit, STAmount(uCurrencyID, uSenderID)); + sleRippleState->setIFieldAmount(bFlipped ? sfLowLimit : sfHighLimit, STAmount(uCurrencyID, uReceiverID)); } else { diff --git a/src/LedgerFormats.cpp b/src/LedgerFormats.cpp index 1db310a4c..fc70296ba 100644 --- a/src/LedgerFormats.cpp +++ b/src/LedgerFormats.cpp @@ -73,9 +73,7 @@ LedgerEntryFormat LedgerFormats[]= { "RippleState", ltRIPPLE_STATE, { { S_FIELD(Flags), STI_UINT32, SOE_FLAGS, 0 }, { S_FIELD(Balance), STI_AMOUNT, SOE_REQUIRED, 0 }, - { S_FIELD(LowID), STI_ACCOUNT, SOE_REQUIRED, 0 }, { S_FIELD(LowLimit), STI_AMOUNT, SOE_REQUIRED, 0 }, - { S_FIELD(HighID), STI_ACCOUNT, SOE_REQUIRED, 0 }, { S_FIELD(HighLimit), STI_AMOUNT, SOE_REQUIRED, 0 }, { S_FIELD(LastTxnID), STI_HASH256, SOE_REQUIRED, 0 }, { S_FIELD(LastTxnSeq), STI_UINT32, SOE_REQUIRED, 0 }, diff --git a/src/LedgerMaster.cpp b/src/LedgerMaster.cpp index abdbf12e9..e0adb16ad 100644 --- a/src/LedgerMaster.cpp +++ b/src/LedgerMaster.cpp @@ -5,7 +5,6 @@ #include "Application.h" #include "NewcoinAddress.h" -#include "Conversion.h" #include "Log.h" uint32 LedgerMaster::getCurrentLedgerIndex() diff --git a/src/LedgerMaster.h b/src/LedgerMaster.h index 37db69c5c..76e632738 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); } diff --git a/src/Log.cpp b/src/Log.cpp index bdd56959b..948552cbf 100644 --- a/src/Log.cpp +++ b/src/Log.cpp @@ -10,6 +10,8 @@ boost::recursive_mutex Log::sLock; LogSeverity Log::sMinSeverity = lsINFO; std::ofstream* Log::outStream = NULL; +boost::filesystem::path *Log::pathToLog = NULL; +uint32 Log::logRotateCounter = 0; Log::~Log() { @@ -31,6 +33,48 @@ Log::~Log() (*outStream) << logMsg << std::endl; } + +std::string Log::rotateLog(void) +{ + boost::recursive_mutex::scoped_lock sl(sLock); + boost::filesystem::path abs_path; + std::string abs_path_str; + + uint32 failsafe = 0; + + std::string abs_new_path_str; + do { + std::string s; + std::stringstream out; + + failsafe++; + if (failsafe == std::numeric_limits::max()) { + return "unable to create new log file; too many log files!"; + } + abs_path = boost::filesystem::absolute(""); + abs_path /= *pathToLog; + abs_path_str = abs_path.parent_path().string(); + out << logRotateCounter; + s = out.str(); + + + abs_new_path_str = abs_path_str + "/" + s + + "_" + pathToLog->filename().string(); + + logRotateCounter++; + + } while (boost::filesystem::exists(boost::filesystem::path(abs_new_path_str))); + + outStream->close(); + boost::filesystem::rename(abs_path, boost::filesystem::path(abs_new_path_str)); + + + + setLogFile(*pathToLog); + + return abs_new_path_str; + +} + void Log::setMinSeverity(LogSeverity s) { boost::recursive_mutex::scoped_lock sl(sLock); @@ -52,4 +96,6 @@ void Log::setLogFile(boost::filesystem::path path) outStream = newStream; if (outStream) Log(lsINFO) << "Starting up"; + + pathToLog = new boost::filesystem::path(path); } diff --git a/src/Log.h b/src/Log.h index 715301222..fd3db13fd 100644 --- a/src/Log.h +++ b/src/Log.h @@ -9,6 +9,9 @@ // Ensure that we don't get value.h without writer.h #include "../json/json.h" +#include "types.h" +#include + enum LogSeverity { lsTRACE = 0, @@ -33,6 +36,9 @@ protected: mutable std::ostringstream oss; LogSeverity mSeverity; + static boost::filesystem::path *pathToLog; + static uint32 logRotateCounter; + public: Log(LogSeverity s) : mSeverity(s) { ; } @@ -51,6 +57,7 @@ public: static void setMinSeverity(LogSeverity); static void setLogFile(boost::filesystem::path); + static std::string rotateLog(void); }; #endif diff --git a/src/NetworkOPs.cpp b/src/NetworkOPs.cpp index 043389226..9988a0392 100644 --- a/src/NetworkOPs.cpp +++ b/src/NetworkOPs.cpp @@ -67,6 +67,13 @@ void NetworkOPs::closeTimeOffset(int offset) Log(lsINFO) << "Close time offset now " << mCloseTimeOffset; } +uint32 NetworkOPs::getLedgerID(const uint256& hash) +{ + Ledger::ref lrLedger = mLedgerMaster->getLedgerByHash(hash); + + return lrLedger ? lrLedger->getLedgerSeq() : 0; +} + uint32 NetworkOPs::getCurrentLedgerID() { return mLedgerMaster->getCurrentLedger()->getLedgerSeq(); diff --git a/src/NetworkOPs.h b/src/NetworkOPs.h index ed6e7f047..cc84f9f89 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() { @@ -103,13 +104,14 @@ 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(); } - // 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(); } + SLE::pointer getSLE(Ledger::pointer lpLedger, const uint256& uHash) { return lpLedger->getSLE(uHash); } // // Transaction operations @@ -134,8 +136,8 @@ public: // Directory functions // - STVector256 getDirNodeInfo(const uint256& uLedger, const uint256& uRootIndex, - uint64& uNodePrevious, uint64& uNodeNext); + STVector256 getDirNodeInfo(const uint256& uLedger, const uint256& uRootIndex, + uint64& uNodePrevious, uint64& uNodeNext); // // Nickname functions @@ -150,7 +152,6 @@ public: Json::Value getOwnerInfo(const uint256& uLedger, const NewcoinAddress& naAccount); Json::Value getOwnerInfo(Ledger::pointer lpLedger, const NewcoinAddress& naAccount); - // raw object operations bool findRawLedger(const uint256& ledgerHash, std::vector& rawLedger); bool findRawTransaction(const uint256& transactionHash, std::vector& rawTransaction); diff --git a/src/NewcoinAddress.h b/src/NewcoinAddress.h index 369b609d0..707a976c5 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) diff --git a/src/Peer.cpp b/src/Peer.cpp index ea27e06c8..641a33571 100644 --- a/src/Peer.cpp +++ b/src/Peer.cpp @@ -12,7 +12,6 @@ #include "Peer.h" #include "Config.h" #include "Application.h" -#include "Conversion.h" #include "SerializedTransaction.h" #include "utils.h" #include "Log.h" diff --git a/src/RPCServer.cpp b/src/RPCServer.cpp index cd79010c4..ee3fb0620 100644 --- a/src/RPCServer.cpp +++ b/src/RPCServer.cpp @@ -6,7 +6,6 @@ #include "Application.h" #include "RPC.h" #include "Wallet.h" -#include "Conversion.h" #include "NewcoinAddress.h" #include "AccountState.h" #include "NicknameState.h" @@ -14,6 +13,8 @@ #include "Log.h" #include "RippleLines.h" +#include "Pathfinder.h" + #include #include @@ -422,7 +423,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 +438,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 +476,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 +491,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 +568,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 +596,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 +616,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 +656,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 +671,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 +713,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 +728,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 +768,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 +783,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 +915,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 +923,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 +943,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 +970,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 +993,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 +1059,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 +1105,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 +1145,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 +1158,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 +1177,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()) @@ -1462,7 +1451,7 @@ Json::Value RPCServer::doRipple(const Json::Value ¶ms) bLimit = params.size() != iArg ? params[iArg].asString() == "limit" : false; bAverage = params.size() != iArg ? params[iArg].asString() == "average" : false; - if (!bPartial && !bFull) + if (!bLimit && !bAverage) { return RPCError(rpcINVALID_PARAMS); } @@ -1494,8 +1483,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 +1491,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,8 +1544,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; uint32 uQualityIn = 0; @@ -1575,7 +1561,7 @@ Json::Value RPCServer::doRippleLineSet(const Json::Value& params) { return RPCError(rpcDST_ACT_MALFORMED); } - else if (!saLimitAmount.setFullValue(params[3u].asString(), params.size() >= 5 ? params[4u].asString() : "")) + else if (!saLimitAmount.setFullValue(params[3u].asString(), params.size() >= 5 ? params[4u].asString() : "", params[2u].asString())) { return RPCError(rpcSRC_AMT_MALFORMED); } @@ -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()) @@ -1606,8 +1592,7 @@ Json::Value RPCServer::doRippleLineSet(const Json::Value& params) asSrc->getSeq(), theConfig.FEE_DEFAULT, 0, // YYY No source tag - naDstAccountID, - bLimitAmount, saLimitAmount, + saLimitAmount, bQualityIn, uQualityIn, bQualityOut, uQualityOut); @@ -1627,7 +1612,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 +1621,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 +1633,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 +1723,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 +1732,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") @@ -1794,7 +1777,17 @@ Json::Value RPCServer::doSend(const Json::Value& params) // Destination exists, ordinary send. STPathSet spsPaths; + uint160 srcCurrencyID; + bool ret_b; + ret_b = false; + if (!saSrcAmountMax.isNative() || !saDstAmount.isNative()) + { + STAmount::currencyFromString(srcCurrencyID, sSrcCurrency); + Pathfinder pf(naSrcAccountID, naDstAccountID, srcCurrencyID, saDstAmount); + ret_b = pf.findPaths(5, 1, spsPaths); + } + trans = Transaction::sharedPayment( naAccountPublic, naAccountPrivate, naSrcAccountID, @@ -2081,7 +2074,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 +2083,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 +2116,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 +2142,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 +2168,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 +2303,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 +2316,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 +2329,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()) @@ -2518,6 +2508,11 @@ Json::Value RPCServer::doLogin(const Json::Value& params) } } +Json::Value RPCServer::doLogRotate(const Json::Value& params) +{ + return Log::rotateLog(); +} + Json::Value RPCServer::doCommand(const std::string& command, Json::Value& params) { Log(lsTRACE) << "RPC:" << command; @@ -2543,6 +2538,7 @@ Json::Value RPCServer::doCommand(const std::string& command, Json::Value& params { "data_fetch", &RPCServer::doDataFetch, 1, 1, true }, { "data_store", &RPCServer::doDataStore, 2, 2, true }, { "ledger", &RPCServer::doLedger, 0, 2, false, optNetwork }, + { "logrotate", &RPCServer::doLogRotate, 0, 0, true, 0 }, { "nickname_info", &RPCServer::doNicknameInfo, 1, 1, false, optCurrent }, { "nickname_set", &RPCServer::doNicknameSet, 2, 3, false, optCurrent }, { "offer_create", &RPCServer::doOfferCreate, 9, 10, false, optCurrent }, @@ -2602,7 +2598,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); } diff --git a/src/RPCServer.h b/src/RPCServer.h index 33f9699b0..8d56ed55a 100644 --- a/src/RPCServer.h +++ b/src/RPCServer.h @@ -141,6 +141,7 @@ private: Json::Value doDataFetch(const Json::Value& params); Json::Value doDataStore(const Json::Value& params); Json::Value doLedger(const Json::Value& params); + Json::Value doLogRotate(const Json::Value& params); Json::Value doNicknameInfo(const Json::Value& params); Json::Value doNicknameSet(const Json::Value& params); Json::Value doOfferCreate(const Json::Value& params); @@ -184,6 +185,7 @@ private: Json::Value doLogin(const Json::Value& params); + public: static pointer create(boost::asio::io_service& io_service, NetworkOPs* mNetOps) { diff --git a/src/RippleCalc.cpp b/src/RippleCalc.cpp index 7b88303bc..3a1b1cc2f 100644 --- a/src/RippleCalc.cpp +++ b/src/RippleCalc.cpp @@ -744,7 +744,7 @@ void RippleCalc::calcNodeRipple( { const uint160 uCurrencyID = saCur.getCurrency(); const uint160 uCurIssuerID = saCur.getIssuer(); - const uint160 uPrvIssuerID = saPrv.getIssuer(); + // const uint160 uPrvIssuerID = saPrv.getIssuer(); STAmount saCurIn = STAmount::divide(STAmount::multiply(saCur, uQualityOut, uCurrencyID, uCurIssuerID), uQualityIn, uCurrencyID, uCurIssuerID); diff --git a/src/RippleState.cpp b/src/RippleState.cpp index 26a5bb707..72b9efd10 100644 --- a/src/RippleState.cpp +++ b/src/RippleState.cpp @@ -7,12 +7,12 @@ RippleState::RippleState(SerializedLedgerEntry::pointer ledgerEntry) : { if (!mLedgerEntry || mLedgerEntry->getType() != ltRIPPLE_STATE) return; - mLowID = mLedgerEntry->getIValueFieldAccount(sfLowID); - mHighID = mLedgerEntry->getIValueFieldAccount(sfHighID); - mLowLimit = mLedgerEntry->getIValueFieldAmount(sfLowLimit); mHighLimit = mLedgerEntry->getIValueFieldAmount(sfHighLimit); + mLowID = NewcoinAddress::createAccountID(mLowLimit.getIssuer()); + mHighID = NewcoinAddress::createAccountID(mHighLimit.getIssuer()); + mLowQualityIn = mLedgerEntry->getIFieldU32(sfLowQualityIn); mLowQualityOut = mLedgerEntry->getIFieldU32(sfLowQualityOut); diff --git a/src/SerializedLedger.cpp b/src/SerializedLedger.cpp index 0353df8b6..08b807890 100644 --- a/src/SerializedLedger.cpp +++ b/src/SerializedLedger.cpp @@ -128,12 +128,12 @@ NewcoinAddress SerializedLedgerEntry::getOwner() NewcoinAddress SerializedLedgerEntry::getFirstOwner() { - return getIValueFieldAccount(sfLowID); + return NewcoinAddress::createAccountID(getIValueFieldAmount(sfLowLimit).getIssuer()); } NewcoinAddress SerializedLedgerEntry::getSecondOwner() { - return getIValueFieldAccount(sfHighID); + return NewcoinAddress::createAccountID(getIValueFieldAmount(sfHighLimit).getIssuer()); } std::vector SerializedLedgerEntry::getOwners() @@ -146,16 +146,25 @@ std::vector SerializedLedgerEntry::getOwners() switch (getIFieldSType(i)) { case sfAccount: - case sfLowID: - case sfHighID: - { - const STAccount* entry = dynamic_cast(mObject.peekAtPIndex(i)); - if ((entry != NULL) && entry->getValueH160(account)) - owners.push_back(Ledger::getAccountRootIndex(account)); - } + { + const STAccount* entry = dynamic_cast(mObject.peekAtPIndex(i)); + if ((entry != NULL) && entry->getValueH160(account)) + owners.push_back(Ledger::getAccountRootIndex(account)); + } + break; + + case sfLowLimit: + case sfHighLimit: + { + const STAmount* entry = dynamic_cast(mObject.peekAtPIndex(i)); + if ((entry != NULL)) + owners.push_back(Ledger::getAccountRootIndex(entry->getIssuer())); + } + break; default: nothing(); + break; } } diff --git a/src/SerializedObject.cpp b/src/SerializedObject.cpp index af4210f3d..eaf7ec400 100644 --- a/src/SerializedObject.cpp +++ b/src/SerializedObject.cpp @@ -42,9 +42,6 @@ std::auto_ptr STObject::makeDefaultObject(SerializedTypeID id, c case STI_VL: return std::auto_ptr(new STVariableLength(name)); - case STI_TL: - return std::auto_ptr(new STTaggedList(name)); - case STI_ACCOUNT: return std::auto_ptr(new STAccount(name)); @@ -91,9 +88,6 @@ std::auto_ptr STObject::makeDeserializedObject(SerializedTypeID case STI_VL: return STVariableLength::deserialize(sit, name); - case STI_TL: - return STTaggedList::deserialize(sit, name); - case STI_ACCOUNT: return STAccount::deserialize(sit, name); @@ -476,17 +470,6 @@ std::vector STObject::getValueFieldVL(SOE_Field field) const return cf->getValue(); } -std::vector STObject::getValueFieldTL(SOE_Field field) const -{ - const SerializedType* rf = peekAtPField(field); - if (!rf) throw std::runtime_error("Field not found"); - SerializedTypeID id = rf->getSType(); - if (id == STI_NOTPRESENT) return std::vector(); // optional field not present - const STTaggedList *cf = dynamic_cast(rf); - if (!cf) throw std::runtime_error("Wrong field type"); - return cf->getValue(); -} - STAmount STObject::getValueFieldAmount(SOE_Field field) const { const SerializedType* rf = peekAtPField(field); @@ -620,16 +603,6 @@ void STObject::setValueFieldVL(SOE_Field field, const std::vector cf->setValue(v); } -void STObject::setValueFieldTL(SOE_Field field, const std::vector& v) -{ - SerializedType* rf = getPField(field); - if (!rf) throw std::runtime_error("Field not found"); - if (rf->getSType() == STI_NOTPRESENT) rf = makeFieldPresent(field); - STTaggedList* cf = dynamic_cast(rf); - if (!cf) throw std::runtime_error("Wrong field type"); - cf->setValue(v); -} - void STObject::setValueFieldAmount(SOE_Field field, const STAmount &v) { SerializedType* rf = getPField(field); diff --git a/src/SerializedTypes.cpp b/src/SerializedTypes.cpp index 3bd54dc34..dde47265c 100644 --- a/src/SerializedTypes.cpp +++ b/src/SerializedTypes.cpp @@ -255,51 +255,6 @@ void STAccount::setValueNCA(const NewcoinAddress& nca) setValueH160(nca.getAccountID()); } -std::string STTaggedList::getText() const -{ - std::string ret; - for (std::vector::const_iterator it=value.begin(); it!=value.end(); ++it) - { - ret += boost::lexical_cast(it->first); - ret += ","; - ret += strHex(it->second); - } - return ret; -} - -Json::Value STTaggedList::getJson(int) const -{ - Json::Value ret(Json::arrayValue); - - for (std::vector::const_iterator it=value.begin(); it!=value.end(); ++it) - { - Json::Value elem(Json::arrayValue); - elem.append(it->first); - elem.append(strHex(it->second)); - ret.append(elem); - } - - return ret; -} - -STTaggedList* STTaggedList::construct(SerializerIterator& u, const char *name) -{ - return new STTaggedList(name, u.getTaggedList()); -} - -int STTaggedList::getLength() const -{ - int ret = Serializer::getTaggedListLength(value); - if (ret<0) throw std::overflow_error("bad TL length"); - return ret; -} - -bool STTaggedList::isEquivalent(const SerializedType& t) const -{ - const STTaggedList* v = dynamic_cast(&t); - return v && (value == v->value); -} - STPathSet* STPathSet::construct(SerializerIterator& s, const char *name) { std::vector paths; diff --git a/src/SerializedTypes.h b/src/SerializedTypes.h index 6c9099df5..28a306367 100644 --- a/src/SerializedTypes.h +++ b/src/SerializedTypes.h @@ -15,24 +15,11 @@ enum SerializedTypeID STI_DONE = -1, STI_NOTPRESENT = 0, - // common types - STI_UINT32 = 1, - STI_UINT64 = 2, - STI_HASH128 = 3, - STI_HASH256 = 4, - STI_TL = 5, - STI_AMOUNT = 6, - STI_VL = 7, - STI_ACCOUNT = 8, - STI_OBJECT = 14, - STI_ARRAY = 15, - - // uncommon types - STI_UINT8 = 16, - STI_UINT16 = 17, - STI_HASH160 = 18, - STI_PATHSET = 19, - STI_VECTOR256 = 20, +#define TYPE(name, field, value) STI_##field = value, +#define FIELD(name, field, value) +#include "SerializeProto.h" +#undef TYPE +#undef FIELD // high level types STI_TRANSACTION = 100001, @@ -730,45 +717,6 @@ namespace boost }; } -class STTaggedList : public SerializedType -{ -protected: - std::vector value; - - STTaggedList* duplicate() const { return new STTaggedList(name, value); } - static STTaggedList* construct(SerializerIterator&, const char* name = NULL); - -public: - - STTaggedList() { ; } - STTaggedList(const char* n) : SerializedType(n) { ; } - STTaggedList(const std::vector& v) : value(v) { ; } - STTaggedList(const char* n, const std::vector& v) : SerializedType(n), value(v) { ; } - static std::auto_ptr deserialize(SerializerIterator& sit, const char* name) - { return std::auto_ptr(construct(sit, name)); } - - int getLength() const; - SerializedTypeID getSType() const { return STI_TL; } - std::string getText() const; - void add(Serializer& s) const { if (s.addTaggedList(value) < 0) throw(0); } - - const std::vector& peekValue() const { return value; } - std::vector& peekValue() { return value; } - std::vector getValue() const { return value; } - virtual Json::Value getJson(int) const; - - void setValue(const std::vector& v) { value=v; } - - int getItemCount() const { return value.size(); } - bool isEmpty() const { return value.empty(); } - - void clear() { value.erase(value.begin(), value.end()); } - void addItem(const TaggedListItem& v) { value.push_back(v); } - - operator std::vector() const { return value; } - virtual bool isEquivalent(const SerializedType& t) const; -}; - class STVector256 : public SerializedType { protected: diff --git a/src/Transaction.cpp b/src/Transaction.cpp index 526f433bf..c6488cb8a 100644 --- a/src/Transaction.cpp +++ b/src/Transaction.cpp @@ -256,18 +256,13 @@ Transaction::pointer Transaction::sharedCreate( Transaction::pointer Transaction::setCreditSet( const NewcoinAddress& naPrivateKey, - const NewcoinAddress& naDstAccountID, - bool bLimitAmount, const STAmount& saLimitAmount, bool bQualityIn, uint32 uQualityIn, bool bQualityOut, uint32 uQualityOut) { - mTransaction->setITFieldAccount(sfDestination, naDstAccountID); - - if (bLimitAmount) - mTransaction->setITFieldAmount(sfLimitAmount, saLimitAmount); + mTransaction->setITFieldAmount(sfLimitAmount, saLimitAmount); if (bQualityIn) mTransaction->setITFieldU32(sfQualityIn, uQualityIn); @@ -286,8 +281,6 @@ Transaction::pointer Transaction::sharedCreditSet( uint32 uSeq, const STAmount& saFee, uint32 uSourceTag, - const NewcoinAddress& naDstAccountID, - bool bLimitAmount, const STAmount& saLimitAmount, bool bQualityIn, uint32 uQualityIn, @@ -296,8 +289,8 @@ Transaction::pointer Transaction::sharedCreditSet( { pointer tResult = boost::make_shared(ttCREDIT_SET, naPublicKey, naSourceAccount, uSeq, saFee, uSourceTag); - return tResult->setCreditSet(naPrivateKey, naDstAccountID, - bLimitAmount, saLimitAmount, + return tResult->setCreditSet(naPrivateKey, + saLimitAmount, bQualityIn, uQualityIn, bQualityOut, uQualityOut); } diff --git a/src/Transaction.h b/src/Transaction.h index abe612853..d8dc7fa7c 100644 --- a/src/Transaction.h +++ b/src/Transaction.h @@ -74,8 +74,6 @@ private: Transaction::pointer setCreditSet( const NewcoinAddress& naPrivateKey, - const NewcoinAddress& naDstAccountID, - bool bLimitAmount, const STAmount& saLimitAmount, bool bQualityIn, uint32 uQualityIn, @@ -185,8 +183,6 @@ public: uint32 uSeq, const STAmount& saFee, uint32 uSourceTag, - const NewcoinAddress& naDstAccountID, - bool bLimitAmount, const STAmount& saLimitAmount, bool bQualityIn, uint32 uQualityIn, diff --git a/src/TransactionAction.cpp b/src/TransactionAction.cpp index 8f3746916..c668236a7 100644 --- a/src/TransactionAction.cpp +++ b/src/TransactionAction.cpp @@ -166,18 +166,24 @@ TER TransactionEngine::doAccountSet(const SerializedTransaction& txn) { uint32 uRate = txn.getITFieldU32(sfTransferRate); - if (!uRate) + if (!uRate || uRate == QUALITY_ONE) { Log(lsINFO) << "doAccountSet: unset transfer rate"; mTxnAccount->makeIFieldAbsent(sfTransferRate); } - else + else if (uRate > QUALITY_ONE) { Log(lsINFO) << "doAccountSet: set transfer rate"; mTxnAccount->setIFieldU32(sfTransferRate, uRate); } + else + { + Log(lsINFO) << "doAccountSet: bad transfer rate"; + + return temBAD_TRANSFER_RATE; + } } // @@ -235,18 +241,27 @@ TER TransactionEngine::doCreditSet(const SerializedTransaction& txn) TER terResult = tesSUCCESS; Log(lsINFO) << "doCreditSet>"; + const STAmount saLimitAmount = txn.getITFieldAmount(sfLimitAmount); + const bool bQualityIn = txn.getITFieldPresent(sfQualityIn); + const uint32 uQualityIn = bQualityIn ? txn.getITFieldU32(sfQualityIn) : 0; + const bool bQualityOut = txn.getITFieldPresent(sfQualityOut); + const uint32 uQualityOut = bQualityIn ? txn.getITFieldU32(sfQualityOut) : 0; + const uint160 uCurrencyID = saLimitAmount.getCurrency(); + uint160 uDstAccountID = saLimitAmount.getIssuer(); + const bool bFlipped = mTxnAccountID > uDstAccountID; // true, iff current is not lowest. + bool bDelIndex = false; + // Check if destination makes sense. - uint160 uDstAccountID = txn.getITFieldAccount(sfDestination); if (!uDstAccountID) { - Log(lsINFO) << "doCreditSet: Invalid transaction: Destination account not specifed."; + Log(lsINFO) << "doCreditSet: Malformed transaction: Destination account not specifed."; return temDST_NEEDED; } else if (mTxnAccountID == uDstAccountID) { - Log(lsINFO) << "doCreditSet: Invalid transaction: Can not extend credit to self."; + Log(lsINFO) << "doCreditSet: Malformed transaction: Can not extend credit to self."; return temDST_IS_SRC; } @@ -259,15 +274,8 @@ TER TransactionEngine::doCreditSet(const SerializedTransaction& txn) return terNO_DST; } - const bool bFlipped = mTxnAccountID > uDstAccountID; // true, iff current is not lowest. - const bool bLimitAmount = txn.getITFieldPresent(sfLimitAmount); - const STAmount saLimitAmount = bLimitAmount ? txn.getITFieldAmount(sfLimitAmount) : STAmount(); - const bool bQualityIn = txn.getITFieldPresent(sfQualityIn); - const uint32 uQualityIn = bQualityIn ? txn.getITFieldU32(sfQualityIn) : 0; - const bool bQualityOut = txn.getITFieldPresent(sfQualityOut); - const uint32 uQualityOut = bQualityIn ? txn.getITFieldU32(sfQualityOut) : 0; - const uint160 uCurrencyID = saLimitAmount.getCurrency(); - bool bDelIndex = false; + STAmount saLimitAllow = saLimitAmount; + saLimitAllow.setIssuer(mTxnAccountID); SLE::pointer sleRippleState = entryCache(ltRIPPLE_STATE, Ledger::getRippleStateIndex(mTxnAccountID, uDstAccountID, uCurrencyID)); if (sleRippleState) @@ -277,8 +285,8 @@ TER TransactionEngine::doCreditSet(const SerializedTransaction& txn) if (!saLimitAmount) { // Zeroing line. - uint160 uLowID = sleRippleState->getIValueFieldAccount(sfLowID).getAccountID(); - uint160 uHighID = sleRippleState->getIValueFieldAccount(sfHighID).getAccountID(); + uint160 uLowID = sleRippleState->getIValueFieldAmount(sfLowLimit).getIssuer(); + uint160 uHighID = sleRippleState->getIValueFieldAmount(sfHighLimit).getIssuer(); bool bLow = uLowID == uSrcAccountID; bool bHigh = uLowID == uDstAccountID; bool bBalanceZero = !sleRippleState->getIValueFieldAmount(sfBalance); @@ -299,8 +307,7 @@ TER TransactionEngine::doCreditSet(const SerializedTransaction& txn) if (!bDelIndex) { - if (bLimitAmount) - sleRippleState->setIFieldAmount(bFlipped ? sfHighLimit: sfLowLimit , saLimitAmount); + sleRippleState->setIFieldAmount(bFlipped ? sfHighLimit: sfLowLimit, saLimitAllow); if (!bQualityIn) { @@ -348,10 +355,9 @@ TER TransactionEngine::doCreditSet(const SerializedTransaction& txn) Log(lsINFO) << "doCreditSet: Creating ripple line: " << sleRippleState->getIndex().ToString(); sleRippleState->setIFieldAmount(sfBalance, STAmount(uCurrencyID, ACCOUNT_ONE)); // Zero balance in currency. - sleRippleState->setIFieldAmount(bFlipped ? sfHighLimit : sfLowLimit, saLimitAmount); - sleRippleState->setIFieldAmount(bFlipped ? sfLowLimit : sfHighLimit, STAmount(uCurrencyID, ACCOUNT_ONE)); - sleRippleState->setIFieldAccount(bFlipped ? sfHighID : sfLowID, mTxnAccountID); - sleRippleState->setIFieldAccount(bFlipped ? sfLowID : sfHighID, uDstAccountID); + sleRippleState->setIFieldAmount(bFlipped ? sfHighLimit : sfLowLimit, saLimitAllow); + sleRippleState->setIFieldAmount(bFlipped ? sfLowLimit : sfHighLimit, STAmount(uCurrencyID, uDstAccountID)); + if (uQualityIn) sleRippleState->setIFieldU32(bFlipped ? sfHighQualityIn : sfLowQualityIn, uQualityIn); if (uQualityOut) diff --git a/src/TransactionErr.cpp b/src/TransactionErr.cpp index 878d7cd1c..85ea95594 100644 --- a/src/TransactionErr.cpp +++ b/src/TransactionErr.cpp @@ -31,6 +31,7 @@ bool transResultInfo(TER terCode, std::string& strToken, std::string& strHuman) { temBAD_PATH, "temBAD_PATH", "Malformed." }, { temBAD_PATH_LOOP, "temBAD_PATH_LOOP", "Malformed." }, { temBAD_PUBLISH, "temBAD_PUBLISH", "Malformed: bad publish." }, + { temBAD_TRANSFER_RATE, "temBAD_TRANSFER_RATE", "Malformed: transfer rate must be >= 1.0" }, { temBAD_SET_ID, "temBAD_SET_ID", "Malformed." }, { temCREATEXNS, "temCREATEXNS", "Can not specify non XNS for Create." }, { temDST_IS_SRC, "temDST_IS_SRC", "Destination may not be source." }, @@ -89,3 +90,4 @@ std::string transHuman(TER terCode) return transResultInfo(terCode, strToken, strHuman) ? strHuman : "-"; } +// vim:ts=4 diff --git a/src/TransactionErr.h b/src/TransactionErr.h index 4f0d5a799..7ce5cd610 100644 --- a/src/TransactionErr.h +++ b/src/TransactionErr.h @@ -33,6 +33,7 @@ enum TER // aka TransactionEngineResult temBAD_PATH, temBAD_PATH_LOOP, temBAD_PUBLISH, + temBAD_TRANSFER_RATE, temBAD_SET_ID, temCREATEXNS, temDST_IS_SRC, diff --git a/src/TransactionFormats.cpp b/src/TransactionFormats.cpp index 3ab00f7de..a66f36d41 100644 --- a/src/TransactionFormats.cpp +++ b/src/TransactionFormats.cpp @@ -27,11 +27,10 @@ TransactionFormat InnerTxnFormats[]= }, { "CreditSet", ttCREDIT_SET, { { S_FIELD(Flags), STI_UINT32, SOE_FLAGS, 0 }, - { S_FIELD(Destination), STI_ACCOUNT, SOE_REQUIRED, 0 }, - { S_FIELD(SourceTag), STI_UINT32, SOE_IFFLAG, 1 }, - { S_FIELD(LimitAmount), STI_AMOUNT, SOE_IFFLAG, 2 }, - { S_FIELD(QualityIn), STI_UINT32, SOE_IFFLAG, 4 }, - { S_FIELD(QualityOut), STI_UINT32, SOE_IFFLAG, 8 }, + { S_FIELD(LimitAmount), STI_AMOUNT, SOE_REQUIRED, 0 }, + { S_FIELD(QualityIn), STI_UINT32, SOE_IFFLAG, 1 }, + { S_FIELD(QualityOut), STI_UINT32, SOE_IFFLAG, 2 }, + { S_FIELD(SourceTag), STI_UINT32, SOE_IFFLAG, 4 }, { sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } } }, /* diff --git a/src/UniqueNodeList.cpp b/src/UniqueNodeList.cpp index b5b1d2c80..96ca1b7d7 100644 --- a/src/UniqueNodeList.cpp +++ b/src/UniqueNodeList.cpp @@ -2,7 +2,6 @@ // XXX Want a limit of 2000 validators. #include "Application.h" -#include "Conversion.h" #include "HttpsClient.h" #include "Log.h" #include "ParseSection.h" diff --git a/src/Version.h b/src/Version.h index d7cd3a02a..f35da8166 100644 --- a/src/Version.h +++ b/src/Version.h @@ -16,11 +16,11 @@ // Version we prefer to speak: #define PROTO_VERSION_MAJOR 0 -#define PROTO_VERSION_MINOR 7 +#define PROTO_VERSION_MINOR 8 // Version we will speak to: #define MIN_PROTO_MAJOR 0 -#define MIN_PROTO_MINOR 7 +#define MIN_PROTO_MINOR 8 #define MAKE_VERSION_INT(maj,min) ((maj << 16) | min) #define GET_VERSION_MAJOR(ver) (ver >> 16) diff --git a/src/WSDoor.cpp b/src/WSDoor.cpp index b4394fb95..208c5c71c 100644 --- a/src/WSDoor.cpp +++ b/src/WSDoor.cpp @@ -22,6 +22,9 @@ // This is a light weight, untrusted interface for web clients. // For now we don't provide proof. Later we will. // +// Might need to support this header for browsers: Access-Control-Allow-Origin: * +// - https://developer.mozilla.org/en-US/docs/HTTP_access_control +// // // Strategy: @@ -75,7 +78,12 @@ public: Json::Value invokeCommand(const Json::Value& jvRequest); boost::unordered_set parseAccountIds(const Json::Value& jvArray); - // Commands + // 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); void doAccountInfoUnsubscribe(Json::Value& jvResult, const Json::Value& jvRequest); void doAccountTransactionSubscribe(Json::Value& jvResult, const Json::Value& jvRequest); @@ -293,6 +301,12 @@ Json::Value WSConnection::invokeCommand(const Json::Value& jvRequest) const char* pCommand; doFuncPtr dfpFunc; } commandsA[] = { + // Request-Response Commands: + { "ledger_closed", &WSConnection::doLedgerClosed }, + { "ledger_current", &WSConnection::doLedgerCurrent }, + { "ledger_entry", &WSConnection::doLedgerEntry }, + + // Streaming commands: { "account_info_subscribe", &WSConnection::doAccountInfoSubscribe }, { "account_info_unsubscribe", &WSConnection::doAccountInfoUnsubscribe }, { "account_transaction_subscribe", &WSConnection::doAccountTransactionSubscribe }, @@ -541,6 +555,239 @@ 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_index"] = theApp->getOPs().getCurrentLedgerID(); +} + +void WSConnection::doLedgerEntry(Json::Value& jvResult, const Json::Value& jvRequest) +{ + 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; + + 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; + + uint256 uNodeIndex; + bool bNodeBinary = false; + + if (jvRequest.isMember("index")) + { + // XXX Needs to provide proof. + uNodeIndex.SetHex(jvRequest["index"].asString()); + bNodeBinary = true; + } + else if (jvRequest.isMember("account_root")) + { + NewcoinAddress naAccount; + + if (!naAccount.setAccountID(jvRequest["account_root"].asString())) + { + jvResult["error"] = "malformedAddress"; + } + else + { + uNodeIndex = Ledger::getAccountRootIndex(naAccount.getAccountID()); + } + } + else if (jvRequest.isMember("directory")) + { + + if (!jvRequest.isObject()) + { + uNodeIndex.SetHex(jvRequest["directory"].asString()); + } + else if (jvRequest["directory"].isMember("sub_index") + && !jvRequest["directory"]["sub_index"].isIntegral()) + { + jvResult["error"] = "malformedRequest"; + } + else + { + uint64 uSubIndex = jvRequest["directory"].isMember("sub_index") + ? jvRequest["directory"]["sub_index"].asUInt() + : 0; + + if (jvRequest["directory"].isMember("dir_root")) + { + uint256 uDirRoot; + + uDirRoot.SetHex(jvRequest["dir_root"].asString()); + + uNodeIndex = Ledger::getDirNodeIndex(uDirRoot, uSubIndex); + } + else if (jvRequest["directory"].isMember("owner")) + { + NewcoinAddress naOwnerID; + + if (!naOwnerID.setAccountID(jvRequest["directory"]["owner"].asString())) + { + jvResult["error"] = "malformedAddress"; + } + else + { + uint256 uDirRoot = Ledger::getOwnerDirIndex(naOwnerID.getAccountID()); + + uNodeIndex = Ledger::getDirNodeIndex(uDirRoot, uSubIndex); + } + } + else + { + jvResult["error"] = "malformedRequest"; + } + } + } + else if (jvRequest.isMember("generator")) + { + NewcoinAddress naGeneratorID; + + if (!jvRequest.isObject()) + { + uNodeIndex.SetHex(jvRequest["generator"].asString()); + } + else if (!jvRequest["generator"].isMember("regular_seed")) + { + jvResult["error"] = "malformedRequest"; + } + else if (!naGeneratorID.setSeedGeneric(jvRequest["generator"]["regular_seed"].asString())) + { + jvResult["error"] = "malformedAddress"; + } + else + { + NewcoinAddress na0Public; // To find the generator's index. + NewcoinAddress naGenerator = NewcoinAddress::createGeneratorPublic(naGeneratorID); + + na0Public.setAccountPublic(naGenerator, 0); + + uNodeIndex = Ledger::getGeneratorIndex(na0Public.getAccountID()); + } + } + else if (jvRequest.isMember("offer")) + { + NewcoinAddress naAccountID; + + if (!jvRequest.isObject()) + { + uNodeIndex.SetHex(jvRequest["offer"].asString()); + } + else if (!jvRequest["offer"].isMember("account") + || !jvRequest["offer"].isMember("seq") + || !jvRequest["offer"]["seq"].isIntegral()) + { + jvResult["error"] = "malformedRequest"; + } + else if (!naAccountID.setAccountID(jvRequest["offer"]["account"].asString())) + { + jvResult["error"] = "malformedAddress"; + } + else + { + uint32 uSequence = jvRequest["offer"]["seq"].asUInt(); + + uNodeIndex = Ledger::getOfferIndex(naAccountID.getAccountID(), uSequence); + } + } + else if (jvRequest.isMember("ripple_state")) + { + 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 Should also provide proof. + jvResult["error"] = "entryNotFound"; + } + else if (bNodeBinary) + { + // XXX Should also provide proof. + Serializer s; + + sleNode->add(s); + + jvResult["node_binary"] = strHex(s.peekData()); + jvResult["index"] = uNodeIndex.ToString(); + } + else + { + jvResult["node"] = sleNode->getJson(0); + jvResult["index"] = uNodeIndex.ToString(); + } + } +} + void WSConnection::doTransactionSubcribe(Json::Value& jvResult, const Json::Value& jvRequest) { if (!theApp->getOPs().subTransaction(this)) diff --git a/src/main.cpp b/src/main.cpp index b9154261d..4a69f9f2d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -51,6 +51,7 @@ void printHelp(const po::options_description& desc) cout << " data_fetch " << endl; cout << " data_store " << endl; cout << " ledger [|current|lastclosed] [full]" << endl; + cout << " logrotate " << endl; cout << " nickname_info " << endl; cout << " nickname_set [] []" << endl; cout << " offer_create [passive]" << endl; diff --git a/src/uint256.h b/src/uint256.h index bb11b101b..3e2ab10e6 100644 --- a/src/uint256.h +++ b/src/uint256.h @@ -386,96 +386,6 @@ public: }; -////////////////////////////////////////////////////////////////////////////// -// -// uint160 -// - -class uint160 : public base_uint160 -{ -public: - typedef base_uint160 basetype; - - uint160() - { - zero(); - } - - uint160(const basetype& b) - { - *this = b; - } - - uint160& operator=(const basetype& b) - { - for (int i = 0; i < WIDTH; i++) - pn[i] = b.pn[i]; - - return *this; - } - - uint160(uint64 b) - { - *this = b; - } - - uint160& operator=(uint64 uHost) - { - zero(); - - // Put in least significant bits. - ((uint64_t *) end())[-1] = htobe64(uHost); - - return *this; - } - - explicit uint160(const std::string& str) - { - SetHex(str); - } - - explicit uint160(const std::vector& vch) - { - if (vch.size() == sizeof(pn)) - memcpy(pn, &vch[0], sizeof(pn)); - else - zero(); - } - - base_uint256 to256() const; -}; - -inline bool operator==(const uint160& a, uint64 b) { return (base_uint160)a == b; } -inline bool operator!=(const uint160& a, uint64 b) { return (base_uint160)a != b; } - -inline const uint160 operator^(const base_uint160& a, const base_uint160& b) { return uint160(a) ^= b; } -inline const uint160 operator&(const base_uint160& a, const base_uint160& b) { return uint160(a) &= b; } -inline const uint160 operator|(const base_uint160& a, const base_uint160& b) { return uint160(a) |= b; } - -inline bool operator==(const base_uint160& a, const uint160& b) { return (base_uint160)a == (base_uint160)b; } -inline bool operator!=(const base_uint160& a, const uint160& b) { return (base_uint160)a != (base_uint160)b; } -inline const uint160 operator^(const base_uint160& a, const uint160& b) { return (base_uint160)a ^ (base_uint160)b; } -inline const uint160 operator&(const base_uint160& a, const uint160& b) { return (base_uint160)a & (base_uint160)b; } -inline const uint160 operator|(const base_uint160& a, const uint160& b) { return (base_uint160)a | (base_uint160)b; } - -inline bool operator==(const uint160& a, const base_uint160& b) { return (base_uint160)a == (base_uint160)b; } -inline bool operator!=(const uint160& a, const base_uint160& b) { return (base_uint160)a != (base_uint160)b; } -inline const uint160 operator^(const uint160& a, const base_uint160& b) { return (base_uint160)a ^ (base_uint160)b; } -inline const uint160 operator&(const uint160& a, const base_uint160& b) { return (base_uint160)a & (base_uint160)b; } -inline const uint160 operator|(const uint160& a, const base_uint160& b) { return (base_uint160)a | (base_uint160)b; } -inline bool operator==(const uint160& a, const uint160& b) { return (base_uint160)a == (base_uint160)b; } -inline bool operator!=(const uint160& a, const uint160& b) { return (base_uint160)a != (base_uint160)b; } -inline const uint160 operator^(const uint160& a, const uint160& b) { return (base_uint160)a ^ (base_uint160)b; } -inline const uint160 operator&(const uint160& a, const uint160& b) { return (base_uint160)a & (base_uint160)b; } -inline const uint160 operator|(const uint160& a, const uint160& b) { return (base_uint160)a | (base_uint160)b; } - -extern std::size_t hash_value(const uint160&); - -inline const std::string strHex(const uint160& ui) -{ - return strHex(ui.begin(), ui.size()); -} - ////////////////////////////////////////////////////////////////////////////// // // uint256 @@ -694,5 +604,102 @@ inline int Testuint256AdHoc(std::vector vArg) return (0); } +////////////////////////////////////////////////////////////////////////////// +// +// uint160 +// + +class uint160 : public base_uint160 +{ +public: + typedef base_uint160 basetype; + + uint160() + { + zero(); + } + + uint160(const basetype& b) + { + *this = b; + } + + uint160& operator=(const basetype& b) + { + for (int i = 0; i < WIDTH; i++) + pn[i] = b.pn[i]; + + return *this; + } + + uint160(uint64 b) + { + *this = b; + } + + uint160& operator=(uint64 uHost) + { + zero(); + + // Put in least significant bits. + ((uint64_t *) end())[-1] = htobe64(uHost); + + return *this; + } + + explicit uint160(const std::string& str) + { + SetHex(str); + } + + explicit uint160(const std::vector& vch) + { + if (vch.size() == sizeof(pn)) + memcpy(pn, &vch[0], sizeof(pn)); + else + zero(); + } + + base_uint256 to256() const + { + uint256 m; + memcpy(m.begin(), begin(), size()); + return m; + } + +}; + +inline bool operator==(const uint160& a, uint64 b) { return (base_uint160)a == b; } +inline bool operator!=(const uint160& a, uint64 b) { return (base_uint160)a != b; } + +inline const uint160 operator^(const base_uint160& a, const base_uint160& b) { return uint160(a) ^= b; } +inline const uint160 operator&(const base_uint160& a, const base_uint160& b) { return uint160(a) &= b; } +inline const uint160 operator|(const base_uint160& a, const base_uint160& b) { return uint160(a) |= b; } + +inline bool operator==(const base_uint160& a, const uint160& b) { return (base_uint160)a == (base_uint160)b; } +inline bool operator!=(const base_uint160& a, const uint160& b) { return (base_uint160)a != (base_uint160)b; } +inline const uint160 operator^(const base_uint160& a, const uint160& b) { return (base_uint160)a ^ (base_uint160)b; } +inline const uint160 operator&(const base_uint160& a, const uint160& b) { return (base_uint160)a & (base_uint160)b; } +inline const uint160 operator|(const base_uint160& a, const uint160& b) { return (base_uint160)a | (base_uint160)b; } + +inline bool operator==(const uint160& a, const base_uint160& b) { return (base_uint160)a == (base_uint160)b; } +inline bool operator!=(const uint160& a, const base_uint160& b) { return (base_uint160)a != (base_uint160)b; } +inline const uint160 operator^(const uint160& a, const base_uint160& b) { return (base_uint160)a ^ (base_uint160)b; } +inline const uint160 operator&(const uint160& a, const base_uint160& b) { return (base_uint160)a & (base_uint160)b; } +inline const uint160 operator|(const uint160& a, const base_uint160& b) { return (base_uint160)a | (base_uint160)b; } +inline bool operator==(const uint160& a, const uint160& b) { return (base_uint160)a == (base_uint160)b; } +inline bool operator!=(const uint160& a, const uint160& b) { return (base_uint160)a != (base_uint160)b; } +inline const uint160 operator^(const uint160& a, const uint160& b) { return (base_uint160)a ^ (base_uint160)b; } +inline const uint160 operator&(const uint160& a, const uint160& b) { return (base_uint160)a & (base_uint160)b; } +inline const uint160 operator|(const uint160& a, const uint160& b) { return (base_uint160)a | (base_uint160)b; } + +extern std::size_t hash_value(const uint160&); + +inline const std::string strHex(const uint160& ui) +{ + return strHex(ui.begin(), ui.size()); +} + + #endif // vim:ts=4 diff --git a/test/config.js b/test/config.js index 6b320f248..0610373db 100644 --- a/test/config.js +++ b/test/config.js @@ -9,15 +9,17 @@ 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" + 'rpc_ip' : "0.0.0.0", + 'rpc_port' : 5005, + 'websocket_ip' : "127.0.0.1", + 'websocket_port' : 6005, + 'validation_seed' : "shhDFVsmS2GSu5vUyZSPXYfj1r79h", + 'validators' : "n9L8LZZCwsdXzKUN9zoVxs4YznYXZ9hEhsQZY7aVpxtFaSceiyDZ beta" } }; // vim:ts=4 diff --git a/test/server.js b/test/server.js index 0bd0f582c..9e20569a5 100644 --- a/test/server.js +++ b/test/server.js @@ -1,4 +1,7 @@ // Manage test servers +// +// YYY Would be nice to be able to hide server output. +// // Provide servers // diff --git a/test/standalone-test.js b/test/standalone-test.js index d707baeca..6a18592a4 100644 --- a/test/standalone-test.js +++ b/test/standalone-test.js @@ -1,11 +1,16 @@ -// console.log("standalone-test.js>"); - var fs = require("fs"); var buster = require("buster"); var server = require("./server.js"); +var remote = require("../js/remote.js"); +var config = require("./config.js"); -buster.testCase("Check standalone server startup", { +// How long to wait for server to start. +var serverDelay = 1500; + +buster.testRunner.timeout = 5000; + +buster.testCase("Standalone server startup", { "server start and stop": function(done) { server.start("alpha", function(e) { @@ -18,4 +23,166 @@ buster.testCase("Check standalone server startup", { } }); +buster.testCase("WebSocket connection", { + 'setUp' : + function(done) { + server.start("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"); + + alpha.connect(function(stat) { + buster.assert(1 == stat); // OPEN + + 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); + + 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_current' : + function(done) { + alpha.ledger_current(function (r) { + console.log(r); + + buster.assert.equals(r.ledger_index, 3); + done(); + }); + }, + + '// ledger_closed' : + function(done) { + alpha.ledger_closed(function (r) { + console.log("result: %s", JSON.stringify(r)); + + buster.assert.equals(r.ledger_index, 2); + done(); + }); + }, + + 'account_root success' : + 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' : 'iHb9CJAWyB4ij91VRWn96DkukG4bwdtyTh' + } , function (r) { + // console.log("account_root: %s", JSON.stringify(r)); + + buster.assert('node' in r); + done(); + }); + }); + }, + + 'account_root malformedAddress' : + 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' : '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(); + }); + }); + }, + + '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(); + }); + }); + }, + +}); + // vim:ts=4 diff --git a/websocketpp b/websocketpp index f78b9df4a..dd9899c34 160000 --- a/websocketpp +++ b/websocketpp @@ -1 +1 @@ -Subproject commit f78b9df4adbc354f5fdf8c2c8b9e76549f977cb8 +Subproject commit dd9899c34bb1f86caf486735b136a5460b4760db