From 8d660736a8e3bce7a9b00bad842061d63b52c77e Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Sun, 10 Mar 2013 18:27:02 -0700 Subject: [PATCH 01/19] Fix cases where we don't relay transactions. --- src/cpp/ripple/NetworkOPs.cpp | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/src/cpp/ripple/NetworkOPs.cpp b/src/cpp/ripple/NetworkOPs.cpp index da49c25e1..ec5ab3474 100644 --- a/src/cpp/ripple/NetworkOPs.cpp +++ b/src/cpp/ripple/NetworkOPs.cpp @@ -374,27 +374,24 @@ Transaction::pointer NetworkOPs::processTransaction(Transaction::pointer trans, if (r == tefFAILURE) throw Fault(IO_ERROR); - if (isTerRetry(r)) - { // transaction should be held - cLog(lsDEBUG) << "Transaction should be held: " << r; - trans->setStatus(HELD); - theApp->getMasterTransaction().canonicalize(trans, true); - mLedgerMaster->addHeldTransaction(trans); - return trans; - } - if (r == tefPAST_SEQ) - { // duplicate or conflict - cLog(lsINFO) << "Transaction is obsolete"; - trans->setStatus(OBSOLETE); - return trans; - } - if (r == tesSUCCESS) { cLog(lsINFO) << "Transaction is now included in open ledger"; trans->setStatus(INCLUDED); theApp->getMasterTransaction().canonicalize(trans, true); } + else if (r == tefPAST_SEQ) + { // duplicate or conflict + cLog(lsINFO) << "Transaction is obsolete"; + trans->setStatus(OBSOLETE); + } + else if (isTerRetry(r)) + { // transaction should be held + cLog(lsDEBUG) << "Transaction should be held: " << r; + trans->setStatus(HELD); + theApp->getMasterTransaction().canonicalize(trans, true); + mLedgerMaster->addHeldTransaction(trans); + } else { cLog(lsDEBUG) << "Status other than success " << r; From 9cafb7a2a6bfb268de24f79e385fdf85d89f8ee2 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Sun, 10 Mar 2013 19:05:22 -0700 Subject: [PATCH 02/19] Fix load manager buglets. --- src/cpp/ripple/LoadManager.cpp | 2 +- src/cpp/ripple/WSConnection.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/cpp/ripple/LoadManager.cpp b/src/cpp/ripple/LoadManager.cpp index e604e052e..7bc23eb85 100644 --- a/src/cpp/ripple/LoadManager.cpp +++ b/src/cpp/ripple/LoadManager.cpp @@ -152,7 +152,7 @@ bool LoadManager::shouldCutoff(LoadSource& source) const boost::mutex::scoped_lock sl(mLock); int now = upTime(); canonicalize(source, now); - if (!source.isPrivileged() || (source.mBalance > mDebitLimit)) + if (source.isPrivileged() || (source.mBalance > mDebitLimit)) return false; } logDisconnect(source.getName()); diff --git a/src/cpp/ripple/WSConnection.h b/src/cpp/ripple/WSConnection.h index 10b8be406..bc928d713 100644 --- a/src/cpp/ripple/WSConnection.h +++ b/src/cpp/ripple/WSConnection.h @@ -110,7 +110,7 @@ public: jvResult["id"] = jvRequest["id"]; } - theApp->getLoadManager().adjust(mLoadSource, 5); + theApp->getLoadManager().adjust(mLoadSource, -5); return jvResult; } @@ -131,7 +131,7 @@ public: jvResult["result"] = mRPCHandler.doCommand(jvRequest, iRole, cost); } - if (theApp->getLoadManager().adjust(mLoadSource, cost) && theApp->getLoadManager().shouldWarn(mLoadSource)) + if (theApp->getLoadManager().adjust(mLoadSource, -cost) && theApp->getLoadManager().shouldWarn(mLoadSource)) jvResult["warning"] = "load"; // Currently we will simply unwrap errors returned by the RPC From 4b449b5c99154494ccbccf12f3004ad29dc4d6ac Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Sun, 10 Mar 2013 19:07:11 -0700 Subject: [PATCH 03/19] Fix sign. --- src/cpp/ripple/LoadManager.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/cpp/ripple/LoadManager.cpp b/src/cpp/ripple/LoadManager.cpp index 7bc23eb85..5384df4bd 100644 --- a/src/cpp/ripple/LoadManager.cpp +++ b/src/cpp/ripple/LoadManager.cpp @@ -24,18 +24,18 @@ LoadManager::LoadManager(int creditRate, int creditLimit, int debitWarn, int deb mCreditRate(creditRate), mCreditLimit(creditLimit), mDebitWarn(debitWarn), mDebitLimit(debitLimit), mShutdown(false), mUptime(0), mCosts(LT_MAX) { - addLoadCost(LoadCost(LT_InvalidRequest, 10, LC_CPU | LC_Network)); - addLoadCost(LoadCost(LT_RequestNoReply, 1, LC_CPU | LC_Disk)); - addLoadCost(LoadCost(LT_InvalidSignature, 100, LC_CPU)); - addLoadCost(LoadCost(LT_UnwantedData, 5, LC_CPU | LC_Network)); - addLoadCost(LoadCost(LT_BadData, 20, LC_CPU)); + addLoadCost(LoadCost(LT_InvalidRequest, -10, LC_CPU | LC_Network)); + addLoadCost(LoadCost(LT_RequestNoReply, -1, LC_CPU | LC_Disk)); + addLoadCost(LoadCost(LT_InvalidSignature, -100, LC_CPU)); + addLoadCost(LoadCost(LT_UnwantedData, -5, LC_CPU | LC_Network)); + addLoadCost(LoadCost(LT_BadData, -20, LC_CPU)); - addLoadCost(LoadCost(LT_NewTrusted, 10, 0)); - addLoadCost(LoadCost(LT_NewTransaction, 2, 0)); - addLoadCost(LoadCost(LT_NeededData, 10, 0)); + addLoadCost(LoadCost(LT_NewTrusted, -10, 0)); + addLoadCost(LoadCost(LT_NewTransaction, -2, 0)); + addLoadCost(LoadCost(LT_NeededData, -10, 0)); - addLoadCost(LoadCost(LT_RequestData, 5, LC_Disk | LC_Network)); - addLoadCost(LoadCost(LT_CheapQuery, 1, LC_CPU)); + addLoadCost(LoadCost(LT_RequestData, -5, LC_Disk | LC_Network)); + addLoadCost(LoadCost(LT_CheapQuery, -1, LC_CPU)); } From 92318a47bd59659e2dbfde174b14893ee2fe4afa Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Sun, 10 Mar 2013 19:15:28 -0700 Subject: [PATCH 04/19] Log when we would disconnected, but don't actually disconnect for now. --- src/cpp/ripple/LoadManager.cpp | 6 ++++++ src/cpp/ripple/LoadManager.h | 10 ++++++++-- src/cpp/ripple/WSConnection.h | 2 ++ 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/cpp/ripple/LoadManager.cpp b/src/cpp/ripple/LoadManager.cpp index 5384df4bd..41d15ac94 100644 --- a/src/cpp/ripple/LoadManager.cpp +++ b/src/cpp/ripple/LoadManager.cpp @@ -124,7 +124,10 @@ void LoadManager::canonicalize(LoadSource& source, int now) const { source.mBalance += mCreditRate * (now - source.mLastUpdate); if (source.mBalance > mCreditLimit) + { source.mBalance = mCreditLimit; + source.mLogged = false; + } } source.mLastUpdate = now; } @@ -154,6 +157,9 @@ bool LoadManager::shouldCutoff(LoadSource& source) const canonicalize(source, now); if (source.isPrivileged() || (source.mBalance > mDebitLimit)) return false; + if (source.mLogged) + return true; + source.mLogged = true; } logDisconnect(source.getName()); return true; diff --git a/src/cpp/ripple/LoadManager.h b/src/cpp/ripple/LoadManager.h index 070384d70..25b8aa585 100644 --- a/src/cpp/ripple/LoadManager.h +++ b/src/cpp/ripple/LoadManager.h @@ -66,11 +66,14 @@ protected: int mFlags; int mLastUpdate; int mLastWarning; + bool mLogged; public: - LoadSource(bool admin) : mBalance(0), mFlags(admin ? lsfPrivileged : 0), mLastUpdate(upTime()), mLastWarning(0) + LoadSource(bool admin) : + mBalance(0), mFlags(admin ? lsfPrivileged : 0), mLastUpdate(upTime()), mLastWarning(0), mLogged(false) { ; } - LoadSource(const std::string& name) : mName(name), mBalance(0), mFlags(0), mLastUpdate(upTime()), mLastWarning(0) + LoadSource(const std::string& name) : + mName(name), mBalance(0), mFlags(0), mLastUpdate(upTime()), mLastWarning(0), mLogged(false) { ; } void rename(const std::string& name) { mName = name; } @@ -80,6 +83,9 @@ public: void setPrivileged() { mFlags |= lsfPrivileged; } int getBalance() const { return mBalance; } + bool isLogged() const { return mLogged; } + void clearLogged() { mLogged = false; } + void setOutbound() { mFlags |= lsfOutbound; } bool isOutbound() const { return (mFlags & lsfOutbound) != 0; } }; diff --git a/src/cpp/ripple/WSConnection.h b/src/cpp/ripple/WSConnection.h index bc928d713..6f3aa2cd2 100644 --- a/src/cpp/ripple/WSConnection.h +++ b/src/cpp/ripple/WSConnection.h @@ -90,10 +90,12 @@ public: { if (theApp->getLoadManager().shouldCutoff(mLoadSource)) { +#if SHOULD_DISCONNECT connection_ptr ptr = mConnection.lock(); if (ptr) ptr->close(websocketpp::close::status::PROTOCOL_ERROR, "overload"); return rpcError(rpcSLOW_DOWN); +#endif } if (!jvRequest.isMember("command")) From 27a7ac75de49abc5e4f396acf6df37b9d05dfb07 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Sun, 10 Mar 2013 21:22:01 -0700 Subject: [PATCH 05/19] Add, subtract, multiply, and divide with specified rounding direction. CAUTION: This is still untested and undebugged code. Only divRound has been even slightly tested. --- src/cpp/ripple/AmountRound.cpp | 266 +++++++++++++++++++++++++++++++ src/cpp/ripple/BigNum64.h | 6 + src/cpp/ripple/SerializedTypes.h | 8 + 3 files changed, 280 insertions(+) create mode 100644 src/cpp/ripple/AmountRound.cpp diff --git a/src/cpp/ripple/AmountRound.cpp b/src/cpp/ripple/AmountRound.cpp new file mode 100644 index 000000000..7a7aea55c --- /dev/null +++ b/src/cpp/ripple/AmountRound.cpp @@ -0,0 +1,266 @@ + +#include + +#include "SerializedTypes.h" +#include "Log.h" + +SETUP_LOG(); + +#if (ULONG_MAX > UINT_MAX) +#define BN_add_word64(bn, word) BN_add_word(bn, word) +#define BN_sub_word64(bn, word) BN_sub_word(bn, word) +#define BN_mul_word64(bn, word) BN_mul_word(bn, word) +#define BN_div_word64(bn, word) BN_div_word(bn, word) +#else +#include "BigNum64.h" +#endif + +static const uint64 tenTo14 = 100000000000000ull; +static const uint64 tenTo14m1 = tenTo14 - 1; +static const uint64 tenTo17 = tenTo14 * 1000; +static const uint64 tenTo17m1 = tenTo17 - 1; + +// CAUTION: This is still very early code and is *NOT* ready for real use yet. +// Only divRound is tested, and that's only slightly tested. + +static void canonicalizeRound(bool isNative, uint64& value, int& offset, bool roundUp) +{ + cLog(lsINFO) << "canonicalize< " << value << ":" << offset << (roundUp ? " up" : " down"); + if (isNative && (offset < 0)) + { + if (roundUp) + value += 9; + else + value -= 9; + value /= 10; + ++offset; + } + else if (!isNative && (value > STAmount::cMinValue)) + { + if (roundUp) + value += 9; + else + value -= 9; + value /= 10; + ++offset; + } + cLog(lsINFO) << "canonicalize> " << value << ":" << offset << (roundUp ? " up" : " down"); +} + +STAmount STAmount::addRound(const STAmount& v1, const STAmount& v2, bool roundUp) +{ + v1.throwComparable(v2); + + if (v2.mValue == 0) + return v1; + + if (v1.mValue == 0) + return STAmount(v1.getFName(), v1.mCurrency, v1.mIssuer, v2.mValue, v2.mOffset, v2.mIsNegative); + + if (v1.mIsNative) + return STAmount(v1.getFName(), v1.getSNValue() + v2.getSNValue()); + + int ov1 = v1.mOffset, ov2 = v2.mOffset; + int64 vv1 = static_cast(v1.mValue), vv2=static_cast(v2.mValue); + if (v1.mIsNegative) vv1 = -vv1; + if (v2.mIsNegative) vv2 = -vv2; + + while (ov1 < ov2) + { + if (roundUp) + vv1 += 9; + else + vv1 -= 9; + vv1 /= 10; + ++ov1; + } + while (ov2 < ov1) + { + if (roundUp) + vv1 += 9; + else + vv1 -= 9; + vv1 /= 10; + ++ov2; + } + + int64 fv = vv1 + vv2; + if (fv >= 0) + { + uint64 v = static_cast(fv); + canonicalizeRound(false, v, ov1, roundUp); + return STAmount(v1.getFName(), v1.mCurrency, v1.mIssuer, v, ov1, false); + } + else + { + uint64 v = static_cast(-fv); + canonicalizeRound(false, v, ov1, !roundUp); + return STAmount(v1.getFName(), v1.mCurrency, v1.mIssuer, v, ov1, true); + } +} + +STAmount STAmount::subRound(const STAmount& v1, const STAmount& v2, bool roundUp) +{ + v1.throwComparable(v2); + + if (v2.mValue == 0) + return v1; + + if (v1.mValue == 0) + return STAmount(v1.getFName(), v1.mCurrency, v1.mIssuer, v2.mValue, v2.mOffset, !v2.mIsNegative); + + if (v1.mIsNative) + return STAmount(v1.getFName(), v1.getSNValue() - v2.getSNValue()); + + int ov1 = v1.mOffset, ov2 = v2.mOffset; + int64 vv1 = static_cast(v1.mValue), vv2=static_cast(v2.mValue); + if (v1.mIsNegative) vv1 = -vv1; + if (v2.mIsNegative) vv2 = -vv2; + + while (ov1 < ov2) + { + if (roundUp) + vv1 += 9; + else + vv1 -= 9; + vv1 /= 10; + ++ov1; + } + while (ov2 < ov1) + { + if (roundUp) + vv1 -= 9; + else + vv1 += 9; + vv1 /= 10; + ++ov2; + } + + int64 fv = vv1 + vv2; + if (fv >= 0) + return STAmount(v1.getFName(), v1.mCurrency, v1.mIssuer, fv, ov1, false); + else + return STAmount(v1.getFName(), v1.mCurrency, v1.mIssuer, -fv, ov1, true); +} + +STAmount STAmount::mulRound(const STAmount& v1, const STAmount& v2, + const uint160& uCurrencyID, const uint160& uIssuerID, bool roundUp) +{ + if (v1.isZero() || v2.isZero()) + return STAmount(uCurrencyID, uIssuerID); + + if (v1.mIsNative && v2.mIsNative && uCurrencyID.isZero()) + { + uint64 minV = (v1.getSNValue() < v2.getSNValue()) ? v1.getSNValue() : v2.getSNValue(); + uint64 maxV = (v1.getSNValue() < v2.getSNValue()) ? v2.getSNValue() : v1.getSNValue(); + if (minV > 3000000000ull) // sqrt(cMaxNative) + throw std::runtime_error("Native value overflow"); + if (((maxV >> 32) * minV) > 2095475792ull) // cMaxNative / 2^32 + throw std::runtime_error("Native value overflow"); + return STAmount(v1.getFName(), minV * maxV); + } + + uint64 value1 = v1.mValue, value2 = v2.mValue; + int offset1 = v1.mOffset, offset2 = v2.mOffset; + + if (v1.mIsNative) + { + while (value1 < STAmount::cMinValue) + { + value1 *= 10; + --offset1; + } + } + + if (v2.mIsNative) + { + while (value2 < STAmount::cMinValue) + { + value2 *= 10; + --offset2; + } + } + + bool resultNegative = v1.mIsNegative != v2.mIsNegative; + // Compute (numerator * denominator) / 10^14 with rounding + // 10^16 <= result <= 10^18 + CBigNum v; + if ((BN_add_word64(&v, value1) != 1) || (BN_mul_word64(&v, value2) != 1) || + (BN_add_word64(&v, (resultNegative == roundUp) ? (-tenTo14m1) : tenTo14m1) != 1) || + (BN_div_word64(&v, tenTo14) == ((uint64) -1))) + throw std::runtime_error("internal bn error"); + + // 10^16 <= product <= 10^18 + assert(BN_num_bytes(&v) <= 64); + + uint64 amount = v.getuint64(); + int offset = offset1 + offset2 + 14; + canonicalizeRound(uCurrencyID.isZero(), amount, offset, resultNegative != roundUp); + return STAmount(uCurrencyID, uIssuerID, amount, offset, resultNegative); +} + +STAmount STAmount::divRound(const STAmount& num, const STAmount& den, + const uint160& uCurrencyID, const uint160& uIssuerID, bool roundUp) +{ + if (den.isZero()) throw std::runtime_error("division by zero"); + if (num.isZero()) return STAmount(uCurrencyID, uIssuerID); + + uint64 numVal = num.mValue, denVal = den.mValue; + int numOffset = num.mOffset, denOffset = den.mOffset; + + if (num.mIsNative) + while (numVal < STAmount::cMinValue) + { // Need to bring into range + numVal *= 10; + --numOffset; + } + + if (den.mIsNative) + while (denVal < STAmount::cMinValue) + { + denVal *= 10; + --denOffset; + } + + bool resultNegative = num.mIsNegative != num.mIsNegative; + // Compute (numerator * 10^17) / denominator + CBigNum v; + if ((BN_add_word64(&v, numVal) != 1) || (BN_mul_word64(&v, tenTo17) != 1)) + throw std::runtime_error("internal bn error"); + + if (resultNegative != roundUp) + BN_add_word64(&v, denVal - 1); + else + BN_sub_word64(&v, denVal - 1); + + if (BN_div_word64(&v, denVal) == ((uint64) -1)) + throw std::runtime_error("internal bn error"); + + // 10^16 <= quotient <= 10^18 + assert(BN_num_bytes(&v) <= 64); + + uint64 amount = v.getuint64(); + int offset = numOffset - denOffset - 17; + canonicalizeRound(uCurrencyID.isZero(), amount, offset, resultNegative != roundUp); + return STAmount(uCurrencyID, uIssuerID, amount, offset, resultNegative); +} + +BOOST_AUTO_TEST_SUITE(amountRound) + +BOOST_AUTO_TEST_CASE( amountRound_test ) +{ + STAmount one(CURRENCY_ONE, ACCOUNT_ONE, 1); + STAmount two(CURRENCY_ONE, ACCOUNT_ONE, 2); + STAmount three(CURRENCY_ONE, ACCOUNT_ONE, 3); + + STAmount oneThird1 = STAmount::divRound(one, three, CURRENCY_ONE, ACCOUNT_ONE, false); + STAmount oneThird2 = STAmount::divide(one, three, CURRENCY_ONE, ACCOUNT_ONE); + STAmount oneThird3 = STAmount::divRound(one, three, CURRENCY_ONE, ACCOUNT_ONE, true); + cLog(lsINFO) << oneThird1; + cLog(lsINFO) << oneThird2; + cLog(lsINFO) << oneThird3; +} + +BOOST_AUTO_TEST_SUITE_END() + +// vim:ts=4 diff --git a/src/cpp/ripple/BigNum64.h b/src/cpp/ripple/BigNum64.h index 9150a25ca..0a052dda6 100644 --- a/src/cpp/ripple/BigNum64.h +++ b/src/cpp/ripple/BigNum64.h @@ -7,6 +7,12 @@ static int BN_add_word64(BIGNUM *a, uint64 w) return BN_add(a, &bn, a); } +static int BN_sub_word64(BIGNUM *a, uint64 w) +{ + CBigNum bn(w); + return BN_sub(a, &bn, a); +} + static int BN_mul_word64(BIGNUM *a, uint64 w) { CBigNum bn(w); diff --git a/src/cpp/ripple/SerializedTypes.h b/src/cpp/ripple/SerializedTypes.h index b618c952d..f407bfae8 100644 --- a/src/cpp/ripple/SerializedTypes.h +++ b/src/cpp/ripple/SerializedTypes.h @@ -427,6 +427,14 @@ public: static STAmount multiply(const STAmount& v1, const STAmount& v2) { return multiply(v1, v2, v1); } + // Add, subtract, multiply, or divide rounding result in specified direction + static STAmount addRound(const STAmount& v1, const STAmount& v2, bool roundUp); + static STAmount subRound(const STAmount& v1, const STAmount& v2, bool roundUp); + static STAmount mulRound(const STAmount& v1, const STAmount& v2, + const uint160& currency, const uint160& issuer, bool roundUp); + static STAmount divRound(const STAmount& v1, const STAmount& v2, + const uint160& currency, const uint160& issuer, bool roundUp); + // Someone is offering X for Y, what is the rate? // Rate: smaller is better, the taker wants the most out: in/out static uint64 getRate(const STAmount& offerOut, const STAmount& offerIn); From 33bb64e4d7fa47a1794c800180a1213230280c0e Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Sun, 10 Mar 2013 21:24:07 -0700 Subject: [PATCH 06/19] Missing from previous commit. --- src/cpp/ripple/Amount.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/cpp/ripple/Amount.cpp b/src/cpp/ripple/Amount.cpp index c228fba65..122787e71 100644 --- a/src/cpp/ripple/Amount.cpp +++ b/src/cpp/ripple/Amount.cpp @@ -21,6 +21,7 @@ static const uint64 tenTo17 = tenTo14 * 1000; #if (ULONG_MAX > UINT_MAX) #define BN_add_word64(bn, word) BN_add_word(bn, word) +#define BN_sub_word64(bn, word) BN_sub_word(bn, word) #define BN_mul_word64(bn, word) BN_mul_word(bn, word) #define BN_div_word64(bn, word) BN_div_word(bn, word) #else From 31134b06b1cda2c5851812ce457f4b07ff628536 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Sun, 10 Mar 2013 21:30:07 -0700 Subject: [PATCH 07/19] Only round on first scaling divide. --- src/cpp/ripple/AmountRound.cpp | 47 ++++++++++++++++++++++++---------- 1 file changed, 34 insertions(+), 13 deletions(-) diff --git a/src/cpp/ripple/AmountRound.cpp b/src/cpp/ripple/AmountRound.cpp index 7a7aea55c..ecb7efb66 100644 --- a/src/cpp/ripple/AmountRound.cpp +++ b/src/cpp/ripple/AmountRound.cpp @@ -24,7 +24,7 @@ static const uint64 tenTo17m1 = tenTo17 - 1; // Only divRound is tested, and that's only slightly tested. static void canonicalizeRound(bool isNative, uint64& value, int& offset, bool roundUp) -{ +{ // Have to round on first divide, if a divide is needed cLog(lsINFO) << "canonicalize< " << value << ":" << offset << (roundUp ? " up" : " down"); if (isNative && (offset < 0)) { @@ -65,23 +65,30 @@ STAmount STAmount::addRound(const STAmount& v1, const STAmount& v2, bool roundUp if (v1.mIsNegative) vv1 = -vv1; if (v2.mIsNegative) vv2 = -vv2; - while (ov1 < ov2) + if (ov1 < ov2) { if (roundUp) vv1 += 9; else vv1 -= 9; - vv1 /= 10; - ++ov1; + while (ov1 < ov2) + { + vv1 /= 10; + ++ov1; + } } - while (ov2 < ov1) + + if (ov2 < ov1) { if (roundUp) vv1 += 9; else vv1 -= 9; - vv1 /= 10; - ++ov2; + while (ov2 < ov1) + { + vv1 /= 10; + ++ov2; + } } int64 fv = vv1 + vv2; @@ -117,23 +124,30 @@ STAmount STAmount::subRound(const STAmount& v1, const STAmount& v2, bool roundUp if (v1.mIsNegative) vv1 = -vv1; if (v2.mIsNegative) vv2 = -vv2; - while (ov1 < ov2) + if (ov1 < ov2) { if (roundUp) vv1 += 9; else vv1 -= 9; - vv1 /= 10; - ++ov1; + while (ov1 < ov2) + { + vv1 /= 10; + ++ov1; + } } - while (ov2 < ov1) + + if (ov2 < ov1) { if (roundUp) vv1 -= 9; else vv1 += 9; - vv1 /= 10; - ++ov2; + while (ov2 < ov1) + { + vv1 /= 10; + ++ov2; + } } int64 fv = vv1 + vv2; @@ -259,6 +273,13 @@ BOOST_AUTO_TEST_CASE( amountRound_test ) cLog(lsINFO) << oneThird1; cLog(lsINFO) << oneThird2; cLog(lsINFO) << oneThird3; + + STAmount twoThird1 = STAmount::divRound(two, three, CURRENCY_ONE, ACCOUNT_ONE, false); + STAmount twoThird2 = STAmount::divide(two, three, CURRENCY_ONE, ACCOUNT_ONE); + STAmount twoThird3 = STAmount::divRound(two, three, CURRENCY_ONE, ACCOUNT_ONE, true); + cLog(lsINFO) << twoThird1; + cLog(lsINFO) << twoThird2; + cLog(lsINFO) << twoThird3; } BOOST_AUTO_TEST_SUITE_END() From a85b38e8e3f3910f235ae652f723a6074523c248 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Sun, 10 Mar 2013 21:33:59 -0700 Subject: [PATCH 08/19] Bugfixes. --- src/cpp/ripple/AmountRound.cpp | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/src/cpp/ripple/AmountRound.cpp b/src/cpp/ripple/AmountRound.cpp index ecb7efb66..698bb3133 100644 --- a/src/cpp/ripple/AmountRound.cpp +++ b/src/cpp/ripple/AmountRound.cpp @@ -81,12 +81,12 @@ STAmount STAmount::addRound(const STAmount& v1, const STAmount& v2, bool roundUp if (ov2 < ov1) { if (roundUp) - vv1 += 9; + vv2 += 9; else - vv1 -= 9; + vv2 -= 9; while (ov2 < ov1) { - vv1 /= 10; + vv2 /= 10; ++ov2; } } @@ -140,12 +140,12 @@ STAmount STAmount::subRound(const STAmount& v1, const STAmount& v2, bool roundUp if (ov2 < ov1) { if (roundUp) - vv1 -= 9; + vv2 -= 9; else - vv1 += 9; + vv2 += 9; while (ov2 < ov1) { - vv1 /= 10; + vv2 /= 10; ++ov2; } } @@ -199,9 +199,15 @@ STAmount STAmount::mulRound(const STAmount& v1, const STAmount& v2, // Compute (numerator * denominator) / 10^14 with rounding // 10^16 <= result <= 10^18 CBigNum v; - if ((BN_add_word64(&v, value1) != 1) || (BN_mul_word64(&v, value2) != 1) || - (BN_add_word64(&v, (resultNegative == roundUp) ? (-tenTo14m1) : tenTo14m1) != 1) || - (BN_div_word64(&v, tenTo14) == ((uint64) -1))) + if ((BN_add_word64(&v, value1) != 1) || (BN_mul_word64(&v, value2) != 1)) + throw std::runtime_error("internal bn error"); + + if (resultNegative != roundUp) + BN_add_word64(&v, tenTo14m1); + else + BN_sub_word64(&v, tenTo14m1); + + if (BN_div_word64(&v, tenTo14) == ((uint64) -1)) throw std::runtime_error("internal bn error"); // 10^16 <= product <= 10^18 From 466ac775270b129e8e14b9accad8414818976496 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Sun, 10 Mar 2013 21:36:00 -0700 Subject: [PATCH 09/19] Don't round so aggressively. --- src/cpp/ripple/AmountRound.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/cpp/ripple/AmountRound.cpp b/src/cpp/ripple/AmountRound.cpp index 698bb3133..100744253 100644 --- a/src/cpp/ripple/AmountRound.cpp +++ b/src/cpp/ripple/AmountRound.cpp @@ -30,8 +30,8 @@ static void canonicalizeRound(bool isNative, uint64& value, int& offset, bool ro { if (roundUp) value += 9; - else - value -= 9; +// else +// value -= 9; value /= 10; ++offset; } @@ -39,8 +39,8 @@ static void canonicalizeRound(bool isNative, uint64& value, int& offset, bool ro { if (roundUp) value += 9; - else - value -= 9; +// else +// value -= 9; value /= 10; ++offset; } From 275a4a22d7bcb6433d6338074df72632e4b4632d Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Sun, 10 Mar 2013 21:55:33 -0700 Subject: [PATCH 10/19] Fixes. --- src/cpp/ripple/AmountRound.cpp | 39 ++++++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 11 deletions(-) diff --git a/src/cpp/ripple/AmountRound.cpp b/src/cpp/ripple/AmountRound.cpp index 100744253..701003688 100644 --- a/src/cpp/ripple/AmountRound.cpp +++ b/src/cpp/ripple/AmountRound.cpp @@ -25,22 +25,32 @@ static const uint64 tenTo17m1 = tenTo17 - 1; static void canonicalizeRound(bool isNative, uint64& value, int& offset, bool roundUp) { // Have to round on first divide, if a divide is needed + if (!roundUp) // canonicalize already rounds down + return; + cLog(lsINFO) << "canonicalize< " << value << ":" << offset << (roundUp ? " up" : " down"); - if (isNative && (offset < 0)) + if (isNative) { - if (roundUp) + if (offset < 0) + { + while (offset < -1) + { + value /= 10; + ++offset; + } value += 9; -// else -// value -= 9; - value /= 10; - ++offset; + value /= 10; + ++offset; + } } - else if (!isNative && (value > STAmount::cMinValue)) + else if (value > STAmount::cMaxValue) { - if (roundUp) - value += 9; -// else -// value -= 9; + while (value > (10 * STAmount::cMaxValue)) + { + value /= 10; + ++offset; + } + value += 9; value /= 10; ++offset; } @@ -286,6 +296,13 @@ BOOST_AUTO_TEST_CASE( amountRound_test ) cLog(lsINFO) << twoThird1; cLog(lsINFO) << twoThird2; cLog(lsINFO) << twoThird3; + + STAmount oneA = STAmount::mulRound(oneThird1, three, CURRENCY_ONE, ACCOUNT_ONE, false); + STAmount oneB = STAmount::multiply(oneThird2, three, CURRENCY_ONE, ACCOUNT_ONE); + STAmount oneC = STAmount::mulRound(oneThird3, three, CURRENCY_ONE, ACCOUNT_ONE, true); + cLog(lsINFO) << oneA; + cLog(lsINFO) << oneB; + cLog(lsINFO) << oneC; } BOOST_AUTO_TEST_SUITE_END() From e287000438ab175eec2377784e3127e4e8d3ab4a Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Mon, 11 Mar 2013 00:40:26 -0700 Subject: [PATCH 11/19] Fixes. --- src/cpp/ripple/AmountRound.cpp | 82 ++++++++++++++++++++-------------- 1 file changed, 49 insertions(+), 33 deletions(-) diff --git a/src/cpp/ripple/AmountRound.cpp b/src/cpp/ripple/AmountRound.cpp index 701003688..9fb3b88ca 100644 --- a/src/cpp/ripple/AmountRound.cpp +++ b/src/cpp/ripple/AmountRound.cpp @@ -24,7 +24,7 @@ static const uint64 tenTo17m1 = tenTo17 - 1; // Only divRound is tested, and that's only slightly tested. static void canonicalizeRound(bool isNative, uint64& value, int& offset, bool roundUp) -{ // Have to round on first divide, if a divide is needed +{ if (!roundUp) // canonicalize already rounds down return; @@ -38,7 +38,7 @@ static void canonicalizeRound(bool isNative, uint64& value, int& offset, bool ro value /= 10; ++offset; } - value += 9; + value += 9; // add before last divide value /= 10; ++offset; } @@ -50,7 +50,7 @@ static void canonicalizeRound(bool isNative, uint64& value, int& offset, bool ro value /= 10; ++offset; } - value += 9; + value += 9; // add before last divide value /= 10; ++offset; } @@ -71,34 +71,36 @@ STAmount STAmount::addRound(const STAmount& v1, const STAmount& v2, bool roundUp return STAmount(v1.getFName(), v1.getSNValue() + v2.getSNValue()); int ov1 = v1.mOffset, ov2 = v2.mOffset; - int64 vv1 = static_cast(v1.mValue), vv2=static_cast(v2.mValue); - if (v1.mIsNegative) vv1 = -vv1; - if (v2.mIsNegative) vv2 = -vv2; + int64 vv1 = static_cast(v1.mValue), vv2 = static_cast(v2.mValue); + if (v1.mIsNegative) + vv1 = -vv1; + if (v2.mIsNegative) + vv2 = -vv2; if (ov1 < ov2) { - if (roundUp) - vv1 += 9; - else - vv1 -= 9; - while (ov1 < ov2) + while (ov1 < (ov2 - 1) { vv1 /= 10; ++ov1; } + if (roundUp) + vv1 += 9; + vv1 /= 10; + ++ov1; } if (ov2 < ov1) { - if (roundUp) - vv2 += 9; - else - vv2 -= 9; - while (ov2 < ov1) + while (ov2 < (ov1 - 1)) { vv2 /= 10; ++ov2; } + if (roundUp) + vv2 += 9; + vv2 /= 10; + ++ov2; } int64 fv = vv1 + vv2; @@ -130,41 +132,53 @@ STAmount STAmount::subRound(const STAmount& v1, const STAmount& v2, bool roundUp return STAmount(v1.getFName(), v1.getSNValue() - v2.getSNValue()); int ov1 = v1.mOffset, ov2 = v2.mOffset; - int64 vv1 = static_cast(v1.mValue), vv2=static_cast(v2.mValue); - if (v1.mIsNegative) vv1 = -vv1; - if (v2.mIsNegative) vv2 = -vv2; + int64 vv1 = static_cast(v1.mValue), vv2 = static_cast(v2.mValue); + + if (v1.mIsNegative) + vv1 = -vv1; + + if (!v2.mIsNegative) + vv2 = -vv2; if (ov1 < ov2) { - if (roundUp) - vv1 += 9; - else - vv1 -= 9; - while (ov1 < ov2) + while (ov1 < (ov2 - 1) { vv1 /= 10; ++ov1; } + if (roundUp) + vv1 += 9; + vv1 /= 10; + ++ov1; } if (ov2 < ov1) { - if (roundUp) - vv2 -= 9; - else - vv2 += 9; - while (ov2 < ov1) + while (ov2 < (ov1 - 1)) { vv2 /= 10; ++ov2; } + if (roundUp) + vv2 += 9; + vv2 /= 10; + ++ov2; } int64 fv = vv1 + vv2; if (fv >= 0) - return STAmount(v1.getFName(), v1.mCurrency, v1.mIssuer, fv, ov1, false); + { + uint64 v = static_cast(fv); + canonicalizeRound(false, v, ov1, roundUp); + return STAmount(v1.getFName(), v1.mCurrency, v1.mIssuer, v, ov1, false); + } else - return STAmount(v1.getFName(), v1.mCurrency, v1.mIssuer, -fv, ov1, true); + { + uint64 v = static_cast(-fv); + canonicalizeRound(false, v, ov1, !roundUp); + return STAmount(v1.getFName(), v1.mCurrency, v1.mIssuer, v, ov1, true); + } } STAmount STAmount::mulRound(const STAmount& v1, const STAmount& v2, @@ -232,8 +246,10 @@ STAmount STAmount::mulRound(const STAmount& v1, const STAmount& v2, STAmount STAmount::divRound(const STAmount& num, const STAmount& den, const uint160& uCurrencyID, const uint160& uIssuerID, bool roundUp) { - if (den.isZero()) throw std::runtime_error("division by zero"); - if (num.isZero()) return STAmount(uCurrencyID, uIssuerID); + if (den.isZero()) + throw std::runtime_error("division by zero"); + if (num.isZero()) + return STAmount(uCurrencyID, uIssuerID); uint64 numVal = num.mValue, denVal = den.mValue; int numOffset = num.mOffset, denOffset = den.mOffset; From 495ddae43829d0fe166807a9dd5e7c8e7a5f2b3c Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Mon, 11 Mar 2013 00:44:55 -0700 Subject: [PATCH 12/19] Fixes. --- src/cpp/ripple/AmountRound.cpp | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/cpp/ripple/AmountRound.cpp b/src/cpp/ripple/AmountRound.cpp index 9fb3b88ca..b86679135 100644 --- a/src/cpp/ripple/AmountRound.cpp +++ b/src/cpp/ripple/AmountRound.cpp @@ -20,15 +20,14 @@ static const uint64 tenTo14m1 = tenTo14 - 1; static const uint64 tenTo17 = tenTo14 * 1000; static const uint64 tenTo17m1 = tenTo17 - 1; -// CAUTION: This is still very early code and is *NOT* ready for real use yet. -// Only divRound is tested, and that's only slightly tested. +// CAUTION: This is early code and is *NOT* ready for real use yet. static void canonicalizeRound(bool isNative, uint64& value, int& offset, bool roundUp) { if (!roundUp) // canonicalize already rounds down return; - cLog(lsINFO) << "canonicalize< " << value << ":" << offset << (roundUp ? " up" : " down"); + cLog(lsDEBUG) << "canonicalize< " << value << ":" << offset << (roundUp ? " up" : " down"); if (isNative) { if (offset < 0) @@ -54,7 +53,7 @@ static void canonicalizeRound(bool isNative, uint64& value, int& offset, bool ro value /= 10; ++offset; } - cLog(lsINFO) << "canonicalize> " << value << ":" << offset << (roundUp ? " up" : " down"); + cLog(lsDEBUG) << "canonicalize> " << value << ":" << offset << (roundUp ? " up" : " down"); } STAmount STAmount::addRound(const STAmount& v1, const STAmount& v2, bool roundUp) @@ -79,7 +78,7 @@ STAmount STAmount::addRound(const STAmount& v1, const STAmount& v2, bool roundUp if (ov1 < ov2) { - while (ov1 < (ov2 - 1) + while (ov1 < (ov2 - 1)) { vv1 /= 10; ++ov1; @@ -142,7 +141,7 @@ STAmount STAmount::subRound(const STAmount& v1, const STAmount& v2, bool roundUp if (ov1 < ov2) { - while (ov1 < (ov2 - 1) + while (ov1 < (ov2 - 1)) { vv1 /= 10; ++ov1; @@ -319,6 +318,13 @@ BOOST_AUTO_TEST_CASE( amountRound_test ) cLog(lsINFO) << oneA; cLog(lsINFO) << oneB; cLog(lsINFO) << oneC; + + STAmount fourThirdsA = STAmount::addRound(twoThird2, twoThird2, false); + STAmount fourThirdsB = twoThird2 + twoThird2; + STAmount fourThirdsC = STAmount::addRound(twoThird2, twoThird2, true); + cLog(lsINFO) << fourThirdsA; + cLog(lsINFO) << fourThirdsB; + cLog(lsINFO) << fourThirdsC; } BOOST_AUTO_TEST_SUITE_END() From 39f2b95140d441806f5b7c1ad241914bbe76c15a Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Mon, 11 Mar 2013 00:59:57 -0700 Subject: [PATCH 13/19] More convenience functions. --- src/cpp/ripple/SerializedTypes.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/cpp/ripple/SerializedTypes.h b/src/cpp/ripple/SerializedTypes.h index f407bfae8..30cb3b8fb 100644 --- a/src/cpp/ripple/SerializedTypes.h +++ b/src/cpp/ripple/SerializedTypes.h @@ -435,6 +435,15 @@ public: static STAmount divRound(const STAmount& v1, const STAmount& v2, const uint160& currency, const uint160& issuer, bool roundUp); + static STAmount mulRound(const STAmount& v1, const STAmount& v2, const STAmount& saUnit, bool roundUp) + { return mulRound(v1, v2, saUnit.getCurrency(), saUnit.getIssuer(), roundUp); } + static STAmount mulRound(const STAmount& v1, const STAmount& v2, bool roundUp) + { return mulRound(v1, v2, v1.getCurrency(), v1.getIssuer(), roundUp); } + static STAmount divRound(const STAmount& v1, const STAmount& v2, const STAmount& saUnit, bool roundUp) + { return divRound(v1, v2, saUnit.getCurrency(), saUnit.getIssuer(), roundUp); } + static STAmount divRound(const STAmount& v1, const STAmount& v2, bool roundUp) + { return divRound(v1, v2, v2.getCurrency(), v2.getIssuer(), roundUp); } + // Someone is offering X for Y, what is the rate? // Rate: smaller is better, the taker wants the most out: in/out static uint64 getRate(const STAmount& offerOut, const STAmount& offerIn); From 204fed2fba6514ad91dcca7e270ba5f8516c06aa Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Mon, 11 Mar 2013 01:00:41 -0700 Subject: [PATCH 14/19] A few last details. --- src/cpp/ripple/AmountRound.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/cpp/ripple/AmountRound.cpp b/src/cpp/ripple/AmountRound.cpp index b86679135..10f7d7b21 100644 --- a/src/cpp/ripple/AmountRound.cpp +++ b/src/cpp/ripple/AmountRound.cpp @@ -37,7 +37,7 @@ static void canonicalizeRound(bool isNative, uint64& value, int& offset, bool ro value /= 10; ++offset; } - value += 9; // add before last divide + value += 10; // add before last divide value /= 10; ++offset; } @@ -49,7 +49,7 @@ static void canonicalizeRound(bool isNative, uint64& value, int& offset, bool ro value /= 10; ++offset; } - value += 9; // add before last divide + value += 9; // add before last divide value /= 10; ++offset; } @@ -325,6 +325,13 @@ BOOST_AUTO_TEST_CASE( amountRound_test ) cLog(lsINFO) << fourThirdsA; cLog(lsINFO) << fourThirdsB; cLog(lsINFO) << fourThirdsC; + + STAmount dripTest1 = STAmount::mulRound(twoThird2, two, uint160(), uint160(), false); + STAmount dripTest2 = STAmount::multiply(twoThird2, two, uint160(), uint160()); + STAmount dripTest3 = STAmount::mulRound(twoThird2, two, uint160(), uint160(), true); + cLog(lsINFO) << dripTest1; + cLog(lsINFO) << dripTest2; + cLog(lsINFO) << dripTest3; } BOOST_AUTO_TEST_SUITE_END() From 70711944ac305e90449ef59418e07083bbbfd971 Mon Sep 17 00:00:00 2001 From: Stefan Thomas Date: Sun, 10 Mar 2013 21:42:44 +0100 Subject: [PATCH 15/19] JS: Utility function to convert ripple epoch to JS timestamp. --- src/js/index.js | 2 ++ src/js/utils.js | 10 ++++++++++ 2 files changed, 12 insertions(+) diff --git a/src/js/index.js b/src/js/index.js index 4ff2b374d..b603d6a53 100644 --- a/src/js/index.js +++ b/src/js/index.js @@ -3,6 +3,8 @@ exports.Amount = require('./amount').Amount; exports.UInt160 = require('./amount').UInt160; exports.Seed = require('./amount').Seed; +exports.utils = require('./utils'); + // Important: We do not guarantee any specific version of SJCL or for any // specific features to be included. The version and configuration may change at // any time without warning. diff --git a/src/js/utils.js b/src/js/utils.js index d1779faf9..462f3f286 100644 --- a/src/js/utils.js +++ b/src/js/utils.js @@ -97,6 +97,15 @@ var assert = function (assertion, msg) { } }; +/** + * Convert a ripple epoch to a JavaScript timestamp. + * + * JavaScript timestamps are unix epoch in milliseconds. + */ +var toTimestamp = function (rpepoch) { + return (rpepoch + 0x386D4380) * 1000; +}; + exports.trace = trace; exports.arraySet = arraySet; exports.hexToString = hexToString; @@ -106,5 +115,6 @@ exports.stringToHex = stringToHex; exports.chunkString = chunkString; exports.logObject = logObject; exports.assert = assert; +exports.toTimestamp = toTimestamp; // vim:sw=2:sts=2:ts=8:et From 99c2f44cfab2026ac18d3948ac2d9845fae5403c Mon Sep 17 00:00:00 2001 From: Stefan Thomas Date: Mon, 11 Mar 2013 09:27:03 +0100 Subject: [PATCH 16/19] JS: Fix missing boundary bytes in PathSet serialization. --- src/js/serializedtypes.js | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/js/serializedtypes.js b/src/js/serializedtypes.js index 93009a9fb..a3a2808d8 100644 --- a/src/js/serializedtypes.js +++ b/src/js/serializedtypes.js @@ -243,17 +243,25 @@ var STAccount = exports.Account = new SerializedType({ }); var STPathSet = exports.PathSet = new SerializedType({ + typeBoundary: 0xff, + typeEnd: 0x00, + typeAccount: 0x01, + typeCurrency: 0x10, + typeIssuer: 0x20, serialize: function (so, val) { // XXX for (var i = 0, l = val.length; i < l; i++) { + // Boundary + if (i) STInt8.serialize(so, this.typeBoundary); + for (var j = 0, l2 = val[i].length; j < l2; j++) { var entry = val[i][j]; var type = 0; - if (entry.account) type |= 0x01; - if (entry.currency) type |= 0x10; - if (entry.issuer) type |= 0x20; + if (entry.account) type |= this.typeAccount; + if (entry.currency) type |= this.typeCurrency; + if (entry.issuer) type |= this.typeIssuer; STInt8.serialize(so, type); @@ -268,10 +276,8 @@ var STPathSet = exports.PathSet = new SerializedType({ so.append(UInt160.from_json(entry.issuer).to_bytes()); } } - - if (j < l2) STInt8.serialize(so, 0xff); } - STInt8.serialize(so, 0x00); + STInt8.serialize(so, this.typeEnd); }, parse: function (so) { // XXX From b31c2ea6010e2f2f4fd57faaea8b48b941db106b Mon Sep 17 00:00:00 2001 From: Stefan Thomas Date: Mon, 11 Mar 2013 09:28:37 +0100 Subject: [PATCH 17/19] JS: Orderbook: Get current state when subscribing. --- src/js/orderbook.js | 4 ++-- src/js/remote.js | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/js/orderbook.js b/src/js/orderbook.js index c78674e07..00ac29b23 100644 --- a/src/js/orderbook.js +++ b/src/js/orderbook.js @@ -32,7 +32,7 @@ var OrderBook = function (remote, if (OrderBook.subscribe_events.indexOf(type) !== -1) { if (!self._subs && 'open' === self._remote._online_state) { self._remote.request_subscribe() - .books([self.to_json()]) + .books([self.to_json()], true) .request(); } self._subs += 1; @@ -54,7 +54,7 @@ var OrderBook = function (remote, this._remote.on('connect', function () { if (self._subs) { self._remote.request_subscribe() - .books([self.to_json()]) + .books([self.to_json()], true) .request(); } }); diff --git a/src/js/remote.js b/src/js/remote.js index 2f99748b2..fed025256 100644 --- a/src/js/remote.js +++ b/src/js/remote.js @@ -203,7 +203,7 @@ Request.prototype.rt_accounts = function (accounts) { return this.accounts(accounts, true); }; -Request.prototype.books = function (books) { +Request.prototype.books = function (books, state) { var procBooks = []; for (var i = 0, l = books.length; i < l; i++) { @@ -221,6 +221,8 @@ Request.prototype.books = function (books) { json["IssuerIn"] = UInt160.json_rewrite(book["IssuerIn"]); } + if (state || book["StateNow"]) json["StateNow"] = true; + procBooks.push(json); } this.message.books = procBooks; From 79e8734c54757223c82c23d5b58b805bdbdb6902 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Mon, 11 Mar 2013 02:14:25 -0700 Subject: [PATCH 18/19] Remove broken code. (Was commented out anyway.) --- src/cpp/ripple/Amount.cpp | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/src/cpp/ripple/Amount.cpp b/src/cpp/ripple/Amount.cpp index 122787e71..9b9530eb7 100644 --- a/src/cpp/ripple/Amount.cpp +++ b/src/cpp/ripple/Amount.cpp @@ -1249,25 +1249,6 @@ void STAmount::roundSelf() } } -#if 0 -std::string STAmount::getExtendedText() const -{ - if (mIsNative) - { - return str(boost::format("%s " SYSTEM_CURRENCY_CODE) % getText()); - } - else - { - return str(boost::format("%s/%s/%s %dE%d" ) - % getText() - % getHumanCurrency() - % RippleAddress::createHumanAccountID(mIssuer) - % getMantissa() - % getExponent()); - } -} -#endif - Json::Value STAmount::getJson(int) const { Json::Value elem(Json::objectValue); From 23fa7ab67e2d326c11cbf8a6388b0a8c50ffe01c Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Mon, 11 Mar 2013 02:18:32 -0700 Subject: [PATCH 19/19] Don't try to print ledger sequences using %d --- src/cpp/ripple/Ledger.cpp | 6 +++--- src/cpp/ripple/NetworkOPs.cpp | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/cpp/ripple/Ledger.cpp b/src/cpp/ripple/Ledger.cpp index 5ea9e318d..1403ea3ae 100644 --- a/src/cpp/ripple/Ledger.cpp +++ b/src/cpp/ripple/Ledger.cpp @@ -403,12 +403,12 @@ uint256 Ledger::getHash() void Ledger::saveAcceptedLedger(Job&, bool fromConsensus) { cLog(lsTRACE) << "saveAcceptedLedger " << (fromConsensus ? "fromConsensus " : "fromAcquire ") << getLedgerSeq(); - static boost::format ledgerExists("SELECT LedgerSeq FROM Ledgers INDEXED BY SeqLedger where LedgerSeq = %d;"); - static boost::format deleteLedger("DELETE FROM Ledgers WHERE LedgerSeq = %d;"); + static boost::format ledgerExists("SELECT LedgerSeq FROM Ledgers INDEXED BY SeqLedger where LedgerSeq = %u;"); + static boost::format deleteLedger("DELETE FROM Ledgers WHERE LedgerSeq = %u;"); static boost::format AcctTransExists("SELECT LedgerSeq FROM AccountTransactions WHERE TransID = '%s';"); static boost::format transExists("SELECT Status FROM Transactions WHERE TransID = '%s';"); static boost::format - updateTx("UPDATE Transactions SET LedgerSeq = %d, Status = '%c', TxnMeta = %s WHERE TransID = '%s';"); + updateTx("UPDATE Transactions SET LedgerSeq = %u, Status = '%c', TxnMeta = %s WHERE TransID = '%s';"); static boost::format addLedger("INSERT OR REPLACE INTO Ledgers " "(LedgerHash,LedgerSeq,PrevHash,TotalCoins,ClosingTime,PrevClosingTime,CloseTimeRes,CloseFlags," "AccountSetHash,TransSetHash) VALUES ('%s','%u','%s','%s','%u','%u','%d','%u','%s','%s');"); diff --git a/src/cpp/ripple/NetworkOPs.cpp b/src/cpp/ripple/NetworkOPs.cpp index ec5ab3474..40868a6f3 100644 --- a/src/cpp/ripple/NetworkOPs.cpp +++ b/src/cpp/ripple/NetworkOPs.cpp @@ -1065,7 +1065,7 @@ std::vector< std::pair > std::string sql = str(boost::format("SELECT LedgerSeq,Status,RawTxn,TxnMeta FROM Transactions where TransID in " "(SELECT TransID from AccountTransactions " - " WHERE Account = '%s' AND LedgerSeq <= '%d' AND LedgerSeq >= '%d' ) ORDER BY LedgerSeq DESC LIMIT 200;") + " WHERE Account = '%s' AND LedgerSeq <= '%u' AND LedgerSeq >= '%u' ) ORDER BY LedgerSeq DESC LIMIT 200;") % account.humanAccountID() % maxLedger % minLedger); { @@ -1101,7 +1101,7 @@ std::vector NetworkOPs::getAccountTxsB( std::string sql = str(boost::format("SELECT LedgerSeq, RawTxn,TxnMeta FROM Transactions where TransID in (SELECT TransID from AccountTransactions " - " WHERE Account = '%s' AND LedgerSeq <= '%d' AND LedgerSeq >= '%d' ) ORDER BY LedgerSeq DESC LIMIT 500;") + " WHERE Account = '%s' AND LedgerSeq <= '%u' AND LedgerSeq >= '%u' ) ORDER BY LedgerSeq DESC LIMIT 500;") % account.humanAccountID() % maxLedger % minLedger); { @@ -1145,7 +1145,7 @@ std::vector { std::vector accounts; std::string sql = str(boost::format - ("SELECT DISTINCT Account FROM AccountTransactions INDEXED BY AcctLgrIndex WHERE LedgerSeq = '%d';") + ("SELECT DISTINCT Account FROM AccountTransactions INDEXED BY AcctLgrIndex WHERE LedgerSeq = '%u';") % ledgerSeq); RippleAddress acct; {