From 4a49fefdd900bf203e57ced2812eec5d2efd8c53 Mon Sep 17 00:00:00 2001 From: Nik Bougalis Date: Thu, 4 Dec 2014 03:16:41 -0800 Subject: [PATCH] Various cleanups: * Replace SYSTEM_NAME and other macros with C++ constructs * Remove RIPPLE_ARRAYSIZE and use std::extent or ranged for loops * Remove old-style, unused offer crossing unit test * Make STAmount::saFromRate free and remove default argument --- Builds/VisualStudio2013/RippleD.vcxproj | 5 - .../VisualStudio2013/RippleD.vcxproj.filters | 9 - src/ripple/app/book/impl/Taker.cpp | 4 +- src/ripple/app/ledger/LedgerEntrySet.cpp | 6 +- src/ripple/app/main/Main.cpp | 2 +- src/ripple/app/misc/ProofOfWork.cpp | 58 +- src/ripple/app/node/SqliteFactory.cpp | 8 +- src/ripple/app/paths/RippleCalc.cpp | 10 +- .../app/paths/cursor/ReverseLiquidity.cpp | 2 +- .../cursor/ReverseLiquidityForAccount.cpp | 2 +- src/ripple/app/peers/UniqueNodeList.cpp | 68 +- src/ripple/app/websocket/WSServerHandler.h | 7 +- src/ripple/basics/ArraySize.h | 30 - src/ripple/basics/tests/cross_offer.test.cpp | 820 ------------------ src/ripple/core/SystemParameters.h | 69 +- src/ripple/core/impl/Config.cpp | 4 +- src/ripple/net/impl/RPCCall.cpp | 64 +- src/ripple/protocol/STAmount.h | 10 +- src/ripple/protocol/TER.h | 14 +- src/ripple/protocol/UintTypes.h | 2 - src/ripple/protocol/impl/STAmount.cpp | 7 +- src/ripple/protocol/impl/TER.cpp | 242 +++--- src/ripple/protocol/impl/UintTypes.cpp | 5 +- src/ripple/rpc/handlers/Stop.cpp | 2 +- src/ripple/rpc/impl/JsonWriter.cpp | 1 - src/ripple/server/impl/JSONRPCUtil.cpp | 4 +- src/ripple/unity/basics.cpp | 2 - 27 files changed, 305 insertions(+), 1152 deletions(-) delete mode 100644 src/ripple/basics/ArraySize.h delete mode 100644 src/ripple/basics/tests/cross_offer.test.cpp diff --git a/Builds/VisualStudio2013/RippleD.vcxproj b/Builds/VisualStudio2013/RippleD.vcxproj index 438586dd3b..ba0f8f79f3 100644 --- a/Builds/VisualStudio2013/RippleD.vcxproj +++ b/Builds/VisualStudio2013/RippleD.vcxproj @@ -2116,8 +2116,6 @@ - - @@ -2198,9 +2196,6 @@ - - True - diff --git a/Builds/VisualStudio2013/RippleD.vcxproj.filters b/Builds/VisualStudio2013/RippleD.vcxproj.filters index 9b636aa708..6d409e3bb7 100644 --- a/Builds/VisualStudio2013/RippleD.vcxproj.filters +++ b/Builds/VisualStudio2013/RippleD.vcxproj.filters @@ -337,9 +337,6 @@ {1B5E3484-E132-ADEA-8A38-01B0F4ABAC58} - - {B1F0C3D5-71C4-3ABF-E292-F147387D07CB} - {235DCF23-2CF8-4F03-1A54-C159823A7E8D} @@ -3048,9 +3045,6 @@ ripple\app\websocket - - ripple\basics - ripple\basics @@ -3150,9 +3144,6 @@ ripple\basics - - ripple\basics\tests - ripple\basics diff --git a/src/ripple/app/book/impl/Taker.cpp b/src/ripple/app/book/impl/Taker.cpp index 8837cf7aab..9b510af4e7 100644 --- a/src/ripple/app/book/impl/Taker.cpp +++ b/src/ripple/app/book/impl/Taker.cpp @@ -92,7 +92,7 @@ Taker::flow (Amounts amount, Offer const& offer, Account const& taker) } else { - Amount const taker_charge (Amount::saFromRate (taker_charge_rate)); + Amount const taker_charge (amountFromRate (taker_charge_rate)); amount = offer.quality ().ceil_in (amount, divide (taker_funds, taker_charge)); } @@ -116,7 +116,7 @@ Taker::flow (Amounts amount, Offer const& offer, Account const& taker) } else { - Amount const owner_charge (Amount::saFromRate (owner_charge_rate)); + Amount const owner_charge (amountFromRate (owner_charge_rate)); owner_amount = offer.quality ().ceil_out (owner_amount, divide (owner_funds, owner_charge)); } diff --git a/src/ripple/app/ledger/LedgerEntrySet.cpp b/src/ripple/app/ledger/LedgerEntrySet.cpp index f0f5e761d6..cc1d816755 100644 --- a/src/ripple/app/ledger/LedgerEntrySet.cpp +++ b/src/ripple/app/ledger/LedgerEntrySet.cpp @@ -1276,12 +1276,8 @@ STAmount LedgerEntrySet::rippleTransferFee ( if (QUALITY_ONE != uTransitRate) { - // NIKB use STAmount::saFromRate - STAmount saTransitRate ( - noIssue(), static_cast (uTransitRate), -9); - STAmount saTransferTotal = multiply ( - saAmount, saTransitRate, saAmount.issue ()); + saAmount, amountFromRate (uTransitRate), saAmount.issue ()); STAmount saTransferFee = saTransferTotal - saAmount; WriteLog (lsDEBUG, LedgerEntrySet) << "rippleTransferFee:" << diff --git a/src/ripple/app/main/Main.cpp b/src/ripple/app/main/Main.cpp index a017f40c2a..a82aff5dc7 100644 --- a/src/ripple/app/main/Main.cpp +++ b/src/ripple/app/main/Main.cpp @@ -84,7 +84,7 @@ void startServer () void printHelp (const po::options_description& desc) { std::cerr - << SYSTEM_NAME "d [options] \n" + << systemName () << "d [options] \n" << desc << std::endl << "Commands: \n" " account_info ||| [] [strict]\n" diff --git a/src/ripple/app/misc/ProofOfWork.cpp b/src/ripple/app/misc/ProofOfWork.cpp index dc368c362e..7bcf32c01a 100644 --- a/src/ripple/app/misc/ProofOfWork.cpp +++ b/src/ripple/app/misc/ProofOfWork.cpp @@ -17,9 +17,9 @@ */ //============================================================================== -#include #include #include +#include namespace ripple { @@ -154,8 +154,15 @@ bool ProofOfWork::checkSolution (uint256 const& solution) const bool ProofOfWork::validateToken (std::string const& strToken) { - static boost::regex reToken ("[[:xdigit:]]{64}-[[:xdigit:]]{64}-[[:digit:]]+-[[:digit:]]+-[[:xdigit:]]{64}"); - boost::smatch smMatch; + static boost::regex const reToken ( + "[[:xdigit:]]{64}-" + "[[:xdigit:]]{64}-" + "[[:digit:]]+-" + "[[:digit:]]+-" + "[[:xdigit:]]{64}", + boost::regex_constants::optimize); + + boost::smatch smMatch; return boost::regex_match (strToken, smMatch, reToken); } @@ -164,34 +171,35 @@ bool ProofOfWork::validateToken (std::string const& strToken) bool ProofOfWork::calcResultInfo (PowResult powCode, std::string& strToken, std::string& strHuman) { - static struct + struct PowResultInfo { - PowResult powCode; - const char* cpToken; - const char* cpHuman; - } powResultInfoA[] = - { - { powREUSED, "powREUSED", "Proof-of-work has already been used." }, - { powBADNONCE, "powBADNONCE", "The solution does not meet the required difficulty." }, - { powEXPIRED, "powEXPIRED", "Token is expired." }, - { powCORRUPT, "powCORRUPT", "Invalid token." }, - { powTOOEASY, "powTOOEASY", "Difficulty has increased since token was issued." }, - - { powOK, "powOK", "Valid proof-of-work." }, + PowResult code; + char const* token; + char const* text; }; - int iIndex = RIPPLE_ARRAYSIZE (powResultInfoA); - - while (iIndex-- && powResultInfoA[iIndex].powCode != powCode) - ; - - if (iIndex >= 0) + static + PowResultInfo const results[] = { - strToken = powResultInfoA[iIndex].cpToken; - strHuman = powResultInfoA[iIndex].cpHuman; + { powOK, "powOK", "Valid proof-of-work." }, + { powREUSED, "powREUSED", "Proof-of-work has already been used." }, + { powBADNONCE, "powBADNONCE", "The solution does not meet the required difficulty." }, + { powEXPIRED, "powEXPIRED", "Token is expired." }, + { powCORRUPT, "powCORRUPT", "Invalid token." }, + { powTOOEASY, "powTOOEASY", "Difficulty has increased since token was issued." }, + }; + + for (auto const& result : results) + { + if (powCode == result.code) + { + strToken = result.token; + strHuman = result.text; + return true; + } } - return iIndex >= 0; + return false; } } // ripple diff --git a/src/ripple/app/node/SqliteFactory.cpp b/src/ripple/app/node/SqliteFactory.cpp index 36a07e661a..3568297f45 100644 --- a/src/ripple/app/node/SqliteFactory.cpp +++ b/src/ripple/app/node/SqliteFactory.cpp @@ -17,8 +17,8 @@ */ //============================================================================== -#include #include +#include namespace ripple { @@ -44,8 +44,6 @@ static const char* s_nodeStoreDBInit [] = "END TRANSACTION;" }; -static int s_nodeStoreDBCount = RIPPLE_ARRAYSIZE (s_nodeStoreDBInit); - //------------------------------------------------------------------------------ class SqliteBackend : public NodeStore::Backend @@ -53,8 +51,8 @@ class SqliteBackend : public NodeStore::Backend public: explicit SqliteBackend (std::string const& path, int hashnode_cache_size) : m_name (path) - , m_db (new DatabaseCon(setup_DatabaseCon (getConfig()), - path, s_nodeStoreDBInit, s_nodeStoreDBCount)) + , m_db (new DatabaseCon(setup_DatabaseCon (getConfig()), path, + s_nodeStoreDBInit, std::extent::value)) { std::string s ("PRAGMA cache_size=-"); s += std::to_string (hashnode_cache_size); diff --git a/src/ripple/app/paths/RippleCalc.cpp b/src/ripple/app/paths/RippleCalc.cpp index a270a7303f..44f09a4e34 100644 --- a/src/ripple/app/paths/RippleCalc.cpp +++ b/src/ripple/app/paths/RippleCalc.cpp @@ -230,7 +230,7 @@ TER RippleCalc::rippleCalculate () << "rippleCalc: AFTER:" << " mIndex=" << pathState->index() << " uQuality=" << pathState->quality() - << " rate=" << STAmount::saFromRate (pathState->quality()); + << " rate=" << amountFromRate (pathState->quality()); if (!pathState->quality()) { @@ -257,7 +257,7 @@ TER RippleCalc::rippleCalculate () lsDEBUG, RippleCalc) << "rippleCalc: better:" << " uQuality=" - << STAmount::saFromRate (pathState->quality()) + << amountFromRate (pathState->quality()) << " inPass()=" << pathState->inPass() << " saOutPass=" << pathState->outPass(); @@ -278,7 +278,7 @@ TER RippleCalc::rippleCalculate () << " mIndex=" << pathState->index() << " uQuality=" << pathState->quality() << " rate=" - << STAmount::saFromRate (pathState->quality()) + << amountFromRate (pathState->quality()) << " inPass()=" << pathState->inPass() << " saOutPass=" << pathState->outPass(); @@ -306,7 +306,7 @@ TER RippleCalc::rippleCalculate () << "rippleCalc: " << "Summary: " << pathState->index() << " rate: " - << STAmount::saFromRate (pathState->quality()) + << amountFromRate (pathState->quality()) << " quality:" << pathState->quality() << " best: " << (iBest == pathState->index ()); } @@ -320,7 +320,7 @@ TER RippleCalc::rippleCalculate () WriteLog (lsDEBUG, RippleCalc) << "rippleCalc: best:" << " uQuality=" - << STAmount::saFromRate (pathState->quality()) + << amountFromRate (pathState->quality()) << " inPass()=" << pathState->inPass() << " saOutPass=" << pathState->outPass(); diff --git a/src/ripple/app/paths/cursor/ReverseLiquidity.cpp b/src/ripple/app/paths/cursor/ReverseLiquidity.cpp index 7cf93c5d41..73fa506c00 100644 --- a/src/ripple/app/paths/cursor/ReverseLiquidity.cpp +++ b/src/ripple/app/paths/cursor/ReverseLiquidity.cpp @@ -52,7 +52,7 @@ TER PathCursor::reverseLiquidity () const // a fee when third parties transfer that account's own issuances. // node.transferRate_ caches the output transfer rate for this node. - node().transferRate_ = STAmount::saFromRate ( + node().transferRate_ = amountFromRate ( rippleTransferRate (ledger(), node().issue_.account)); if (node().isAccount ()) diff --git a/src/ripple/app/paths/cursor/ReverseLiquidityForAccount.cpp b/src/ripple/app/paths/cursor/ReverseLiquidityForAccount.cpp index c48c45cf1d..d458980d17 100644 --- a/src/ripple/app/paths/cursor/ReverseLiquidityForAccount.cpp +++ b/src/ripple/app/paths/cursor/ReverseLiquidityForAccount.cpp @@ -205,7 +205,7 @@ TER PathCursor::reverseLiquidityForAccount () const << " (available) previousNode.saRevRedeem=" << previousNode().saRevRedeem << " uRateMax=" - << STAmount::saFromRate (uRateMax).getText (); + << amountFromRate (uRateMax).getText (); } else { diff --git a/src/ripple/app/peers/UniqueNodeList.cpp b/src/ripple/app/peers/UniqueNodeList.cpp index 9084261c5a..2ac3901c3d 100644 --- a/src/ripple/app/peers/UniqueNodeList.cpp +++ b/src/ripple/app/peers/UniqueNodeList.cpp @@ -39,8 +39,6 @@ namespace ripple { #define NODE_FETCH_JOBS 10 #define NODE_FETCH_SECONDS 10 #define NODE_FILE_BYTES_MAX (50<<10) // 50k -#define NODE_FILE_NAME SYSTEM_NAME ".txt" -#define NODE_FILE_PATH "/" NODE_FILE_NAME // Wait for validation information to be stable before scoring. // #define SCORE_DELAY_SECONDS 20 @@ -118,6 +116,8 @@ public: , mFetchActive (0) , m_fetchTimer (this) { + node_file_name_ = std::string (systemName ()) + ".txt"; + node_file_path_ = "/" + node_file_name_; } //-------------------------------------------------------------------------- @@ -1161,19 +1161,19 @@ private: if (!bReject) { - IniFileSections secSite = parseIniFile (strSiteFile, true); - bool bGood = !err; + IniFileSections secSite = parseIniFile (strSiteFile, true); + bool bGood = !err; if (bGood) { - WriteLog (lsTRACE, UniqueNodeList) << boost::format ("Validator: '%s' received " NODE_FILE_NAME ".") % strDomain; + WriteLog (lsTRACE, UniqueNodeList) << strDomain + << ": retrieved configuration"; } else { - WriteLog (lsTRACE, UniqueNodeList) - << boost::format ("Validator: '%s' unable to retrieve " NODE_FILE_NAME ": %s") - % strDomain - % err.message (); + WriteLog (lsTRACE, UniqueNodeList) << strDomain + << ": unable to retrieve configuration: " + << err.message (); } // @@ -1185,19 +1185,17 @@ private: { bGood = false; - WriteLog (lsTRACE, UniqueNodeList) - << boost::format ("Validator: '%s' bad " NODE_FILE_NAME " missing single entry for " SECTION_DOMAIN ".") - % strDomain; + WriteLog (lsTRACE, UniqueNodeList) << strDomain + << ": " << SECTION_DOMAIN + << "entry missing."; } if (bGood && strSite != strDomain) { bGood = false; - WriteLog (lsTRACE, UniqueNodeList) - << boost::format ("Validator: '%s' bad " NODE_FILE_NAME " " SECTION_DOMAIN " does not match: %s") - % strDomain - % strSite; + WriteLog (lsTRACE, UniqueNodeList) << strDomain + << ": " << SECTION_DOMAIN << " does not match " << strSite; } // @@ -1210,9 +1208,8 @@ private: // Bad [validation_public_key] IniFileSections. bGood = false; - WriteLog (lsTRACE, UniqueNodeList) - << boost::format ("Validator: '%s' bad " NODE_FILE_NAME " " SECTION_PUBLIC_KEY " does not have single entry.") - % strDomain; + WriteLog (lsTRACE, UniqueNodeList) << strDomain + << ": " << SECTION_PUBLIC_KEY << " entry missing."; } RippleAddress naNodePublic; @@ -1222,16 +1219,13 @@ private: // Bad public key. bGood = false; - WriteLog (lsTRACE, UniqueNodeList) - << boost::format ("Validator: '%s' bad " NODE_FILE_NAME " " SECTION_PUBLIC_KEY " is bad: ") - % strDomain - % strNodePublicKey; + WriteLog (lsTRACE, UniqueNodeList) << strDomain + << ": " << SECTION_PUBLIC_KEY << " is not a public key: " + << strNodePublicKey; } if (bGood) { - // WriteLog (lsTRACE, UniqueNodeList) << boost::format("naNodePublic: '%s'") % naNodePublic.humanNodePublic(); - seedDomain sdCurrent; bool bFound = getSeedDomains (strDomain, sdCurrent); @@ -1255,12 +1249,14 @@ private: if (bChangedB) { - WriteLog (lsTRACE, UniqueNodeList) << boost::format ("Validator: '%s' processing new " NODE_FILE_NAME ".") % strDomain; + WriteLog (lsTRACE, UniqueNodeList) << strDomain + << ": processing new " << node_file_name_ << "."; processFile (strDomain, naNodePublic, secSite); } else { - WriteLog (lsTRACE, UniqueNodeList) << boost::format ("Validator: '%s' no change for " NODE_FILE_NAME ".") % strDomain; + WriteLog (lsTRACE, UniqueNodeList) << strDomain + << ": no change in " << node_file_name_ << "."; fetchFinish (); } } @@ -1361,7 +1357,8 @@ private: setSeedDomains (sdCurrent, false); - WriteLog (lsTRACE, UniqueNodeList) << "Validator: '" << strDomain << "' fetching " NODE_FILE_NAME "."; + WriteLog (lsTRACE, UniqueNodeList) << strDomain + << " fetching " << node_file_name_ << "."; fetchProcess (strDomain); // Go get it. @@ -1401,14 +1398,15 @@ private: // Get the ripple.txt and process it. void fetchProcess (std::string strDomain) { - WriteLog (lsTRACE, UniqueNodeList) << "Fetching '" NODE_FILE_NAME "' from '" << strDomain << "'."; + WriteLog (lsTRACE, UniqueNodeList) << strDomain + << ": fetching " << node_file_name_ << "."; std::deque deqSites; // Order searching from most specifically for purpose to generic. // This order allows the client to take the most burden rather than the servers. - deqSites.push_back (str (boost::format (SYSTEM_NAME ".%s") % strDomain)); - deqSites.push_back (str (boost::format ("www.%s") % strDomain)); + deqSites.push_back (systemName () + strDomain); + deqSites.push_back ("www." + strDomain); deqSites.push_back (strDomain); HTTPClient::get ( @@ -1416,7 +1414,7 @@ private: getApp().getIOService (), deqSites, 443, - NODE_FILE_PATH, + node_file_path_, NODE_FILE_BYTES_MAX, boost::posix_time::seconds (NODE_FETCH_SECONDS), std::bind (&UniqueNodeListImp::responseFetch, this, strDomain, @@ -1734,7 +1732,8 @@ private: // // Process Validators // - processValidators (strDomain, NODE_FILE_NAME, naNodePublic, vsReferral, getIniFileSection (secSite, SECTION_VALIDATORS)); + processValidators (strDomain, node_file_name_, naNodePublic, + vsReferral, getIniFileSection (secSite, SECTION_VALIDATORS)); // // Process ips @@ -2047,6 +2046,9 @@ private: beast::DeadlineTimer m_fetchTimer; // Timer to start fetching. std::map m_clusterNodes; + + std::string node_file_name_; + std::string node_file_path_; }; //------------------------------------------------------------------------------ diff --git a/src/ripple/app/websocket/WSServerHandler.h b/src/ripple/app/websocket/WSServerHandler.h index 3f40451227..43591fde38 100644 --- a/src/ripple/app/websocket/WSServerHandler.h +++ b/src/ripple/app/websocket/WSServerHandler.h @@ -461,10 +461,9 @@ public: } cpClient->set_body ( - "" SYSTEM_NAME " Test" - "

" SYSTEM_NAME " Test

" - "

This page shows that http(s) connectivity is working." - "

"); + "" + systemName () + + " Test" + "

" + systemName () + + " Test

This page shows http(s) connectivity is working.

"); return true; } }; diff --git a/src/ripple/basics/ArraySize.h b/src/ripple/basics/ArraySize.h deleted file mode 100644 index 49d07cac34..0000000000 --- a/src/ripple/basics/ArraySize.h +++ /dev/null @@ -1,30 +0,0 @@ -//------------------------------------------------------------------------------ -/* - This file is part of rippled: https://github.com/ripple/rippled - Copyright (c) 2012, 2013 Ripple Labs Inc. - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ -//============================================================================== - -#ifndef RIPPLE_BASICS_ARRAYSIZE_H_INCLUDED -#define RIPPLE_BASICS_ARRAYSIZE_H_INCLUDED - -namespace ripple { - -// DEPRECATED -#define RIPPLE_ARRAYSIZE(x) (sizeof(x) / sizeof((x)[0])) - -} // ripple - -#endif diff --git a/src/ripple/basics/tests/cross_offer.test.cpp b/src/ripple/basics/tests/cross_offer.test.cpp deleted file mode 100644 index 58d5464425..0000000000 --- a/src/ripple/basics/tests/cross_offer.test.cpp +++ /dev/null @@ -1,820 +0,0 @@ -//------------------------------------------------------------------------------ -/* - This file is part of rippled: https://github.com/ripple/rippled - Copyright (c) 2012, 2013 Ripple Labs Inc. - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ -//============================================================================== - -#include - -#include -#include -#include -#include -#include -#include // -#include -#include - -namespace ripple { -namespace core { - -/** Represents both a quality and amounts of currencies for trade. - - Quality is the ratio of output currency to input currency, where - higher means better for the offer taker. The first element of - the pair is the amount of currency available for input into - the offer. The second element of the pair is the amount of currency - that comes out if the full amount of the input currency is provided. - This pair also represents a fraction, for example for specifying a - minimum quality. - - Offer requirements: - - `X` is the type `Offer` - `a`, `b` are values of type `X` - - `X::amount_type` - The return type of `in` and `out` - - `X a;` - Constructs an uninitialized offer - - `a.in();` - - `a.out(); -*/ - -/** Returns `true` if the offer is consumed. */ -template -bool -is_offer_consumed (Offer const& offer) noexcept -{ - assert ((offer.in() != 0 && offer.out() != 0) || - (offer.in() == 0 && offer.out() == 0)); - return offer.in() == 0 || offer.out() == 0; -} - -//------------------------------------------------------------------------------ - -template -struct AmountTraits -{ - /** Returns `true` if `lhs` is of lower quality than `rhs`. */ - template - static - bool - less (Offer const& lhs, Offer const& rhs) noexcept - { - assert (! is_offer_consumed (lhs)); - assert (! is_offer_consumed (rhs)); - assert (lhs.out() != 0); - assert (rhs.out() != 0); - return (lhs.out() / lhs.in()) < (rhs.out() / rhs.in()); - } - - /** Calculates the result of multiplying amount by the implied ratio. */ - template - static - typename Offer::amount_type - multiply (typename Offer::amount_type const& amount, Offer const& rate) - { - // Avoid math when result is exact - if (amount == rate.in()) - return rate.out(); - typename Offer::amount_type const result ( - amount * (rate.out() / rate.in())); - if (result > rate.out()) - return rate.out(); - return result; - } - - template - static - Offer - inverse (Offer const& value) noexcept - { - return Offer (value.out(), value.in()); - } -}; - -/** Returns the offer that would result if the input amount is applied. */ -template -Offer -consume_offer ( - typename Offer::amount_type const& input, - Offer offer) -{ - using Amount = typename Offer::amount_type; - // We need to calculate the most that we can take: - Amount const input_used (std::min (input, offer.in())); - Amount const output (AmountTraits::multiply (input_used, offer)); - offer.in() -= input_used; - offer.out() -= output; - return offer; -} - -/** Fills an order amount in an order book. - - @return The resulting amount of currency in and out. -*/ -template -typename std::iterator_traits::value_type -cross_offer_in ( - typename std::iterator_traits::value_type::amount_type const& in, - typename std::iterator_traits::value_type const& minimum_quality, - BookIter first, BookIter last) -{ - using Amount = - typename std::iterator_traits::value_type::amount_type; - using Offer = - typename std::iterator_traits::value_type; - Offer result {0, 0}; - Amount remain (in); - for (auto iter (first); (result.in() < in) && (iter != last); ++iter) - { - Offer const offer (*iter); - if (AmountTraits::less (offer, minimum_quality)) - break; - Offer const offer_out (consume_offer (remain, offer)); - result.in() += offer.in() - offer_out.in(); - result.out() += offer.out() - offer_out.out(); - *iter = offer_out; - } - return result; -} - -//------------------------------------------------------------------------------ - -/** Returns the composite A->C from offers A->B and B->C, equal liquidity. */ -template -Offer -make_bridged_offer (Offer const& leg1, Offer const& leg2) -{ - using Amount = typename Offer::amount_type; - - // Skip math if both legs can be fully consumed - if (leg1.out() == leg2.in()) - return Offer (leg1.in(), leg2.out()); - - // If leg2 has less liquidity, scale down by leg2 - if (leg1.out() > leg2.in()) - return Offer ( - AmountTraits::multiply (leg2.in(), - AmountTraits::inverse (leg1)), - leg2.out()); - - // leg1 has less liquidity - return Offer (leg1.in(), - AmountTraits::multiply (leg1.out(), leg2)); -} - -namespace detail { - -/** Presents a set of order books as a single bridged order book. */ -template -class MultiBookIterator -{ -private: - using Amount = - typename std::iterator_traits::value_type::amount_type; - - using Offer = - typename std::iterator_traits::value_type; - - typedef std::is_const < - typename std::iterator_traits::reference - > IsConst; - - struct forward_iterator_base_tag - : std::output_iterator_tag - , std::forward_iterator_tag - { - forward_iterator_base_tag() - { - } - }; - - struct forward_const_iterator_base_tag - : std::forward_iterator_tag - { - forward_const_iterator_base_tag() - { - } - }; - - template - friend class MultiBookIterator; - - BookIter m_direct; - BookIter m_direct_end; - BookIter m_leg1; - BookIter m_leg1_end; - BookIter m_leg2; - BookIter m_leg2_end; - bool m_bridged; - Offer m_offer; - - class Proxy : public Offer - { - private: - bool m_bridged; - BookIter m_direct; - BookIter m_leg1; - BookIter m_leg2; - - public: - explicit Proxy (BookIter direct) - : Offer (*direct) - , m_bridged (false) - , m_direct (direct) - { - } - - Proxy (BookIter leg1, BookIter leg2) - : Offer (make_bridged_offer (*leg1, *leg2)) - , m_bridged (true) - , m_leg1 (leg1) - , m_leg2 (leg2) - { - } - - Proxy& - operator= (Offer const& offer) - { - if (m_bridged) - { - Offer const result (consume_offer ( - offer.in(), *m_leg1)); - *m_leg2 = consume_offer ( - m_leg1->in() - result.in(), *m_leg2); - *m_leg1 = result; - } - else - { - *m_direct = offer; - } - ((Offer&)*this) = offer; - return *this; - } - }; - - // Returns true if this iterator has reached the one past the end marker - bool - past_end() const noexcept - { - return - (m_direct == m_direct_end) && - (m_leg1 == m_leg1_end || m_leg2 == m_leg2_end); - } - - void - throw_if_past() - { - if (past_end()) - throw std::out_of_range ("invalid iterator dereferenced"); - } - - // Returns true if the iterators are both equal, or both past the end - template - static - bool - iter_eq (Iter1 iter1, Iter1 iter1_end, - Iter2 iter2, Iter2 iter2_end) noexcept - { - if (iter1 == iter1_end) - return iter2 == iter2_end; - if (iter2 == iter2_end) - return false; - return iter1 == iter2; - } - - // Stores the best offer (if any) in m_offer - void - calc_offer() - { - if (past_end()) - return; - - // FIXME rewrite this - having 3 nested if's is overkill... - if ((m_leg1 != m_leg1_end) && (m_leg2 != m_leg2_end)) - { - Offer const bridged ( - make_bridged_offer (*m_leg1, *m_leg2)); - - if (m_direct != m_direct_end) - { - if (AmountTraits::less (*m_direct, bridged)) - { - m_bridged = true; - m_offer = bridged; - } - else - { - m_bridged = false; - m_offer = *m_direct; - } - } - else - { - m_bridged = true; - m_offer = bridged; - } - } - else - { - m_bridged = false; - m_offer = *m_direct; - } - } - -public: - typedef std::ptrdiff_t difference_type; - typedef typename std::iterator_traits < - BookIter>::value_type value_type; - typedef value_type* pointer; - typedef value_type& reference; - typedef std::conditional_t < - std::is_const >::value, - forward_const_iterator_base_tag, - forward_iterator_base_tag> iterator_category; - - MultiBookIterator () = default; - - template < - class OtherBookIter, - class = std::enable_if_t < - std::is_same ::value - > - > - MultiBookIterator (MultiBookIterator const& other) - : m_direct (other.m_direct) - , m_direct_end (other.m_direct_end) - , m_leg1 (other.m_leg1) - , m_leg1_end (other.m_leg1_end) - , m_leg2 (other.m_leg2) - , m_leg2_end (other.m_leg2_end) - { - } - - template < - class OtherBookIter, - class = std::enable_if_t < - std::is_same ::value - > - > - MultiBookIterator ( - OtherBookIter direct_first, OtherBookIter direct_last, - OtherBookIter leg1_first, OtherBookIter leg1_last, - OtherBookIter leg2_first, OtherBookIter leg2_last) - : m_direct (direct_first) - , m_direct_end (direct_last) - , m_leg1 (leg1_first) - , m_leg1_end (leg1_last) - , m_leg2 (leg2_first) - , m_leg2_end (leg2_last) - { - calc_offer(); - } - - MultiBookIterator& - operator++() - { - throw_if_past (); - - if (m_direct != m_direct_end) - ++m_direct; - if (m_leg1 != m_leg1_end) - ++m_leg1; - if (m_leg2 != m_leg2_end) - ++m_leg2; - calc_offer(); - return *this; - } - - MultiBookIterator - operator++(int) - { - MultiBookIterator prev (*this); - this->operator++(); - return prev; - } - - template - bool - operator== ( - MultiBookIterator const& other) const noexcept - { - if (! iter_eq (m_direct, m_direct_end, - other.m_direct, other.m_direct_end)) - return false; - - if (! iter_eq (m_leg1, m_leg1_end, - other.m_leg1, other.m_leg1_end)) - return false; - - if (! iter_eq (m_leg2, m_leg2_end, - other.m_leg2, other.m_leg2_end)) - return false; - - return true; - } - - Offer const* - operator->() const - { - throw_if_past(); - return &m_offer; - } - - Offer const& - operator*() const - { - throw_if_past(); - return m_offer; - } - -#ifndef _MSC_VER - // This blows up Visual Studio - template < - bool MaybeConst = IsConst::value, - class = std::enable_if_t - > -#endif - Proxy - operator*() - { - static_assert (! IsConst::value, - "invalid call of non-const member function"); - throw_if_past(); - if (m_bridged) - return Proxy (m_leg1, m_leg2); - return Proxy (m_direct); - } -}; - -template -bool -operator!= ( - MultiBookIterator const& lhs, - MultiBookIterator const& rhs) noexcept -{ - return !(rhs == lhs); -} - -} // detail - -//------------------------------------------------------------------------------ - -// TODO Allow const Book -// -template -class MultiBook -{ -private: - static_assert (! std::is_const ::value, - "Book cannot be const"); - - std::reference_wrapper m_direct; - std::reference_wrapper m_leg1; - std::reference_wrapper m_leg2; - -public: - typedef typename Book::value_type value_type; - typedef typename Book::reference reference; - typedef typename Book::const_reference const_reference; - - typedef detail::MultiBookIterator < - typename Book::iterator> iterator; - - typedef detail::MultiBookIterator < - typename Book::const_iterator> const_iterator; - - typedef typename Book::difference_type difference_type; - typedef typename Book::size_type size_type; - - MultiBook (Book& direct, Book& leg1, Book& leg2) - : m_direct (direct) - , m_leg1 (leg1) - , m_leg2 (leg2) - { - } - - bool - empty() const noexcept - { - return cbegin() == cend(); - } - - // Complexity: linear - size_type - size() const noexcept - { - return std::distance (cbegin(), cend()); - } - - iterator - begin() noexcept - { - return iterator ( - m_direct.get().begin(), m_direct.get().end(), - m_leg1.get().begin(), m_leg1.get().end(), - m_leg2.get().begin(), m_leg2.get().end()); - } - - iterator - end() noexcept - { - return iterator ( - m_direct.get().end(), m_direct.get().end(), - m_leg1.get().end(), m_leg1.get().end(), - m_leg2.get().end(), m_leg2.get().end()); - } - - const_iterator - begin() const noexcept - { - return const_iterator ( - m_direct.get().cbegin(), m_direct.get().cend(), - m_leg1.get().cbegin(), m_leg1.get().cend(), - m_leg2.get().cbegin(), m_leg2.get().cend()); - } - - const_iterator - end() const noexcept - { - return const_iterator ( - m_direct.get().cend(), m_direct.get().cend(), - m_leg1.get().cend(), m_leg1.get().cend(), - m_leg2.get().cend(), m_leg2.get().cend()); - } - - const_iterator - cbegin() const noexcept - { - return const_iterator ( - m_direct.get().cbegin(), m_direct.get().cend(), - m_leg1.get().cbegin(), m_leg1.get().cend(), - m_leg2.get().cbegin(), m_leg2.get().cend()); - } - - const_iterator - cend() const noexcept - { - return const_iterator ( - m_direct.get().cend(), m_direct.get().cend(), - m_leg1.get().cend(), m_leg1.get().cend(), - m_leg2.get().cend(), m_leg2.get().cend()); - } -}; - -//------------------------------------------------------------------------------ - -template -typename std::iterator_traits::value_type -cross_offer_in ( - typename std::iterator_traits< - typename Book::iterator>::value_type::amount_type const& in, - typename std::iterator_traits < - typename Book::iterator>::value_type const& minimum_quality, - Book& book) -{ - return cross_offer_in (in, minimum_quality, book.begin(), book.end()); -} - -template -typename std::iterator_traits::value_type -cross_offer_in ( - typename std::iterator_traits< - typename Book::iterator>::value_type::amount_type const& in, - typename std::iterator_traits::value_type - const& minimum_quality, - Book& direct, Book& leg1, Book& leg2) -{ - MultiBook book (direct, leg1, leg2); - return cross_offer_in (in, minimum_quality, book); -} - -//------------------------------------------------------------------------------ - -class cross_offers_test : public beast::unit_test::suite -{ -public: - template - class OfferType - { - private: - Amount m_in; - Amount m_out; - - public: - typedef Amount amount_type; - - OfferType() = default; - - OfferType (Amount const& in, Amount const& out) noexcept - : m_in (in) - , m_out (out) - { - assert ((m_in != 0 && m_out != 0) || (m_in == 0 && m_out == 0)); - } - - Amount const& - in() const noexcept - { - return m_in; - } - - Amount& - in() noexcept - { - return m_in; - } - - Amount const& - out() const noexcept - { - return m_out; - } - - Amount& - out() noexcept - { - return m_out; - } - }; - - typedef double Amount; - typedef OfferType Offer; - typedef std::vector Book; - - template - OfferType - static make_offer (Amount from, Amount rate) - { - return OfferType (from, from * rate); - } - - template - void - check_iterators (Book& b) - { - using Offer = typename Book::value_type; - // These make sure that expressions are well-formed - std::for_each (b.begin(), b.end(), [](Offer){}); - std::for_each (b.cbegin(), b.cend(), [](Offer){}); - { - Book const& cb (b); - std::for_each (cb.begin(), cb.end(), [](Offer){}); - // Should not compile - //*cb.begin() = Book::value_type(); - expect (cb.begin() == cb.end()); - expect (cb.begin() == cb.cend()); - } - expect (b.cbegin() == b.cend()); - expect (b.begin() == b.cend()); - typename Book::iterator iter; - typename Book::const_iterator citer (iter); - citer = typename Book::iterator(); - } - - void - test_iterators() - { - { - Book b; - check_iterators (b); - } - - { - Book b1, b2, b3; - MultiBook b (b1, b2, b3); - check_iterators (b); - } - } - - void - test_full_cross_auto_direct () - { - testcase ("Autobridge (Full Direct Crossing)"); - - Book a_to_b; - - a_to_b.push_back(make_offer(300., 2.0)); - - Book a_to_x; - - a_to_x.push_back(make_offer(300., 0.5)); - - Book x_to_b; - - x_to_b.push_back(make_offer(150., 0.5)); - - auto const rate = make_offer(50.0, 1.5); - - Offer result = cross_offer_in ( - 50.0, - rate, - a_to_b, a_to_x, x_to_b); - - expect ((result.in() == 50.0) && (result.out() == 100.0), - "Expected { 50.0 : 100.0 }"); - } - - void - test_full_cross_auto_bridge () - { - testcase ("Autobridge (Full Bridge Crossing)"); - - Book a_to_b; - - a_to_b.push_back(make_offer(300.00, 1.0)); - - Book a_to_x; - - a_to_x.push_back(make_offer(300.00, 2.0)); - - Book x_to_b; - - x_to_b.push_back(make_offer(300.00, 1.0)); - - auto const rate = make_offer(50.0, 1.5); - - Offer result = cross_offer_in ( - 50.0, - rate, - a_to_b, a_to_x, x_to_b); - - expect ((result.in() == 50.0) && (result.out() == 100.0), - "Expected { 50.0 : 100.0 }"); - } - - void - test_full_cross_direct () - { - testcase ("Direct (Full Crossing)"); - - Book a_to_b; - - a_to_b.push_back(make_offer(300.00, 2.0)); - - auto const rate = make_offer(50.0, 1.5); - - Offer result = cross_offer_in ( - 50.0, - rate, - a_to_b); - - expect ((result.in() == 50.0) && (result.out() == 100.0), - "Expected { 50.0 : 100.0 }"); - } - - void - test_partial_cross_direct () - { - testcase ("Direct (Partial Crossing)"); - - Book a_to_b; - - a_to_b.push_back(make_offer(25.00, 2.0)); - - auto const rate = make_offer(50.0, 1.5); - - Offer result = cross_offer_in ( - 50.0, - rate, - a_to_b); - - expect ((result.in() == 25.0) && (result.out() == 50.0), - "Expected { 25.0 : 50.0 }"); - } - - void - run() - { - test_iterators(); - - test_full_cross_direct (); - test_full_cross_auto_direct (); - test_full_cross_auto_bridge (); - - test_partial_cross_direct (); - } -}; - -BEAST_DEFINE_TESTSUITE_MANUAL(cross_offers,orderbook_logic,ripple); - -} -} diff --git a/src/ripple/core/SystemParameters.h b/src/ripple/core/SystemParameters.h index 842b2c1617..16340ff8e2 100644 --- a/src/ripple/core/SystemParameters.h +++ b/src/ripple/core/SystemParameters.h @@ -20,50 +20,47 @@ #ifndef RIPPLE_CORE_SYSTEMPARAMETERS_H_INCLUDED #define RIPPLE_CORE_SYSTEMPARAMETERS_H_INCLUDED +#include + namespace ripple { -/** Protocol specific constant globals. */ -// VFALCO NOTE use these from now on instead of the macros! -class RippleSystem +/** Various protocol and system specific constant globals. */ + +/* The name of the system. */ +static inline +std::string const& +systemName () { -public: - static inline char const* getSystemName () - { - return "ripple"; - } + static std::string const name = "ripple"; + return name; +} - static char const* getCurrencyCode () - { - return "XRP"; - } +/** Configure the native currency. */ +static +std::uint64_t const +SYSTEM_CURRENCY_GIFT = 1000; - static char const* getCurrencyCodeRipple () - { - return "XRR"; - } +static +std::uint64_t const +SYSTEM_CURRENCY_USERS = 100000000; - static int getCurrencyPrecision () - { - return 6; - } -}; +static +std::uint64_t const +SYSTEM_CURRENCY_PARTS = 1000000; -// VFALCO TODO I would love to replace these macros with the language -// constructs above. The problem is the way they are used at -// the point of call, i.e. "User-agent:" SYSTEM_NAME -// It will be necessary to rewrite some of them to use string streams. -// -#define SYSTEM_NAME "ripple" -#define SYSTEM_CURRENCY_PRECISION 6 +/** Calculate the amount of native currency created at genesis. */ +static +std::uint64_t const +SYSTEM_CURRENCY_START = SYSTEM_CURRENCY_GIFT * SYSTEM_CURRENCY_USERS * SYSTEM_CURRENCY_PARTS; -// VFALCO TODO Replace with C++11 long long constants -// VFALCO NOTE Apparently these are used elsewhere. Make them constants in the config -// or in the Application -// -#define SYSTEM_CURRENCY_GIFT 1000ull -#define SYSTEM_CURRENCY_USERS 100000000ull -#define SYSTEM_CURRENCY_PARTS 1000000ull // 10^SYSTEM_CURRENCY_PRECISION -#define SYSTEM_CURRENCY_START (SYSTEM_CURRENCY_GIFT*SYSTEM_CURRENCY_USERS*SYSTEM_CURRENCY_PARTS) +/* The currency code for the native currency. */ +static inline +std::string const& +systemCurrencyCode () +{ + static std::string const code = "XRP"; + return code; +} } // ripple diff --git a/src/ripple/core/impl/Config.cpp b/src/ripple/core/impl/Config.cpp index 5874b3a67a..40f37532dd 100644 --- a/src/ripple/core/impl/Config.cpp +++ b/src/ripple/core/impl/Config.cpp @@ -342,9 +342,9 @@ void Config::setup (std::string const& strConf, bool bQuiet) strXdgDataHome = strHome + "/.local/share"; } - CONFIG_DIR = strXdgConfigHome + "/" SYSTEM_NAME; + CONFIG_DIR = strXdgConfigHome + "/" + systemName (); CONFIG_FILE = CONFIG_DIR / strConfFile; - DATA_DIR = strXdgDataHome + "/" SYSTEM_NAME; + DATA_DIR = strXdgDataHome + "/" + systemName (); boost::filesystem::create_directories (CONFIG_DIR, ec); diff --git a/src/ripple/net/impl/RPCCall.cpp b/src/ripple/net/impl/RPCCall.cpp index 0ff31eb00c..611212f203 100644 --- a/src/ripple/net/impl/RPCCall.cpp +++ b/src/ripple/net/impl/RPCCall.cpp @@ -18,13 +18,13 @@ //============================================================================== #include -#include #include #include #include #include #include #include +#include namespace ripple { @@ -61,7 +61,7 @@ std::string createHTTPPost ( s << "POST " << (strPath.empty () ? "/" : strPath) << " HTTP/1.0\r\n" - << "User-Agent: " SYSTEM_NAME "-json-rpc/v1\r\n" + << "User-Agent: " << systemName () << "-json-rpc/v1\r\n" << "Host: " << strHost << "\r\n" << "Content-Type: application/json\r\n" << "Content-Length: " << strMsg.size () << "\r\n" @@ -838,17 +838,25 @@ public: // <-- { method: xyz, params: [... ] } or { error: ..., ... } Json::Value parseCommand (std::string strMethod, Json::Value jvParams, bool allowAnyCommand) { - WriteLog (lsTRACE, RPCParser) << "RPC method:" << strMethod; - WriteLog (lsTRACE, RPCParser) << "RPC params:" << jvParams; + if (ShouldLog (lsTRACE, RPCParser)) + { + WriteLog (lsTRACE, RPCParser) << "RPC method:" << strMethod; + WriteLog (lsTRACE, RPCParser) << "RPC params:" << jvParams; + } struct Command { - const char* pCommand; - parseFuncPtr pfpFunc; - int iMinParams; - int iMaxParams; + const char* name; + parseFuncPtr parse; + int minParams; + int maxParams; }; - static Command commandsA[] = + + // FIXME: replace this with a function-static std::map and the lookup + // code with std::map::find when the problem with magic statics on + // Visual Studio is fixed. + static + Command const commands[] = { // Request-response methods // - Returns an error, or the request. @@ -915,29 +923,33 @@ public: { "unsubscribe", &RPCParser::parseEvented, -1, -1 }, }; - int i = RIPPLE_ARRAYSIZE (commandsA); + auto const count = jvParams.size (); - while (i-- && strMethod != commandsA[i].pCommand) - ; - - if (i < 0) + for (auto const& command : commands) { - if (!allowAnyCommand) - return rpcError (rpcUNKNOWN_COMMAND); + if (strMethod == command.name) + { + if ((command.minParams >= 0 && count < command.minParams) || + (command.maxParams >= 0 && count > command.maxParams)) + { + WriteLog (lsDEBUG, RPCParser) << + "Wrong number of parameters for " << command.name << + " minimum=" << command.minParams << + " maximum=" << command.maxParams << + " actual=" << count; - return parseAsIs (jvParams); - } - else if ((commandsA[i].iMinParams >= 0 && jvParams.size () < commandsA[i].iMinParams) - || (commandsA[i].iMaxParams >= 0 && jvParams.size () > commandsA[i].iMaxParams)) - { - WriteLog (lsWARNING, RPCParser) << "Wrong number of parameters: minimum=" << commandsA[i].iMinParams - << " maximum=" << commandsA[i].iMaxParams - << " actual=" << jvParams.size (); + return rpcError (rpcBAD_SYNTAX); + } - return rpcError (rpcBAD_SYNTAX); + return (this->* (command.parse)) (jvParams); + } } - return (this->* (commandsA[i].pfpFunc)) (jvParams); + // The command could not be found + if (!allowAnyCommand) + return rpcError (rpcUNKNOWN_COMMAND); + + return parseAsIs (jvParams); } }; diff --git a/src/ripple/protocol/STAmount.h b/src/ripple/protocol/STAmount.h index 639716865a..b33069a41c 100644 --- a/src/ripple/protocol/STAmount.h +++ b/src/ripple/protocol/STAmount.h @@ -122,13 +122,6 @@ public: return construct (sit, name); } - static - STAmount - saFromRate (std::uint64_t uRate = 0) - { - return STAmount (noIssue(), uRate, -9, false); - } - static STAmount deserialize (SerializerIterator&); @@ -315,6 +308,9 @@ amountFromQuality (std::uint64_t rate); STAmount amountFromJson (SField::ref name, Json::Value const& v); +STAmount +amountFromRate (std::uint64_t uRate); + bool amountFromJsonNoThrow (STAmount& result, Json::Value const& jvSource); diff --git a/src/ripple/protocol/TER.h b/src/ripple/protocol/TER.h index 306d53d1dd..abacfdd9f2 100644 --- a/src/ripple/protocol/TER.h +++ b/src/ripple/protocol/TER.h @@ -224,9 +224,17 @@ inline bool isTecClaim(TER x) } // VFALCO TODO group these into a shell class along with the defines above. -extern bool transResultInfo (TER terCode, std::string& strToken, std::string& strHuman); -extern std::string transToken (TER terCode); -extern std::string transHuman (TER terCode); +extern +bool +transResultInfo (TER code, std::string& token, std::string& text); + +extern +std::string +transToken (TER code); + +extern +std::string +transHuman (TER code); } // ripple diff --git a/src/ripple/protocol/UintTypes.h b/src/ripple/protocol/UintTypes.h index cd2609defe..b50b56a8e9 100644 --- a/src/ripple/protocol/UintTypes.h +++ b/src/ripple/protocol/UintTypes.h @@ -83,8 +83,6 @@ std::string to_string(Account const&); /** Returns "", "XRP", or three letter ISO code. */ std::string to_string(Currency const& c); -const char* systemCurrencyCode(); - /** Tries to convert a string to a Currency, returns true on success. */ bool to_currency(Currency&, std::string const&); diff --git a/src/ripple/protocol/impl/STAmount.cpp b/src/ripple/protocol/impl/STAmount.cpp index bb5b20c7a5..cbb79ea179 100644 --- a/src/ripple/protocol/impl/STAmount.cpp +++ b/src/ripple/protocol/impl/STAmount.cpp @@ -851,6 +851,12 @@ void STAmount::set (std::int64_t v) //------------------------------------------------------------------------------ +STAmount +amountFromRate (std::uint64_t uRate) +{ + return STAmount (noIssue(), uRate, -9, false); +} + STAmount amountFromQuality (std::uint64_t rate) { @@ -1135,7 +1141,6 @@ operator- (STAmount const& value) // //------------------------------------------------------------------------------ -// NIKB TODO Make Amount::divide skip math if den == QUALITY_ONE STAmount divide (STAmount const& num, STAmount const& den, Issue const& issue) { diff --git a/src/ripple/protocol/impl/TER.cpp b/src/ripple/protocol/impl/TER.cpp index db5e989bee..62cad689e9 100644 --- a/src/ripple/protocol/impl/TER.cpp +++ b/src/ripple/protocol/impl/TER.cpp @@ -17,144 +17,148 @@ */ //============================================================================== -#include #include namespace ripple { -bool transResultInfo (TER terCode, std::string& strToken, std::string& strHuman) +bool transResultInfo (TER code, std::string& token, std::string& text) { - static struct + struct TxResultInfo { - TER terCode; - const char* cpToken; - const char* cpHuman; - } transResultInfoA[] = - { - { tecCLAIM, "tecCLAIM", "Fee claimed. Sequence used. No action." }, - { tecDIR_FULL, "tecDIR_FULL", "Can not add entry to full directory." }, - { tecFAILED_PROCESSING, "tecFAILED_PROCESSING", "Failed to correctly process transaction." }, - { tecINSUF_RESERVE_LINE, "tecINSUF_RESERVE_LINE", "Insufficient reserve to add trust line." }, - { tecINSUF_RESERVE_OFFER, "tecINSUF_RESERVE_OFFER", "Insufficient reserve to create offer." }, - { tecNO_DST, "tecNO_DST", "Destination does not exist. Send XRP to create it." }, - { tecNO_DST_INSUF_XRP, "tecNO_DST_INSUF_XRP", "Destination does not exist. Too little XRP sent to create it." }, - { tecNO_LINE_INSUF_RESERVE, "tecNO_LINE_INSUF_RESERVE", "No such line. Too little reserve to create it." }, - { tecNO_LINE_REDUNDANT, "tecNO_LINE_REDUNDANT", "Can't set non-existent line to default." }, - { tecPATH_DRY, "tecPATH_DRY", "Path could not send partial amount." }, - { tecPATH_PARTIAL, "tecPATH_PARTIAL", "Path could not send full amount." }, - { tecMASTER_DISABLED, "tecMASTER_DISABLED", "Master key is disabled." }, - { tecNO_REGULAR_KEY, "tecNO_REGULAR_KEY", "Regular key is not set." }, - - { tecUNFUNDED, "tecUNFUNDED", "One of _ADD, _OFFER, or _SEND. Deprecated." }, - { tecUNFUNDED_ADD, "tecUNFUNDED_ADD", "Insufficient XRP balance for WalletAdd." }, - { tecUNFUNDED_OFFER, "tecUNFUNDED_OFFER", "Insufficient balance to fund created offer." }, - { tecUNFUNDED_PAYMENT, "tecUNFUNDED_PAYMENT", "Insufficient XRP balance to send." }, - { tecOWNERS, "tecOWNERS", "Non-zero owner count." }, - { tecNO_ISSUER, "tecNO_ISSUER", "Issuer account does not exist." }, - { tecNO_AUTH, "tecNO_AUTH", "Not authorized to hold asset." }, - { tecNO_LINE, "tecNO_LINE", "No such line." }, - { tecINSUFF_FEE, "tecINSUFF_FEE", "Insufficient balance to pay fee." }, - { tecFROZEN, "tecFROZEN", "Asset is frozen." }, - { tecNO_TARGET, "tecNO_TARGET", "Target account does not exist." }, - { tecNO_PERMISSION, "tecNO_PERMISSION", "No permission to perform requested operation." }, - { tecNO_ENTRY, "tecNO_ENTRY", "No matching entry found." }, - { tecINSUFFICIENT_RESERVE,"tecINSUFFICIENT_RESERVE", "Insufficient reserve to complete requested operation." }, - - { tefALREADY, "tefALREADY", "The exact transaction was already in this ledger." }, - { tefBAD_ADD_AUTH, "tefBAD_ADD_AUTH", "Not authorized to add account." }, - { tefBAD_AUTH, "tefBAD_AUTH", "Transaction's public key is not authorized." }, - { tefBAD_LEDGER, "tefBAD_LEDGER", "Ledger in unexpected state." }, - { tefCREATED, "tefCREATED", "Can't add an already created account." }, - { tefDST_TAG_NEEDED, "tefDST_TAG_NEEDED", "Destination tag required." }, - { tefEXCEPTION, "tefEXCEPTION", "Unexpected program state." }, - { tefFAILURE, "tefFAILURE", "Failed to apply." }, - { tefINTERNAL, "tefINTERNAL", "Internal error." }, - { tefMASTER_DISABLED, "tefMASTER_DISABLED", "Master key is disabled." }, - { tefMAX_LEDGER, "tefMAX_LEDGER", "Ledger sequence too high." }, - { tefNO_AUTH_REQUIRED, "tefNO_AUTH_REQUIRED", "Auth is not required." }, - { tefPAST_SEQ, "tefPAST_SEQ", "This sequence number has already past." }, - { tefWRONG_PRIOR, "tefWRONG_PRIOR", "This previous transaction does not match." }, - - { telLOCAL_ERROR, "telLOCAL_ERROR", "Local failure." }, - { telBAD_DOMAIN, "telBAD_DOMAIN", "Domain too long." }, - { telBAD_PATH_COUNT, "telBAD_PATH_COUNT", "Malformed: Too many paths." }, - { telBAD_PUBLIC_KEY, "telBAD_PUBLIC_KEY", "Public key too long." }, - { telFAILED_PROCESSING, "telFAILED_PROCESSING", "Failed to correctly process transaction." }, - { telINSUF_FEE_P, "telINSUF_FEE_P", "Fee insufficient." }, - { telNO_DST_PARTIAL, "telNO_DST_PARTIAL", "Partial payment to create account not allowed." }, - - { temMALFORMED, "temMALFORMED", "Malformed transaction." }, - { temBAD_AMOUNT, "temBAD_AMOUNT", "Can only send positive amounts." }, - { temBAD_AUTH_MASTER, "temBAD_AUTH_MASTER", "Auth for unclaimed account needs correct master key." }, - { temBAD_CURRENCY, "temBAD_CURRENCY", "Malformed: Bad currency." }, - { temBAD_EXPIRATION, "temBAD_EXPIRATION", "Malformed: Bad expiration." }, - { temBAD_FEE, "temBAD_FEE", "Invalid fee, negative or not XRP." }, - { temBAD_ISSUER, "temBAD_ISSUER", "Malformed: Bad issuer." }, - { temBAD_LIMIT, "temBAD_LIMIT", "Limits must be non-negative." }, - { temBAD_OFFER, "temBAD_OFFER", "Malformed: Bad offer." }, - { temBAD_PATH, "temBAD_PATH", "Malformed: Bad path." }, - { temBAD_PATH_LOOP, "temBAD_PATH_LOOP", "Malformed: Loop in path." }, - { temBAD_SEND_XRP_LIMIT, "temBAD_SEND_XRP_LIMIT", "Malformed: Limit quality is not allowed for XRP to XRP." }, - { temBAD_SEND_XRP_MAX, "temBAD_SEND_XRP_MAX", "Malformed: Send max is not allowed for XRP to XRP." }, - { temBAD_SEND_XRP_NO_DIRECT, "temBAD_SEND_XRP_NO_DIRECT", "Malformed: No Ripple direct is not allowed for XRP to XRP." }, - { temBAD_SEND_XRP_PARTIAL, "temBAD_SEND_XRP_PARTIAL", "Malformed: Partial payment is not allowed for XRP to XRP." }, - { temBAD_SEND_XRP_PATHS, "temBAD_SEND_XRP_PATHS", "Malformed: Paths are not allowed for XRP to XRP." }, - { temBAD_SEQUENCE, "temBAD_SEQUENCE", "Malformed: Sequence is not in the past." }, - { temBAD_SIGNATURE, "temBAD_SIGNATURE", "Malformed: Bad signature." }, - { temBAD_SRC_ACCOUNT, "temBAD_SRC_ACCOUNT", "Malformed: Bad source account." }, - { temBAD_TRANSFER_RATE, "temBAD_TRANSFER_RATE", "Malformed: Transfer rate must be >= 1.0" }, - { temDST_IS_SRC, "temDST_IS_SRC", "Destination may not be source." }, - { temDST_NEEDED, "temDST_NEEDED", "Destination not specified." }, - { temINVALID, "temINVALID", "The transaction is ill-formed." }, - { temINVALID_FLAG, "temINVALID_FLAG", "The transaction has an invalid flag." }, - { temREDUNDANT, "temREDUNDANT", "Sends same currency to self." }, - { temREDUNDANT_SEND_MAX, "temREDUNDANT_SEND_MAX", "Send max is redundant." }, - { temRIPPLE_EMPTY, "temRIPPLE_EMPTY", "PathSet with no paths." }, - { temUNCERTAIN, "temUNCERTAIN", "In process of determining result. Never returned." }, - { temUNKNOWN, "temUNKNOWN", "The transactions requires logic not implemented yet." }, - - { terRETRY, "terRETRY", "Retry transaction." }, - { terFUNDS_SPENT, "terFUNDS_SPENT", "Can't set password, password set funds already spent." }, - { terINSUF_FEE_B, "terINSUF_FEE_B", "Account balance can't pay fee." }, - { terLAST, "terLAST", "Process last." }, - { terNO_RIPPLE, "terNO_RIPPLE", "Path does not permit rippling." }, - { terNO_ACCOUNT, "terNO_ACCOUNT", "The source account does not exist." }, - { terNO_AUTH, "terNO_AUTH", "Not authorized to hold IOUs." }, - { terNO_LINE, "terNO_LINE", "No such line." }, - { terPRE_SEQ, "terPRE_SEQ", "Missing/inapplicable prior transaction." }, - { terOWNERS, "terOWNERS", "Non-zero owner count." }, - - { tesSUCCESS, "tesSUCCESS", "The transaction was applied. Only final in a validated ledger." }, + TER code; + char const* token; + char const* text; }; - int iIndex = RIPPLE_ARRAYSIZE (transResultInfoA); - - while (iIndex-- && transResultInfoA[iIndex].terCode != terCode) - ; - - if (iIndex >= 0) + // FIXME: replace this with a function-static std::map and the lookup + // code with std::map::find when the problem with magic statics on + // Visual Studio is fixed. + static + TxResultInfo const results[] = { - strToken = transResultInfoA[iIndex].cpToken; - strHuman = transResultInfoA[iIndex].cpHuman; + { tecCLAIM, "tecCLAIM", "Fee claimed. Sequence used. No action." }, + { tecDIR_FULL, "tecDIR_FULL", "Can not add entry to full directory." }, + { tecFAILED_PROCESSING, "tecFAILED_PROCESSING", "Failed to correctly process transaction." }, + { tecINSUF_RESERVE_LINE, "tecINSUF_RESERVE_LINE", "Insufficient reserve to add trust line." }, + { tecINSUF_RESERVE_OFFER, "tecINSUF_RESERVE_OFFER", "Insufficient reserve to create offer." }, + { tecNO_DST, "tecNO_DST", "Destination does not exist. Send XRP to create it." }, + { tecNO_DST_INSUF_XRP, "tecNO_DST_INSUF_XRP", "Destination does not exist. Too little XRP sent to create it." }, + { tecNO_LINE_INSUF_RESERVE, "tecNO_LINE_INSUF_RESERVE", "No such line. Too little reserve to create it." }, + { tecNO_LINE_REDUNDANT, "tecNO_LINE_REDUNDANT", "Can't set non-existent line to default." }, + { tecPATH_DRY, "tecPATH_DRY", "Path could not send partial amount." }, + { tecPATH_PARTIAL, "tecPATH_PARTIAL", "Path could not send full amount." }, + { tecMASTER_DISABLED, "tecMASTER_DISABLED", "Master key is disabled." }, + { tecNO_REGULAR_KEY, "tecNO_REGULAR_KEY", "Regular key is not set." }, + + { tecUNFUNDED, "tecUNFUNDED", "One of _ADD, _OFFER, or _SEND. Deprecated." }, + { tecUNFUNDED_ADD, "tecUNFUNDED_ADD", "Insufficient XRP balance for WalletAdd." }, + { tecUNFUNDED_OFFER, "tecUNFUNDED_OFFER", "Insufficient balance to fund created offer." }, + { tecUNFUNDED_PAYMENT, "tecUNFUNDED_PAYMENT", "Insufficient XRP balance to send." }, + { tecOWNERS, "tecOWNERS", "Non-zero owner count." }, + { tecNO_ISSUER, "tecNO_ISSUER", "Issuer account does not exist." }, + { tecNO_AUTH, "tecNO_AUTH", "Not authorized to hold asset." }, + { tecNO_LINE, "tecNO_LINE", "No such line." }, + { tecINSUFF_FEE, "tecINSUFF_FEE", "Insufficient balance to pay fee." }, + { tecFROZEN, "tecFROZEN", "Asset is frozen." }, + { tecNO_TARGET, "tecNO_TARGET", "Target account does not exist." }, + { tecNO_PERMISSION, "tecNO_PERMISSION", "No permission to perform requested operation." }, + { tecNO_ENTRY, "tecNO_ENTRY", "No matching entry found." }, + { tecINSUFFICIENT_RESERVE, "tecINSUFFICIENT_RESERVE", "Insufficient reserve to complete requested operation." }, + + { tefALREADY, "tefALREADY", "The exact transaction was already in this ledger." }, + { tefBAD_ADD_AUTH, "tefBAD_ADD_AUTH", "Not authorized to add account." }, + { tefBAD_AUTH, "tefBAD_AUTH", "Transaction's public key is not authorized." }, + { tefBAD_LEDGER, "tefBAD_LEDGER", "Ledger in unexpected state." }, + { tefCREATED, "tefCREATED", "Can't add an already created account." }, + { tefDST_TAG_NEEDED, "tefDST_TAG_NEEDED", "Destination tag required." }, + { tefEXCEPTION, "tefEXCEPTION", "Unexpected program state." }, + { tefFAILURE, "tefFAILURE", "Failed to apply." }, + { tefINTERNAL, "tefINTERNAL", "Internal error." }, + { tefMASTER_DISABLED, "tefMASTER_DISABLED", "Master key is disabled." }, + { tefMAX_LEDGER, "tefMAX_LEDGER", "Ledger sequence too high." }, + { tefNO_AUTH_REQUIRED, "tefNO_AUTH_REQUIRED", "Auth is not required." }, + { tefPAST_SEQ, "tefPAST_SEQ", "This sequence number has already past." }, + { tefWRONG_PRIOR, "tefWRONG_PRIOR", "This previous transaction does not match." }, + + { telLOCAL_ERROR, "telLOCAL_ERROR", "Local failure." }, + { telBAD_DOMAIN, "telBAD_DOMAIN", "Domain too long." }, + { telBAD_PATH_COUNT, "telBAD_PATH_COUNT", "Malformed: Too many paths." }, + { telBAD_PUBLIC_KEY, "telBAD_PUBLIC_KEY", "Public key too long." }, + { telFAILED_PROCESSING, "telFAILED_PROCESSING", "Failed to correctly process transaction." }, + { telINSUF_FEE_P, "telINSUF_FEE_P", "Fee insufficient." }, + { telNO_DST_PARTIAL, "telNO_DST_PARTIAL", "Partial payment to create account not allowed." }, + + { temMALFORMED, "temMALFORMED", "Malformed transaction." }, + { temBAD_AMOUNT, "temBAD_AMOUNT", "Can only send positive amounts." }, + { temBAD_AUTH_MASTER, "temBAD_AUTH_MASTER", "Auth for unclaimed account needs correct master key." }, + { temBAD_CURRENCY, "temBAD_CURRENCY", "Malformed: Bad currency." }, + { temBAD_EXPIRATION, "temBAD_EXPIRATION", "Malformed: Bad expiration." }, + { temBAD_FEE, "temBAD_FEE", "Invalid fee, negative or not XRP." }, + { temBAD_ISSUER, "temBAD_ISSUER", "Malformed: Bad issuer." }, + { temBAD_LIMIT, "temBAD_LIMIT", "Limits must be non-negative." }, + { temBAD_OFFER, "temBAD_OFFER", "Malformed: Bad offer." }, + { temBAD_PATH, "temBAD_PATH", "Malformed: Bad path." }, + { temBAD_PATH_LOOP, "temBAD_PATH_LOOP", "Malformed: Loop in path." }, + { temBAD_SEND_XRP_LIMIT, "temBAD_SEND_XRP_LIMIT", "Malformed: Limit quality is not allowed for XRP to XRP." }, + { temBAD_SEND_XRP_MAX, "temBAD_SEND_XRP_MAX", "Malformed: Send max is not allowed for XRP to XRP." }, + { temBAD_SEND_XRP_NO_DIRECT,"temBAD_SEND_XRP_NO_DIRECT","Malformed: No Ripple direct is not allowed for XRP to XRP." }, + { temBAD_SEND_XRP_PARTIAL, "temBAD_SEND_XRP_PARTIAL", "Malformed: Partial payment is not allowed for XRP to XRP." }, + { temBAD_SEND_XRP_PATHS, "temBAD_SEND_XRP_PATHS", "Malformed: Paths are not allowed for XRP to XRP." }, + { temBAD_SEQUENCE, "temBAD_SEQUENCE", "Malformed: Sequence is not in the past." }, + { temBAD_SIGNATURE, "temBAD_SIGNATURE", "Malformed: Bad signature." }, + { temBAD_SRC_ACCOUNT, "temBAD_SRC_ACCOUNT", "Malformed: Bad source account." }, + { temBAD_TRANSFER_RATE, "temBAD_TRANSFER_RATE", "Malformed: Transfer rate must be >= 1.0" }, + { temDST_IS_SRC, "temDST_IS_SRC", "Destination may not be source." }, + { temDST_NEEDED, "temDST_NEEDED", "Destination not specified." }, + { temINVALID, "temINVALID", "The transaction is ill-formed." }, + { temINVALID_FLAG, "temINVALID_FLAG", "The transaction has an invalid flag." }, + { temREDUNDANT, "temREDUNDANT", "Sends same currency to self." }, + { temREDUNDANT_SEND_MAX, "temREDUNDANT_SEND_MAX", "Send max is redundant." }, + { temRIPPLE_EMPTY, "temRIPPLE_EMPTY", "PathSet with no paths." }, + { temUNCERTAIN, "temUNCERTAIN", "In process of determining result. Never returned." }, + { temUNKNOWN, "temUNKNOWN", "The transactions requires logic not implemented yet." }, + + { terRETRY, "terRETRY", "Retry transaction." }, + { terFUNDS_SPENT, "terFUNDS_SPENT", "Can't set password, password set funds already spent." }, + { terINSUF_FEE_B, "terINSUF_FEE_B", "Account balance can't pay fee." }, + { terLAST, "terLAST", "Process last." }, + { terNO_RIPPLE, "terNO_RIPPLE", "Path does not permit rippling." }, + { terNO_ACCOUNT, "terNO_ACCOUNT", "The source account does not exist." }, + { terNO_AUTH, "terNO_AUTH", "Not authorized to hold IOUs." }, + { terNO_LINE, "terNO_LINE", "No such line." }, + { terPRE_SEQ, "terPRE_SEQ", "Missing/inapplicable prior transaction." }, + { terOWNERS, "terOWNERS", "Non-zero owner count." }, + + { tesSUCCESS, "tesSUCCESS", "The transaction was applied. Only final in a validated ledger." }, + }; + + for (auto const& result : results) + { + if (result.code == code) + { + token = result.token; + text = result.text; + return true; + } } - return iIndex >= 0; + return false; } -std::string transToken (TER terCode) +std::string transToken (TER code) { - std::string strToken; - std::string strHuman; + std::string token; + std::string text; - return transResultInfo (terCode, strToken, strHuman) ? strToken : "-"; + return transResultInfo (code, token, text) ? token : "-"; } -std::string transHuman (TER terCode) +std::string transHuman (TER code) { - std::string strToken; - std::string strHuman; + std::string token; + std::string text; - return transResultInfo (terCode, strToken, strHuman) ? strHuman : "-"; + return transResultInfo (code, token, text) ? text : "-"; } } // ripple diff --git a/src/ripple/protocol/impl/UintTypes.cpp b/src/ripple/protocol/impl/UintTypes.cpp index 929e765dd5..cab2caec55 100644 --- a/src/ripple/protocol/impl/UintTypes.cpp +++ b/src/ripple/protocol/impl/UintTypes.cpp @@ -17,6 +17,7 @@ */ //============================================================================== +#include #include #include @@ -120,10 +121,6 @@ bool to_issuer(Account& issuer, std::string const& s) return success; } -const char* systemCurrencyCode() { - return "XRP"; -} - Account const& xrpAccount() { static Account const account(0); diff --git a/src/ripple/rpc/handlers/Stop.cpp b/src/ripple/rpc/handlers/Stop.cpp index f170fd9e6d..b9ae7a5bee 100644 --- a/src/ripple/rpc/handlers/Stop.cpp +++ b/src/ripple/rpc/handlers/Stop.cpp @@ -25,7 +25,7 @@ Json::Value doStop (RPC::Context& context) auto lock = getApp().masterLock(); getApp().signalStop (); - return RPC::makeObjectValue (SYSTEM_NAME " server stopping"); + return RPC::makeObjectValue (systemName () + " server stopping"); } } // ripple diff --git a/src/ripple/rpc/impl/JsonWriter.cpp b/src/ripple/rpc/impl/JsonWriter.cpp index 7b0fa7731e..870405c1a2 100644 --- a/src/ripple/rpc/impl/JsonWriter.cpp +++ b/src/ripple/rpc/impl/JsonWriter.cpp @@ -17,7 +17,6 @@ */ //============================================================================== -#include #include #include diff --git a/src/ripple/server/impl/JSONRPCUtil.cpp b/src/ripple/server/impl/JSONRPCUtil.cpp index fc8a5e9936..51800e7240 100644 --- a/src/ripple/server/impl/JSONRPCUtil.cpp +++ b/src/ripple/server/impl/JSONRPCUtil.cpp @@ -73,7 +73,7 @@ std::string HTTPReply (int nStatus, std::string const& strMsg) // CHECKME this returns a different version than the replies below. Is // this by design or an accident or should it be using // BuildInfo::getFullVersionString () as well? - ret.append ("Server: " SYSTEM_NAME "-json-rpc/v1"); + ret.append ("Server: " + systemName () + "-json-rpc/v1"); ret.append ("\r\n"); // Be careful in modifying this! If you change the contents you MUST @@ -120,7 +120,7 @@ std::string HTTPReply (int nStatus, std::string const& strMsg) ret.append ("Content-Type: application/json; charset=UTF-8\r\n"); - ret.append ("Server: " SYSTEM_NAME "-json-rpc/"); + ret.append ("Server: " + systemName () + "-json-rpc/"); ret.append (BuildInfo::getFullVersionString ()); ret.append ("\r\n"); diff --git a/src/ripple/unity/basics.cpp b/src/ripple/unity/basics.cpp index 5aea3ceca3..3b53d6ae2b 100644 --- a/src/ripple/unity/basics.cpp +++ b/src/ripple/unity/basics.cpp @@ -38,5 +38,3 @@ #include #include #include - -#include