mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-06 17:27:55 +00:00
Merge branch 'master' of github.com:jedmccaleb/NewCoin
This commit is contained in:
@@ -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
|
||||
@@ -1248,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);
|
||||
|
||||
339
src/cpp/ripple/AmountRound.cpp
Normal file
339
src/cpp/ripple/AmountRound.cpp
Normal file
@@ -0,0 +1,339 @@
|
||||
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
#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 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(lsDEBUG) << "canonicalize< " << value << ":" << offset << (roundUp ? " up" : " down");
|
||||
if (isNative)
|
||||
{
|
||||
if (offset < 0)
|
||||
{
|
||||
while (offset < -1)
|
||||
{
|
||||
value /= 10;
|
||||
++offset;
|
||||
}
|
||||
value += 10; // add before last divide
|
||||
value /= 10;
|
||||
++offset;
|
||||
}
|
||||
}
|
||||
else if (value > STAmount::cMaxValue)
|
||||
{
|
||||
while (value > (10 * STAmount::cMaxValue))
|
||||
{
|
||||
value /= 10;
|
||||
++offset;
|
||||
}
|
||||
value += 9; // add before last divide
|
||||
value /= 10;
|
||||
++offset;
|
||||
}
|
||||
cLog(lsDEBUG) << "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<int64>(v1.mValue), vv2 = static_cast<uint64>(v2.mValue);
|
||||
if (v1.mIsNegative)
|
||||
vv1 = -vv1;
|
||||
if (v2.mIsNegative)
|
||||
vv2 = -vv2;
|
||||
|
||||
if (ov1 < ov2)
|
||||
{
|
||||
while (ov1 < (ov2 - 1))
|
||||
{
|
||||
vv1 /= 10;
|
||||
++ov1;
|
||||
}
|
||||
if (roundUp)
|
||||
vv1 += 9;
|
||||
vv1 /= 10;
|
||||
++ov1;
|
||||
}
|
||||
|
||||
if (ov2 < ov1)
|
||||
{
|
||||
while (ov2 < (ov1 - 1))
|
||||
{
|
||||
vv2 /= 10;
|
||||
++ov2;
|
||||
}
|
||||
if (roundUp)
|
||||
vv2 += 9;
|
||||
vv2 /= 10;
|
||||
++ov2;
|
||||
}
|
||||
|
||||
int64 fv = vv1 + vv2;
|
||||
if (fv >= 0)
|
||||
{
|
||||
uint64 v = static_cast<uint64>(fv);
|
||||
canonicalizeRound(false, v, ov1, roundUp);
|
||||
return STAmount(v1.getFName(), v1.mCurrency, v1.mIssuer, v, ov1, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint64 v = static_cast<uint64>(-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<int64>(v1.mValue), vv2 = static_cast<uint64>(v2.mValue);
|
||||
|
||||
if (v1.mIsNegative)
|
||||
vv1 = -vv1;
|
||||
|
||||
if (!v2.mIsNegative)
|
||||
vv2 = -vv2;
|
||||
|
||||
if (ov1 < ov2)
|
||||
{
|
||||
while (ov1 < (ov2 - 1))
|
||||
{
|
||||
vv1 /= 10;
|
||||
++ov1;
|
||||
}
|
||||
if (roundUp)
|
||||
vv1 += 9;
|
||||
vv1 /= 10;
|
||||
++ov1;
|
||||
}
|
||||
|
||||
if (ov2 < ov1)
|
||||
{
|
||||
while (ov2 < (ov1 - 1))
|
||||
{
|
||||
vv2 /= 10;
|
||||
++ov2;
|
||||
}
|
||||
if (roundUp)
|
||||
vv2 += 9;
|
||||
vv2 /= 10;
|
||||
++ov2;
|
||||
}
|
||||
|
||||
int64 fv = vv1 + vv2;
|
||||
if (fv >= 0)
|
||||
{
|
||||
uint64 v = static_cast<uint64>(fv);
|
||||
canonicalizeRound(false, v, ov1, roundUp);
|
||||
return STAmount(v1.getFName(), v1.mCurrency, v1.mIssuer, v, ov1, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint64 v = static_cast<uint64>(-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,
|
||||
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))
|
||||
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
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
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()
|
||||
|
||||
// vim:ts=4
|
||||
@@ -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);
|
||||
|
||||
@@ -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');");
|
||||
|
||||
@@ -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));
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -152,8 +155,11 @@ 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;
|
||||
if (source.mLogged)
|
||||
return true;
|
||||
source.mLogged = true;
|
||||
}
|
||||
logDisconnect(source.getName());
|
||||
return true;
|
||||
|
||||
@@ -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; }
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
@@ -1068,7 +1065,7 @@ std::vector< std::pair<Transaction::pointer, TransactionMetaSet::pointer> >
|
||||
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);
|
||||
|
||||
{
|
||||
@@ -1104,7 +1101,7 @@ std::vector<NetworkOPs::txnMetaLedgerType> 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);
|
||||
|
||||
{
|
||||
@@ -1148,7 +1145,7 @@ std::vector<RippleAddress>
|
||||
{
|
||||
std::vector<RippleAddress> 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;
|
||||
{
|
||||
|
||||
@@ -427,6 +427,23 @@ 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);
|
||||
|
||||
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);
|
||||
|
||||
@@ -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"))
|
||||
@@ -110,7 +112,7 @@ public:
|
||||
jvResult["id"] = jvRequest["id"];
|
||||
}
|
||||
|
||||
theApp->getLoadManager().adjust(mLoadSource, 5);
|
||||
theApp->getLoadManager().adjust(mLoadSource, -5);
|
||||
return jvResult;
|
||||
}
|
||||
|
||||
@@ -131,7 +133,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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user