New Zero struct implements "compare with zero."

* Zero lets classes efficiently compare with 0, so
  you can use constructors like x < zero or y != zero.
* New BEAST_CONSTEXPR to handle Windows/C++11 differences
  regarding the constexpr specifier.
This commit is contained in:
Tom Swirly
2014-04-10 19:14:52 -04:00
committed by Vinnie Falco
parent 524f41177c
commit 64ee0d07d0
26 changed files with 591 additions and 425 deletions

View File

@@ -24,13 +24,8 @@
#ifndef BEAST_CONFIG_COMPILERCONFIG_H_INCLUDED #ifndef BEAST_CONFIG_COMPILERCONFIG_H_INCLUDED
#define BEAST_CONFIG_COMPILERCONFIG_H_INCLUDED #define BEAST_CONFIG_COMPILERCONFIG_H_INCLUDED
// This file has to work when included in a C source file.
#ifndef BEAST_CONFIG_PLATFORMCONFIG_H_INCLUDED
#error "PlatformConfig.h must come first!"
#endif
#include <assert.h> #include <assert.h>
#include "PlatformConfig.h"
// This file defines miscellaneous macros for debugging, assertions, etc. // This file defines miscellaneous macros for debugging, assertions, etc.
@@ -47,6 +42,15 @@
# define BEAST_CDECL # define BEAST_CDECL
#endif #endif
/** This macro fixes C++'s constexpr for VS2012, which doesn't understand it.
*/
#if BEAST_MSVC
# define BEAST_CONSTEXPR const
#else
# define BEAST_CONSTEXPR constexpr
#endif
// Debugging and assertion macros // Debugging and assertion macros
#if BEAST_LOG_ASSERTIONS || BEAST_DEBUG #if BEAST_LOG_ASSERTIONS || BEAST_DEBUG

View File

@@ -17,7 +17,7 @@
*/ */
//============================================================================== //==============================================================================
// MODULES: ../../crypto/impl/Sha256.cpp // MODULES: ../../crypto/impl/Sha256.cpp ../../container/impl/spookyv2.cpp
#if BEAST_INCLUDE_BEASTCONFIG #if BEAST_INCLUDE_BEASTCONFIG
#include "../../../BeastConfig.h" #include "../../../BeastConfig.h"
@@ -131,7 +131,7 @@ public:
static std::size_t const bytes = bits / 8; static std::size_t const bytes = bits / 8;
template <class Int> template <class Int>
static static
unsigned_integer unsigned_integer
from_number (Int v) from_number (Int v)
{ {
@@ -167,7 +167,7 @@ public:
{ {
for (std::size_t i (0); i < size; ++i) for (std::size_t i (0); i < size; ++i)
s << s <<
std::hex << std::hex <<
std::setfill ('0') << std::setfill ('0') <<
std::setw (2*sizeof(UInt)) << std::setw (2*sizeof(UInt)) <<
v.m_vec[i] v.m_vec[i]
@@ -293,7 +293,7 @@ public:
"i=" << std::setw(2) << i << " " << "i=" << std::setw(2) << i << " " <<
"sha256=0x" << d_ << " " << "sha256=0x" << d_ << " " <<
"hash=0x" << "hash=0x" <<
std::setfill ('0') << std::setfill ('0') <<
std::setw (2*sizeof(std::size_t)) << result std::setw (2*sizeof(std::size_t)) << result
; ;
pass(); pass();

View File

@@ -31,3 +31,4 @@
#include "tests/bassert.test.cpp" #include "tests/bassert.test.cpp"
#include "tests/empty_base_optimization.test.cpp" #include "tests/empty_base_optimization.test.cpp"
#include "tests/Zero.test.cpp"

View File

@@ -0,0 +1,140 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2014, Tom Ritchford <tom@swirly.com>
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 BEAST_UTILITY_ZERO_H_INCLUDED
#define BEAST_UTILITY_ZERO_H_INCLUDED
#include "../config/CompilerConfig.h"
namespace beast {
/** Zero allows classes to offer efficient comparisons to zero.
Zero is a struct to allow classes to efficiently compare with zero without
requiring an rvalue construction.
It's often the case that we have classes which combine a number and a unit.
In such cases, comparisons like t > 0 or t != 0 make sense, but comparisons
like t > 1 or t != 1 do not.
The class Zero allows such comparisons to be easily made.
The comparing class T either needs to have a method called signum() which
returns a positive number, 0, or a negative; or there needs to be a signum
function which resolves in the namespace which takes an instance of T and
returns a positive, zero or negative number.
*/
struct Zero {};
namespace {
static BEAST_CONSTEXPR Zero zero{};
} // namespace
/** The default implementation of signum calls the method on the class.
Calls to signum must be made from a namespace that does not include
overloads of the function.
*/
template <typename T>
auto signum(T const& t) -> decltype(t.signum()) {
return t.signum();
}
namespace detail {
namespace zero_helper {
template <class T>
auto call_signum (T const& t) -> decltype(signum(t)) {
return signum(t);
}
} // zero_helper
} // detail
/** Handle operators where T is on the left side using signum. */
template <typename T>
bool operator==(T const& t, Zero) {
return detail::zero_helper::call_signum(t) == 0;
}
template <typename T>
bool operator!=(T const& t, Zero) {
return detail::zero_helper::call_signum(t) != 0;
}
template <typename T>
bool operator>(T const& t, Zero) {
return detail::zero_helper::call_signum(t) > 0;
}
template <typename T>
bool operator>=(T const& t, Zero) {
return detail::zero_helper::call_signum(t) >= 0;
}
template <typename T>
bool operator<(T const& t, Zero) {
return detail::zero_helper::call_signum(t) < 0;
}
template <typename T>
bool operator<=(T const& t, Zero) {
return detail::zero_helper::call_signum(t) <= 0;
}
/** Handle operators where T is on the right side by reversing the operation,
so that T is on the left side.
*/
template <typename T>
bool operator==(Zero, T const& t) {
return t == zero;
}
template <typename T>
bool operator!=(Zero, T const& t) {
return t != zero;
}
template <typename T>
bool operator>(Zero, T const& t) {
return t < zero;
}
template <typename T>
bool operator>=(Zero, T const& t) {
return t <= zero;
}
template <typename T>
bool operator<(Zero, T const& t) {
return t > zero;
}
template <typename T>
bool operator<=(Zero, T const& t) {
return t >= zero;
}
} // beast
#endif

View File

@@ -0,0 +1,136 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2014, Nikolaos D. Bougalis <nikb@bougalis.net>
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 "../Zero.h"
#include "../../unit_test/suite.h"
namespace beast {
struct adl_tester {};
int signum (adl_tester) { return 0; }
namespace detail {
struct adl_tester2 {};
int signum (adl_tester2) { return 0; }
} // detail
class Zero_test : public beast::unit_test::suite
{
private:
struct IntegerWrapper
{
int value;
IntegerWrapper (int v)
: value (v)
{
}
int signum() const
{
return value;
}
};
public:
void expect_same(bool result, bool correct, char const* message)
{
expect(result == correct, message);
}
void
test_lhs_zero (IntegerWrapper x)
{
expect_same (x >= zero, x.signum () >= 0,
"lhs greater-than-or-equal-to");
expect_same (x > zero, x.signum () > 0,
"lhs greater than");
expect_same (x == zero, x.signum () == 0,
"lhs equal to");
expect_same (x != zero, x.signum () != 0,
"lhs not equal to");
expect_same (x < zero, x.signum () < 0,
"lhs less than");
expect_same (x <= zero, x.signum () <= 0,
"lhs less-than-or-equal-to");
}
void
test_lhs_zero ()
{
testcase ("lhs zero");
test_lhs_zero(-7);
test_lhs_zero(0);
test_lhs_zero(32);
}
void
test_rhs_zero (IntegerWrapper x)
{
expect_same (zero >= x, 0 >= x.signum (),
"rhs greater-than-or-equal-to");
expect_same (zero > x, 0 > x.signum (),
"rhs greater than");
expect_same (zero == x, 0 == x.signum (),
"rhs equal to");
expect_same (zero != x, 0 != x.signum (),
"rhs not equal to");
expect_same (zero < x, 0 < x.signum (),
"rhs less than");
expect_same (zero <= x, 0 <= x.signum (),
"rhs less-than-or-equal-to");
}
void
test_rhs_zero ()
{
testcase ("rhs zero");
test_rhs_zero(-4);
test_rhs_zero(0);
test_rhs_zero(64);
}
void
test_adl ()
{
expect (adl_tester{} == zero, "ADL failure!");
expect (detail::adl_tester2{} == zero, "ADL failure!");
}
void
run()
{
test_lhs_zero ();
test_rhs_zero ();
test_adl ();
}
};
BEAST_DEFINE_TESTSUITE(Zero, types, beast);
}

0
src/beast/tests.sh Normal file → Executable file
View File

View File

@@ -25,119 +25,6 @@
#include "../../beast/beast/utility/noexcept.h" #include "../../beast/beast/utility/noexcept.h"
#include "../../beast/beast/cxx14/type_traits.h" // <type_traits> #include "../../beast/beast/cxx14/type_traits.h" // <type_traits>
//------------------------------------------------------------------------------
struct Zero
{
Zero()
{
}
};
namespace {
static Zero const zero;
}
namespace detail {
namespace Zero_helpers {
template <class T>
int
get_signum (T const& t) noexcept
{
return signum(t);
}
}
}
/** Handle operators where T is on the left side using signum. */
template <class T>
bool operator==(T const& t, Zero)
{
return detail::Zero_helpers::get_signum(t) == 0;
}
template <class T>
bool operator!=(T const& t, Zero)
{
return detail::Zero_helpers::get_signum(t) != 0;
}
template <class T>
bool operator>(T const& t, Zero)
{
return detail::Zero_helpers::get_signum(t) > 0;
}
template <class T>
bool operator>=(T const& t, Zero)
{
return detail::Zero_helpers::get_signum(t) >= 0;
}
template <class T>
bool operator<(T const& t, Zero)
{
return detail::Zero_helpers::get_signum(t) < 0;
}
template <class T>
bool operator<=(T const& t, Zero)
{
return detail::Zero_helpers::get_signum(t) <= 0;
}
/** Handle operators where T is on the right side by reversing the operation,
so that T is on the left side.
*/
template <class T>
bool operator==(Zero, T const& t)
{
return t == zero;
}
template <class T>
bool operator!=(Zero, T const& t)
{
return t != zero;
}
template <class T>
bool operator>(Zero, T const& t)
{
return t < zero;
}
template <class T>
bool operator>=(Zero, T const& t)
{
return t <= zero;
}
template <class T>
bool operator<(Zero, T const& t)
{
return t > zero;
}
template <class T>
bool operator<=(Zero, T const& t)
{
return t >= zero;
}
/** Default implementation calls the method on the class.
Alternatively, signum may be overloaded in the same namespace and found
via argument dependent lookup.
*/
template <class T>
auto signum(T const& t) -> decltype(t.signum()) {
return t.signum();
}
//------------------------------------------------------------------------------
namespace ripple { namespace ripple {
namespace core { namespace core {

View File

@@ -39,7 +39,7 @@ struct Amounts
bool bool
empty() const noexcept empty() const noexcept
{ {
return ! in.isPositive() || ! out.isPositive(); return in <= zero || out <= zero;
} }
Amount in; Amount in;

View File

@@ -212,7 +212,7 @@ dir() const noexcept
m_offer.account(), m_offer.amount().out)); m_offer.account(), m_offer.amount().out));
// Check for unfunded offer // Check for unfunded offer
if (! owner_funds.isPositive()) if (owner_funds <= zero)
{ {
// If the owner's balance in the pristine view is the same, // If the owner's balance in the pristine view is the same,
// we haven't modified the balance and therefore the // we haven't modified the balance and therefore the
@@ -270,7 +270,7 @@ dir() const noexcept
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
/** /**
Does everything an OfferStream does, and: Does everything an OfferStream does, and:
- remove offers that became unfunded (if path is used) - remove offers that became unfunded (if path is used)
*/ */

View File

@@ -101,7 +101,7 @@ public:
1, // limit: 1 1, // limit: 1
1, 1); // 1 in, 1 out 1, 1); // 1 in, 1 out
ceil_in (q, ceil_in (q,
10, 10, // 10 in, 10 out 10, 10, // 10 in, 10 out
5, // limit: 5 5, // limit: 5
5, 5); // 5 in, 5 out 5, 5); // 5 in, 5 out
@@ -162,12 +162,12 @@ public:
// 1 in, 1 out: // 1 in, 1 out:
Quality q (Amounts (amount(1),amount(1))); Quality q (Amounts (amount(1),amount(1)));
ceil_out (q, ceil_out (q,
1, 1, // 1 in, 1 out 1, 1, // 1 in, 1 out
1, // limit 1 1, // limit 1
1, 1); // 1 in, 1 out 1, 1); // 1 in, 1 out
ceil_out (q, ceil_out (q,
10, 10, // 10 in, 10 out 10, 10, // 10 in, 10 out
5, // limit 5 5, // limit 5
5, 5); // 5 in, 5 out 5, 5); // 5 in, 5 out
@@ -230,7 +230,7 @@ public:
Amount const limit ( Amount const limit (
raw (4131113916555555, -16)); // .4131113916555555 raw (4131113916555555, -16)); // .4131113916555555
Amounts const result (q.ceil_out (value, limit)); Amounts const result (q.ceil_out (value, limit));
expect (! result.in.isZero()); expect (result.in != zero);
} }
} }

View File

@@ -215,7 +215,7 @@ void LedgerEntrySet::entryModify (SLE::ref sle)
{ {
case taaCACHED: case taaCACHED:
it->second.mAction = taaMODIFY; it->second.mAction = taaMODIFY;
// Fall through // Fall through
case taaCREATE: case taaCREATE:
@@ -1116,7 +1116,7 @@ STAmount LedgerEntrySet::rippleOwed (const uint160& uToAccountID, const uint160&
} }
else else
{ {
saBalance.zero (uCurrencyID, uToAccountID); saBalance.clear (uCurrencyID, uToAccountID);
WriteLog (lsDEBUG, LedgerEntrySet) << "rippleOwed: No credit line between " WriteLog (lsDEBUG, LedgerEntrySet) << "rippleOwed: No credit line between "
<< RippleAddress::createHumanAccountID (uFromAccountID) << RippleAddress::createHumanAccountID (uFromAccountID)
@@ -1149,7 +1149,7 @@ STAmount LedgerEntrySet::rippleLimit (const uint160& uToAccountID, const uint160
} }
else else
{ {
saLimit.zero (uCurrencyID, uToAccountID); saLimit.clear (uCurrencyID, uToAccountID);
#if 0 #if 0
// We could cut off coming here if we test for no line sooner. // We could cut off coming here if we test for no line sooner.
assert (false); assert (false);
@@ -1244,7 +1244,7 @@ STAmount LedgerEntrySet::rippleHolds (const uint160& uAccountID, const uint160&
if (!sleRippleState) if (!sleRippleState)
{ {
saBalance.zero (uCurrencyID, uIssuerID); saBalance.clear (uCurrencyID, uIssuerID);
} }
else if (uAccountID > uIssuerID) else if (uAccountID > uIssuerID)
{ {
@@ -1279,7 +1279,7 @@ STAmount LedgerEntrySet::accountHolds (const uint160& uAccountID, const uint160&
if (saBalance < uReserve) if (saBalance < uReserve)
{ {
saAmount.zero (); saAmount.clear ();
} }
else else
{ {
@@ -1525,8 +1525,8 @@ TER LedgerEntrySet::rippleCredit (const uint160& uSenderID, const uint160& uRece
std::uint32_t uFlags; std::uint32_t uFlags;
// YYY Could skip this if rippling in reverse. // YYY Could skip this if rippling in reverse.
if (saBefore.isPositive () // Sender balance was positive. if (saBefore > zero // Sender balance was positive.
&& !saBalance.isPositive () // Sender is zero or negative. && saBalance <= zero // Sender is zero or negative.
&& isSetBit ((uFlags = sleRippleState->getFieldU32 (sfFlags)), !bSenderHigh ? lsfLowReserve : lsfHighReserve) // Sender reserve is set. && isSetBit ((uFlags = sleRippleState->getFieldU32 (sfFlags)), !bSenderHigh ? lsfLowReserve : lsfHighReserve) // Sender reserve is set.
&& !isSetBit (uFlags, !bSenderHigh ? lsfLowNoRipple : lsfHighNoRipple) && !isSetBit (uFlags, !bSenderHigh ? lsfLowNoRipple : lsfHighNoRipple)
&& !sleRippleState->getFieldAmount (!bSenderHigh ? sfLowLimit : sfHighLimit) // Sender trust limit is 0. && !sleRippleState->getFieldAmount (!bSenderHigh ? sfLowLimit : sfHighLimit) // Sender trust limit is 0.
@@ -1617,7 +1617,7 @@ TER LedgerEntrySet::accountSend (const uint160& uSenderID, const uint160& uRecei
{ {
TER terResult = tesSUCCESS; TER terResult = tesSUCCESS;
assert (!saAmount.isNegative ()); assert (saAmount >= zero);
if (!saAmount || (uSenderID == uReceiverID)) if (!saAmount || (uSenderID == uReceiverID))
{ {

View File

@@ -258,7 +258,7 @@ public:
Not called for stand-alone mode. Not called for stand-alone mode.
*/ */
void setStateTimer (); void setStateTimer ();
void newLCL (int proposers, int convergeTime, uint256 const& ledgerHash); void newLCL (int proposers, int convergeTime, uint256 const& ledgerHash);
void needNetworkLedger () void needNetworkLedger ()
{ {
@@ -324,7 +324,7 @@ public:
void storeProposal (LedgerProposal::ref proposal, const RippleAddress& peerPublic); void storeProposal (LedgerProposal::ref proposal, const RippleAddress& peerPublic);
uint256 getConsensusLCL (); uint256 getConsensusLCL ();
void reportFeeChange (); void reportFeeChange ();
void updateLocalTx (Ledger::ref newValidLedger) override void updateLocalTx (Ledger::ref newValidLedger) override
{ {
m_localTX->sweep (newValidLedger); m_localTX->sweep (newValidLedger);
@@ -408,7 +408,7 @@ public:
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
// //
// Stoppable // Stoppable
void onStop () void onStop ()
{ {
m_heartbeatTimer.cancel(); m_heartbeatTimer.cancel();
@@ -891,7 +891,7 @@ void NetworkOPsImp::runTransactionQueue ()
tx.set_receivetimestamp (getNetworkTimeNC ()); // FIXME: This should be when we received it tx.set_receivetimestamp (getNetworkTimeNC ()); // FIXME: This should be when we received it
getApp ().getPeers ().foreach (send_if_not ( getApp ().getPeers ().foreach (send_if_not (
boost::make_shared<PackedMessage> (tx, protocol::mtTRANSACTION), boost::make_shared<PackedMessage> (tx, protocol::mtTRANSACTION),
peer_in_set(peers))); peer_in_set(peers)));
} }
else else
m_journal.debug << "recently relayed"; m_journal.debug << "recently relayed";
@@ -1022,7 +1022,7 @@ Transaction::pointer NetworkOPsImp::processTransactionCb (
tx.set_receivetimestamp (getNetworkTimeNC ()); // FIXME: This should be when we received it tx.set_receivetimestamp (getNetworkTimeNC ()); // FIXME: This should be when we received it
getApp ().getPeers ().foreach (send_if_not ( getApp ().getPeers ().foreach (send_if_not (
boost::make_shared<PackedMessage> (tx, protocol::mtTRANSACTION), boost::make_shared<PackedMessage> (tx, protocol::mtTRANSACTION),
peer_in_set(peers))); peer_in_set(peers)));
} }
} }
} }
@@ -1459,7 +1459,7 @@ int NetworkOPsImp::beginConsensus (uint256 const& networkClosed, Ledger::pointer
// Create a consensus object to get consensus on this ledger // Create a consensus object to get consensus on this ledger
assert (!mConsensus); assert (!mConsensus);
prevLedger->setImmutable (); prevLedger->setImmutable ();
mConsensus = LedgerConsensus::New (m_clock, *m_localTX, mConsensus = LedgerConsensus::New (m_clock, *m_localTX,
networkClosed, prevLedger, networkClosed, prevLedger,
m_ledgerMaster.getCurrentLedger ()->getCloseTimeNC ()); m_ledgerMaster.getCurrentLedger ()->getCloseTimeNC ());
@@ -2927,11 +2927,11 @@ void NetworkOPsImp::getBookPage (Ledger::pointer lpLedger, const uint160& uTaker
saOwnerFunds = lesActive.accountHolds (uOfferOwnerID, uTakerGetsCurrencyID, uTakerGetsIssuerID); saOwnerFunds = lesActive.accountHolds (uOfferOwnerID, uTakerGetsCurrencyID, uTakerGetsIssuerID);
// m_journal.info << boost::str(boost::format("getBookPage: saOwnerFunds=%s (new)") % saOwnerFunds.getFullText()); // m_journal.info << boost::str(boost::format("getBookPage: saOwnerFunds=%s (new)") % saOwnerFunds.getFullText());
if (saOwnerFunds.isNegative ()) if (saOwnerFunds < zero)
{ {
// Treat negative funds as zero. // Treat negative funds as zero.
saOwnerFunds.zero (); saOwnerFunds.clear ();
} }
} }
} }
@@ -2985,7 +2985,7 @@ void NetworkOPsImp::getBookPage (Ledger::pointer lpLedger, const uint160& uTaker
umBalance[uOfferOwnerID] = saOwnerFunds - saOwnerPays; umBalance[uOfferOwnerID] = saOwnerFunds - saOwnerPays;
if (!saOwnerFunds.isZero () || uOfferOwnerID == uTakerID) if (saOwnerFunds != zero || uOfferOwnerID == uTakerID)
{ {
// Only provide funded offers and offers of the taker. // Only provide funded offers and offers of the taker.
Json::Value& jvOf = jvOffers.append (jvOffer); Json::Value& jvOf = jvOffers.append (jvOffer);

View File

@@ -114,7 +114,7 @@ bool PathRequest::needsUpdate (bool newOnly, LedgerIndex index)
bool PathRequest::isValid (RippleLineCache::ref crCache) bool PathRequest::isValid (RippleLineCache::ref crCache)
{ {
ScopedLockType sl (mLock); ScopedLockType sl (mLock);
bValid = raSrcAccount.isSet () && raDstAccount.isSet () && saDstAmount.isPositive (); bValid = raSrcAccount.isSet () && raDstAccount.isSet () && saDstAmount > zero;
Ledger::pointer lrLedger = crCache->getLedger (); Ledger::pointer lrLedger = crCache->getLedger ();
if (bValid) if (bValid)
@@ -246,7 +246,7 @@ int PathRequest::parseJson (const Json::Value& jvParams, bool complete)
if (!saDstAmount.bSetJson (jvParams["destination_amount"]) || if (!saDstAmount.bSetJson (jvParams["destination_amount"]) ||
(saDstAmount.getCurrency ().isZero () && saDstAmount.getIssuer ().isNonZero ()) || (saDstAmount.getCurrency ().isZero () && saDstAmount.getIssuer ().isNonZero ()) ||
(saDstAmount.getCurrency () == CURRENCY_BAD) || (saDstAmount.getCurrency () == CURRENCY_BAD) ||
!saDstAmount.isPositive ()) saDstAmount <= zero)
{ {
jvStatus = rpcError (rpcDST_AMT_MALFORMED); jvStatus = rpcError (rpcDST_AMT_MALFORMED);
return PFR_PJ_INVALID; return PFR_PJ_INVALID;

View File

@@ -307,7 +307,7 @@ TER PathState::pushNode (
} }
else if ((isSetBit (sleBck->getFieldU32 (sfFlags), lsfRequireAuth) else if ((isSetBit (sleBck->getFieldU32 (sfFlags), lsfRequireAuth)
&& !isSetBit (sleRippleState->getFieldU32 (sfFlags), (bHigh ? lsfHighAuth : lsfLowAuth))) && !isSetBit (sleRippleState->getFieldU32 (sfFlags), (bHigh ? lsfHighAuth : lsfLowAuth)))
&& sleRippleState->getFieldAmount(sfBalance).isZero()) // CHECKME && sleRippleState->getFieldAmount(sfBalance) == zero) // CHECKME
{ {
WriteLog (lsWARNING, RippleCalc) << "pushNode: delay: can't receive IOUs from issuer without auth."; WriteLog (lsWARNING, RippleCalc) << "pushNode: delay: can't receive IOUs from issuer without auth.";
@@ -319,7 +319,7 @@ TER PathState::pushNode (
STAmount saOwed = lesEntries.rippleOwed (pnCur.uAccountID, pnBck.uAccountID, pnCur.uCurrencyID); STAmount saOwed = lesEntries.rippleOwed (pnCur.uAccountID, pnBck.uAccountID, pnCur.uCurrencyID);
STAmount saLimit; STAmount saLimit;
if (!saOwed.isPositive () if (saOwed <= zero
&& -saOwed >= (saLimit = lesEntries.rippleLimit (pnCur.uAccountID, pnBck.uAccountID, pnCur.uCurrencyID))) && -saOwed >= (saLimit = lesEntries.rippleLimit (pnCur.uAccountID, pnBck.uAccountID, pnCur.uCurrencyID)))
{ {
WriteLog (lsWARNING, RippleCalc) << boost::str (boost::format ("pushNode: dry: saOwed=%s saLimit=%s") WriteLog (lsWARNING, RippleCalc) << boost::str (boost::format ("pushNode: dry: saOwed=%s saLimit=%s")

View File

@@ -104,7 +104,7 @@ Pathfinder::Pathfinder (RippleLineCache::ref cache,
mLedger (cache->getLedger ()), mRLCache (cache) mLedger (cache->getLedger ()), mRLCache (cache)
{ {
if (((mSrcAccountID == mDstAccountID) && (mSrcCurrencyID == mDstAmount.getCurrency ())) || mDstAmount.isZero ()) if ((mSrcAccountID == mDstAccountID && mSrcCurrencyID == mDstAmount.getCurrency ()) || mDstAmount == zero)
{ {
// no need to send to same account with same currency, must send non-zero // no need to send to same account with same currency, must send non-zero
bValid = false; bValid = false;
@@ -373,7 +373,7 @@ STPathSet Pathfinder::filterPaths(int iMaxPaths, STPath& extraPath)
WriteLog (lsDEBUG, Pathfinder) << "Skipping a non-filling path: " << mCompletePaths[lqt.get<3> ()].getJson (0); WriteLog (lsDEBUG, Pathfinder) << "Skipping a non-filling path: " << mCompletePaths[lqt.get<3> ()].getJson (0);
} }
if (remaining.isPositive ()) if (remaining > zero)
{ {
WriteLog (lsINFO, Pathfinder) << "Paths could not send " << remaining << " of " << mDstAmount; WriteLog (lsINFO, Pathfinder) << "Paths could not send " << remaining << " of " << mDstAmount;
} }
@@ -409,7 +409,7 @@ boost::unordered_set<uint160> usAccountSourceCurrencies (
const STAmount& saBalance = rspEntry->getBalance (); const STAmount& saBalance = rspEntry->getBalance ();
// Filter out non // Filter out non
if (saBalance.isPositive () // Have IOUs to send. if (saBalance > zero // Have IOUs to send.
|| (rspEntry->getLimitPeer () // Peer extends credit. || (rspEntry->getLimitPeer () // Peer extends credit.
&& ((-saBalance) < rspEntry->getLimitPeer ()))) // Credit left. && ((-saBalance) < rspEntry->getLimitPeer ()))) // Credit left.
{ {
@@ -489,7 +489,7 @@ int Pathfinder::getPathsOut (RippleCurrency const& currencyID, const uint160& ac
if (currencyID != rspEntry->getLimit ().getCurrency ()) if (currencyID != rspEntry->getLimit ().getCurrency ())
nothing (); nothing ();
else if (!rspEntry->getBalance ().isPositive () && else if (rspEntry->getBalance () <= zero &&
(!rspEntry->getLimitPeer () (!rspEntry->getLimitPeer ()
|| -rspEntry->getBalance () >= rspEntry->getLimitPeer () || -rspEntry->getBalance () >= rspEntry->getLimitPeer ()
|| (bAuthRequired && !rspEntry->getAuth ()))) || (bAuthRequired && !rspEntry->getAuth ())))
@@ -657,7 +657,7 @@ void Pathfinder::addLink(
if ((uEndCurrency == rspEntry.getLimit().getCurrency()) && if ((uEndCurrency == rspEntry.getLimit().getCurrency()) &&
!currentPath.hasSeen(acctID, uEndCurrency, acctID)) !currentPath.hasSeen(acctID, uEndCurrency, acctID))
{ // path is for correct currency and has not been seen { // path is for correct currency and has not been seen
if (!rspEntry.getBalance().isPositive() if (rspEntry.getBalance() <= zero
&& (!rspEntry.getLimitPeer() && (!rspEntry.getLimitPeer()
|| -rspEntry.getBalance() >= rspEntry.getLimitPeer() || -rspEntry.getBalance() >= rspEntry.getLimitPeer()
|| (bRequireAuth && !rspEntry.getAuth()))) || (bRequireAuth && !rspEntry.getAuth())))

View File

@@ -29,7 +29,7 @@ namespace ripple {
SETUP_LOG (RippleCalc) SETUP_LOG (RippleCalc)
// VFALCO TODO Update the comment for this function, the argument list no // VFALCO TODO Update the comment for this function, the argument list no
// resembles the comment // resembles the comment
// //
// Provide a better explanation for what this function does. // Provide a better explanation for what this function does.
@@ -226,7 +226,7 @@ TER RippleCalc::calcNodeAdvance (
musUnfundedFound.insert(uOfferIndex); musUnfundedFound.insert(uOfferIndex);
continue; continue;
} }
else if (!saTakerPays.isPositive () || !saTakerGets.isPositive ()) else if (saTakerPays <= zero || saTakerGets <= zero)
{ {
// Offer has bad amounts. Offers should never have a bad amounts. // Offer has bad amounts. Offers should never have a bad amounts.
@@ -301,7 +301,7 @@ TER RippleCalc::calcNodeAdvance (
saOfferFunds = lesActive.accountFunds (uOfrOwnerID, saTakerGets); // Funds held. saOfferFunds = lesActive.accountFunds (uOfrOwnerID, saTakerGets); // Funds held.
if (!saOfferFunds.isPositive ()) if (saOfferFunds <= zero)
{ {
// Offer is unfunded. // Offer is unfunded.
WriteLog (lsTRACE, RippleCalc) << "calcNodeAdvance: unfunded offer"; WriteLog (lsTRACE, RippleCalc) << "calcNodeAdvance: unfunded offer";
@@ -388,7 +388,7 @@ TER RippleCalc::calcNodeDeliverRev (
bDirectRestart = true; // Restart at same quality. bDirectRestart = true; // Restart at same quality.
// YYY Note this gets zeroed on each increment, ideally only on first increment, then it could be a limit on the forward pass. // YYY Note this gets zeroed on each increment, ideally only on first increment, then it could be a limit on the forward pass.
saOutAct.zero (saOutReq); saOutAct.clear (saOutReq);
WriteLog (lsTRACE, RippleCalc) << boost::str (boost::format ("calcNodeDeliverRev> saOutAct=%s saOutReq=%s saPrvDlvReq=%s") WriteLog (lsTRACE, RippleCalc) << boost::str (boost::format ("calcNodeDeliverRev> saOutAct=%s saOutReq=%s saPrvDlvReq=%s")
% saOutAct % saOutAct
@@ -421,7 +421,8 @@ TER RippleCalc::calcNodeDeliverRev (
STAmount& saTakerGets = pnCur.saTakerGets; STAmount& saTakerGets = pnCur.saTakerGets;
STAmount& saRateMax = pnCur.saRateMax; STAmount& saRateMax = pnCur.saRateMax;
terResult = calcNodeAdvance (uNode, psCur, bMultiQuality || saOutAct.isZero(), true); // If needed, advance to next funded offer. terResult = calcNodeAdvance (uNode, psCur, bMultiQuality || saOutAct == zero, true);
// If needed, advance to next funded offer.
if (tesSUCCESS != terResult || !uOfferIndex) if (tesSUCCESS != terResult || !uOfferIndex)
{ {
@@ -595,7 +596,7 @@ TER RippleCalc::calcNodeDeliverRev (
STAmount saTakerGetsNew = saTakerGets - saOutPassAct; STAmount saTakerGetsNew = saTakerGets - saOutPassAct;
STAmount saTakerPaysNew = saTakerPays - saInPassAct; STAmount saTakerPaysNew = saTakerPays - saInPassAct;
if (saTakerPaysNew.isNegative () || saTakerGetsNew.isNegative ()) if (saTakerPaysNew < zero || saTakerGetsNew < zero)
{ {
WriteLog (lsWARNING, RippleCalc) << boost::str (boost::format ("calcNodeDeliverRev: NEGATIVE: saTakerPaysNew=%s saTakerGetsNew=%s") WriteLog (lsWARNING, RippleCalc) << boost::str (boost::format ("calcNodeDeliverRev: NEGATIVE: saTakerPaysNew=%s saTakerGetsNew=%s")
% saTakerPaysNew % saTakerGetsNew); % saTakerPaysNew % saTakerGetsNew);
@@ -683,8 +684,8 @@ TER RippleCalc::calcNodeDeliverFwd (
else else
bDirectRestart = true; // Restart at same quality. bDirectRestart = true; // Restart at same quality.
saInAct.zero (saInReq); saInAct.clear (saInReq);
saInFees.zero (saInReq); saInFees.clear (saInReq);
int loopCount = 0; int loopCount = 0;
@@ -700,7 +701,8 @@ TER RippleCalc::calcNodeDeliverFwd (
} }
// Determine values for pass to adjust saInAct, saInFees, and saCurDeliverAct // Determine values for pass to adjust saInAct, saInFees, and saCurDeliverAct
terResult = calcNodeAdvance (uNode, psCur, bMultiQuality || saInAct.isZero(), false); // If needed, advance to next funded offer. terResult = calcNodeAdvance (uNode, psCur, bMultiQuality || saInAct == zero, false);
// If needed, advance to next funded offer.
if (tesSUCCESS != terResult) if (tesSUCCESS != terResult)
{ {
@@ -738,8 +740,8 @@ TER RippleCalc::calcNodeDeliverFwd (
STAmount saInTotal = STAmount::mulRound (saInFunded, saInFeeRate, true); // Offer maximum in with fees. STAmount saInTotal = STAmount::mulRound (saInFunded, saInFeeRate, true); // Offer maximum in with fees.
STAmount saInRemaining = saInReq - saInAct - saInFees; STAmount saInRemaining = saInReq - saInAct - saInFees;
if (saInRemaining.isNegative()) if (saInRemaining < zero)
saInRemaining.zero(); saInRemaining.clear();
STAmount saInSum = std::min (saInTotal, saInRemaining); // In limited by remaining. STAmount saInSum = std::min (saInTotal, saInRemaining); // In limited by remaining.
STAmount saInPassAct = std::min (saTakerPays, STAmount::divRound (saInSum, saInFeeRate, true)); // In without fees. STAmount saInPassAct = std::min (saTakerPays, STAmount::divRound (saInSum, saInFeeRate, true)); // In without fees.
@@ -766,7 +768,7 @@ TER RippleCalc::calcNodeDeliverFwd (
% saInPassAct % saInPassAct
% saOutPassMax); % saOutPassMax);
if (!saTakerPays || !saInSum.isPositive()) // FIXME: We remove an offer if WE didn't want anything out of it? if (!saTakerPays || saInSum <= zero) // FIXME: We remove an offer if WE didn't want anything out of it?
{ {
WriteLog (lsDEBUG, RippleCalc) << "calcNodeDeliverFwd: Microscopic offer unfunded."; WriteLog (lsDEBUG, RippleCalc) << "calcNodeDeliverFwd: Microscopic offer unfunded.";
@@ -883,7 +885,7 @@ TER RippleCalc::calcNodeDeliverFwd (
STAmount saTakerGetsNew = saTakerGets - saOutPassAct; STAmount saTakerGetsNew = saTakerGets - saOutPassAct;
STAmount saTakerPaysNew = saTakerPays - saInPassAct; STAmount saTakerPaysNew = saTakerPays - saInPassAct;
if (saTakerPaysNew.isNegative () || saTakerGetsNew.isNegative ()) if (saTakerPaysNew < zero || saTakerGetsNew < zero)
{ {
WriteLog (lsWARNING, RippleCalc) << boost::str (boost::format ("calcNodeDeliverFwd: NEGATIVE: saTakerPaysNew=%s saTakerGetsNew=%s") WriteLog (lsWARNING, RippleCalc) << boost::str (boost::format ("calcNodeDeliverFwd: NEGATIVE: saTakerPaysNew=%s saTakerGetsNew=%s")
% saTakerPaysNew % saTakerGetsNew); % saTakerPaysNew % saTakerGetsNew);
@@ -899,7 +901,7 @@ TER RippleCalc::calcNodeDeliverFwd (
lesActive.entryModify (sleOffer); lesActive.entryModify (sleOffer);
if ((saOutPassAct == saOutFunded) || saTakerGetsNew.isZero()) if (saOutPassAct == saOutFunded || saTakerGetsNew == zero)
{ {
// Offer became unfunded. // Offer became unfunded.
@@ -1046,12 +1048,12 @@ void RippleCalc::calcNodeRipple (
% saPrvAct % saPrvAct
% saCurAct); % saCurAct);
assert (saCurReq.isPositive ()); // FIXME: saCurReq was zero assert (saCurReq > zero); // FIXME: saCurReq was zero
assert (saPrvReq.getCurrency () == saCurReq.getCurrency ()); assert (saPrvReq.getCurrency () == saCurReq.getCurrency ());
assert (saPrvReq.getCurrency () == saPrvAct.getCurrency ()); assert (saPrvReq.getCurrency () == saPrvAct.getCurrency ());
assert (saPrvReq.getIssuer () == saPrvAct.getIssuer ()); assert (saPrvReq.getIssuer () == saPrvAct.getIssuer ());
const bool bPrvUnlimited = saPrvReq.isNegative (); const bool bPrvUnlimited = saPrvReq < zero;
const STAmount saPrv = bPrvUnlimited ? STAmount (saPrvReq) : saPrvReq - saPrvAct; const STAmount saPrv = bPrvUnlimited ? STAmount (saPrvReq) : saPrvReq - saPrvAct;
const STAmount saCur = saCurReq - saCurAct; const STAmount saCur = saCurReq - saCurAct;
@@ -1187,11 +1189,11 @@ TER RippleCalc::calcNodeAccountRev (const unsigned int uNode, PathState& psCur,
% saPrvLimit); % saPrvLimit);
// Previous can redeem the owed IOUs it holds. // Previous can redeem the owed IOUs it holds.
const STAmount saPrvRedeemReq = saPrvOwed.isPositive () ? saPrvOwed : STAmount (saPrvOwed.getCurrency (), saPrvOwed.getIssuer ()); const STAmount saPrvRedeemReq = (saPrvOwed > zero) ? saPrvOwed : STAmount (saPrvOwed.getCurrency (), saPrvOwed.getIssuer ());
STAmount& saPrvRedeemAct = pnPrv.saRevRedeem; STAmount& saPrvRedeemAct = pnPrv.saRevRedeem;
// Previous can issue up to limit minus whatever portion of limit already used (not including redeemable amount). // Previous can issue up to limit minus whatever portion of limit already used (not including redeemable amount).
const STAmount saPrvIssueReq = saPrvOwed.isNegative () ? saPrvLimit + saPrvOwed : saPrvLimit; const STAmount saPrvIssueReq = (saPrvOwed < zero) ? saPrvLimit + saPrvOwed : saPrvLimit;
STAmount& saPrvIssueAct = pnPrv.saRevIssue; STAmount& saPrvIssueAct = pnPrv.saRevIssue;
// For !bPrvAccount // For !bPrvAccount
@@ -1222,7 +1224,7 @@ TER RippleCalc::calcNodeAccountRev (const unsigned int uNode, PathState& psCur,
assert (!saCurRedeemReq || (-saNxtOwed) >= saCurRedeemReq); // Current redeem req can't be more than IOUs on hand. assert (!saCurRedeemReq || (-saNxtOwed) >= saCurRedeemReq); // Current redeem req can't be more than IOUs on hand.
assert (!saCurIssueReq // If not issuing, fine. assert (!saCurIssueReq // If not issuing, fine.
|| !saNxtOwed.isNegative () // saNxtOwed >= 0: Sender not holding next IOUs, saNxtOwed < 0: Sender holding next IOUs. || saNxtOwed >= zero // saNxtOwed >= 0: Sender not holding next IOUs, saNxtOwed < 0: Sender holding next IOUs.
|| -saNxtOwed == saCurRedeemReq); // If issue req, then redeem req must consume all owed. || -saNxtOwed == saCurRedeemReq); // If issue req, then redeem req must consume all owed.
if (!uNode) if (!uNode)
@@ -1262,11 +1264,11 @@ TER RippleCalc::calcNodeAccountRev (const unsigned int uNode, PathState& psCur,
} }
else else
{ {
saPrvRedeemAct.zero (saPrvRedeemReq); saPrvRedeemAct.clear (saPrvRedeemReq);
} }
// Calculate issuing. // Calculate issuing.
saPrvIssueAct.zero (saPrvIssueReq); saPrvIssueAct.clear (saPrvIssueReq);
if (saCurWantedReq != saCurWantedAct // Need more. if (saCurWantedReq != saCurWantedAct // Need more.
&& saPrvIssueReq) // Will accept IOUs from prevous. && saPrvIssueReq) // Will accept IOUs from prevous.
@@ -1290,8 +1292,8 @@ TER RippleCalc::calcNodeAccountRev (const unsigned int uNode, PathState& psCur,
else else
{ {
// ^|account --> ACCOUNT --> account // ^|account --> ACCOUNT --> account
saPrvRedeemAct.zero (saPrvRedeemReq); saPrvRedeemAct.clear (saPrvRedeemReq);
saPrvIssueAct.zero (saPrvIssueReq); saPrvIssueAct.clear (saPrvIssueReq);
// redeem (part 1) -> redeem // redeem (part 1) -> redeem
if (saCurRedeemReq // Next wants IOUs redeemed. if (saCurRedeemReq // Next wants IOUs redeemed.
@@ -1364,12 +1366,12 @@ TER RippleCalc::calcNodeAccountRev (const unsigned int uNode, PathState& psCur,
// Note: deliver is always issue as ACCOUNT is the issuer for the offer input. // Note: deliver is always issue as ACCOUNT is the issuer for the offer input.
WriteLog (lsTRACE, RippleCalc) << boost::str (boost::format ("calcNodeAccountRev: account --> ACCOUNT --> offer")); WriteLog (lsTRACE, RippleCalc) << boost::str (boost::format ("calcNodeAccountRev: account --> ACCOUNT --> offer"));
saPrvRedeemAct.zero (saPrvRedeemReq); saPrvRedeemAct.clear (saPrvRedeemReq);
saPrvIssueAct.zero (saPrvIssueReq); saPrvIssueAct.clear (saPrvIssueReq);
// redeem -> deliver/issue. // redeem -> deliver/issue.
if (saPrvOwed.isPositive () // Previous has IOUs to redeem. if (saPrvOwed > zero // Previous has IOUs to redeem.
&& saCurDeliverReq) // Need some issued. && saCurDeliverReq) // Need some issued.
{ {
// Rate : 1.0 : transfer_rate // Rate : 1.0 : transfer_rate
calcNodeRipple (QUALITY_ONE, lesActive.rippleTransferRate (uCurAccountID), saPrvRedeemReq, saCurDeliverReq, saPrvRedeemAct, saCurDeliverAct, uRateMax); calcNodeRipple (QUALITY_ONE, lesActive.rippleTransferRate (uCurAccountID), saPrvRedeemReq, saCurDeliverReq, saPrvRedeemAct, saCurDeliverAct, uRateMax);
@@ -1407,14 +1409,15 @@ TER RippleCalc::calcNodeAccountRev (const unsigned int uNode, PathState& psCur,
% psCur.saOutAct % psCur.saOutAct
% psCur.saOutReq); % psCur.saOutReq);
if (!saCurWantedReq.isPositive ()) if (saCurWantedReq <= zero)
{ {
// TEMPORARY emergency fix // TEMPORARY emergency fix
WriteLog (lsFATAL, RippleCalc) << "CurWantReq was not positive"; WriteLog (lsFATAL, RippleCalc) << "CurWantReq was not positive";
return tefEXCEPTION; return tefEXCEPTION;
} }
assert (saCurWantedReq.isPositive ()); // FIXME: We got one of these assert (saCurWantedReq > zero); // FIXME: We got one of these
// TR notes: can only be a race condition if true!
// Rate: quality in : 1.0 // Rate: quality in : 1.0
calcNodeRipple (uQualityIn, QUALITY_ONE, saPrvDeliverReq, saCurWantedReq, saPrvDeliverAct, saCurWantedAct, uRateMax); calcNodeRipple (uQualityIn, QUALITY_ONE, saPrvDeliverReq, saCurWantedReq, saPrvDeliverAct, saCurWantedAct, uRateMax);
@@ -1576,7 +1579,7 @@ TER RippleCalc::calcNodeAccountFwd (
saCurRedeemAct = saCurRedeemReq; saCurRedeemAct = saCurRedeemReq;
if (!psCur.saInReq.isNegative ()) if (psCur.saInReq >= zero)
{ {
// Limit by send max. // Limit by send max.
saCurRedeemAct = std::min (saCurRedeemAct, psCur.saInReq - psCur.saInAct); saCurRedeemAct = std::min (saCurRedeemAct, psCur.saInReq - psCur.saInAct);
@@ -1588,7 +1591,7 @@ TER RippleCalc::calcNodeAccountFwd (
? saCurIssueReq ? saCurIssueReq
: STAmount (saCurIssueReq); : STAmount (saCurIssueReq);
if (!!saCurIssueAct && !psCur.saInReq.isNegative ()) if (!!saCurIssueAct && psCur.saInReq >= zero)
{ {
// Limit by send max. // Limit by send max.
saCurIssueAct = std::min (saCurIssueAct, psCur.saInReq - psCur.saInAct - saCurRedeemAct); saCurIssueAct = std::min (saCurIssueAct, psCur.saInReq - psCur.saInAct - saCurRedeemAct);
@@ -1640,8 +1643,8 @@ TER RippleCalc::calcNodeAccountFwd (
// account --> ACCOUNT --> account // account --> ACCOUNT --> account
WriteLog (lsTRACE, RippleCalc) << boost::str (boost::format ("calcNodeAccountFwd: account --> ACCOUNT --> account")); WriteLog (lsTRACE, RippleCalc) << boost::str (boost::format ("calcNodeAccountFwd: account --> ACCOUNT --> account"));
saCurRedeemAct.zero (saCurRedeemReq); saCurRedeemAct.clear (saCurRedeemReq);
saCurIssueAct.zero (saCurIssueReq); saCurIssueAct.clear (saCurIssueReq);
// Previous redeem part 1: redeem -> redeem // Previous redeem part 1: redeem -> redeem
if (saPrvRedeemReq && saCurRedeemReq) // Previous wants to redeem. if (saPrvRedeemReq && saCurRedeemReq) // Previous wants to redeem.
@@ -1696,7 +1699,7 @@ TER RippleCalc::calcNodeAccountFwd (
// Non-XRP, current node is the issuer. // Non-XRP, current node is the issuer.
WriteLog (lsTRACE, RippleCalc) << boost::str (boost::format ("calcNodeAccountFwd: account --> ACCOUNT --> offer")); WriteLog (lsTRACE, RippleCalc) << boost::str (boost::format ("calcNodeAccountFwd: account --> ACCOUNT --> offer"));
saCurDeliverAct.zero (saCurDeliverReq); saCurDeliverAct.clear (saCurDeliverReq);
// redeem -> issue/deliver. // redeem -> issue/deliver.
// Previous wants to redeem. // Previous wants to redeem.
@@ -1727,7 +1730,7 @@ TER RippleCalc::calcNodeAccountFwd (
saCurDeliverAct = saCurDeliverReq; saCurDeliverAct = saCurDeliverReq;
// If limited, then limit by send max and available. // If limited, then limit by send max and available.
if (!psCur.saInReq.isNegative ()) if (psCur.saInReq >= zero)
{ {
// Limit by send max. // Limit by send max.
saCurDeliverAct = std::min (saCurDeliverAct, psCur.saInReq - psCur.saInAct); saCurDeliverAct = std::min (saCurDeliverAct, psCur.saInReq - psCur.saInAct);
@@ -1784,8 +1787,8 @@ TER RippleCalc::calcNodeAccountFwd (
// offer --> ACCOUNT --> account // offer --> ACCOUNT --> account
WriteLog (lsTRACE, RippleCalc) << boost::str (boost::format ("calcNodeAccountFwd: offer --> ACCOUNT --> account")); WriteLog (lsTRACE, RippleCalc) << boost::str (boost::format ("calcNodeAccountFwd: offer --> ACCOUNT --> account"));
saCurRedeemAct.zero (saCurRedeemReq); saCurRedeemAct.clear (saCurRedeemReq);
saCurIssueAct.zero (saCurIssueReq); saCurIssueAct.clear (saCurIssueReq);
// deliver -> redeem // deliver -> redeem
if (saPrvDeliverReq && saCurRedeemReq) // Previous wants to deliver and can current redeem. if (saPrvDeliverReq && saCurRedeemReq) // Previous wants to deliver and can current redeem.
@@ -1817,7 +1820,7 @@ TER RippleCalc::calcNodeAccountFwd (
// deliver/redeem -> deliver/issue. // deliver/redeem -> deliver/issue.
WriteLog (lsTRACE, RippleCalc) << boost::str (boost::format ("calcNodeAccountFwd: offer --> ACCOUNT --> offer")); WriteLog (lsTRACE, RippleCalc) << boost::str (boost::format ("calcNodeAccountFwd: offer --> ACCOUNT --> offer"));
saCurDeliverAct.zero (saCurDeliverReq); saCurDeliverAct.clear (saCurDeliverReq);
if (saPrvDeliverReq // Previous wants to deliver if (saPrvDeliverReq // Previous wants to deliver
&& saCurIssueReq) // Current wants issue. && saCurIssueReq) // Current wants issue.
@@ -1937,10 +1940,10 @@ void RippleCalc::pathNext (PathState::ref psrCur, const bool bMultiQuality, cons
{ {
PathState::Node& pnCur = psrCur->vpnNodes[uIndex]; PathState::Node& pnCur = psrCur->vpnNodes[uIndex];
pnCur.saRevRedeem.zero (); pnCur.saRevRedeem.clear ();
pnCur.saRevIssue.zero (); pnCur.saRevIssue.clear ();
pnCur.saRevDeliver.zero (); pnCur.saRevDeliver.clear ();
pnCur.saFwdDeliver.zero (); pnCur.saFwdDeliver.clear ();
} }
psrCur->terStatus = calcNodeRev (uLast, *psrCur, bMultiQuality); psrCur->terStatus = calcNodeRev (uLast, *psrCur, bMultiQuality);
@@ -2139,12 +2142,12 @@ TER RippleCalc::rippleCalc (
pspCur->saInAct = saMaxAmountAct; // Update to current amount processed. pspCur->saInAct = saMaxAmountAct; // Update to current amount processed.
pspCur->saOutAct = saDstAmountAct; pspCur->saOutAct = saDstAmountAct;
CondLog (pspCur->saInReq.isPositive () && pspCur->saInAct >= pspCur->saInReq, lsWARNING, RippleCalc) CondLog (pspCur->saInReq > zero && pspCur->saInAct >= pspCur->saInReq, lsWARNING, RippleCalc)
<< boost::str (boost::format ("rippleCalc: DONE: saInAct=%s saInReq=%s") << boost::str (boost::format ("rippleCalc: DONE: saInAct=%s saInReq=%s")
% pspCur->saInAct % pspCur->saInAct
% pspCur->saInReq); % pspCur->saInReq);
assert (pspCur->saInReq.isNegative () || pspCur->saInAct < pspCur->saInReq); // Error if done. assert (pspCur->saInReq < zero || pspCur->saInAct < pspCur->saInReq); // Error if done.
CondLog (pspCur->saOutAct >= pspCur->saOutReq, lsWARNING, RippleCalc) CondLog (pspCur->saOutAct >= pspCur->saOutReq, lsWARNING, RippleCalc)
<< boost::str (boost::format ("rippleCalc: ALREADY DONE: saOutAct=%s saOutReq=%s") << boost::str (boost::format ("rippleCalc: ALREADY DONE: saOutAct=%s saOutReq=%s")

View File

@@ -105,7 +105,7 @@ enum
is expressed as a multiplier based on the current ledger's fee schedule. is expressed as a multiplier based on the current ledger's fee schedule.
JSON fields JSON fields
"Fee" The fee paid by the transaction. Omitted when the client "Fee" The fee paid by the transaction. Omitted when the client
wants the fee filled in. wants the fee filled in.
@@ -342,7 +342,7 @@ Json::Value RPCHandler::transactionSign (Json::Value params,
if (!bOffline) if (!bOffline)
{ {
SLE::pointer sleAccountRoot = mNetOps->getSLEi (lSnapshot, SLE::pointer sleAccountRoot = mNetOps->getSLEi (lSnapshot,
Ledger::getAccountRootIndex (raSrcAddressID.getAccountID ())); Ledger::getAccountRootIndex (raSrcAddressID.getAccountID ()));
if (!sleAccountRoot) if (!sleAccountRoot)
@@ -474,7 +474,7 @@ Json::Value RPCHandler::transactionSign (Json::Value params,
try try
{ {
// FIXME: For performance, should use asynch interface // FIXME: For performance, should use asynch interface
tpTrans = mNetOps->submitTransactionSync (tpTrans, tpTrans = mNetOps->submitTransactionSync (tpTrans,
mRole == Config::ADMIN, true, bFailHard, bSubmit); mRole == Config::ADMIN, true, bFailHard, bSubmit);
if (!tpTrans) if (!tpTrans)
@@ -771,7 +771,7 @@ Json::Value RPCHandler::doAccountCurrencies (Json::Value params, Resource::Charg
{ {
recvCurrencies.append (STAmount::createHumanCurrency (c)); recvCurrencies.append (STAmount::createHumanCurrency (c));
} }
return jvResult; return jvResult;
} }
@@ -1520,7 +1520,7 @@ Json::Value RPCHandler::doBookOffers (Json::Value params, Resource::Charge& load
{ {
if (! params ["taker"].isString ()) if (! params ["taker"].isString ())
return RPC::expected_field_error ("taker", "string"); return RPC::expected_field_error ("taker", "string");
if (! raTakerID.setAccountID (params ["taker"].asString ())) if (! raTakerID.setAccountID (params ["taker"].asString ()))
return RPC::invalid_field_error ("taker"); return RPC::invalid_field_error ("taker");
} }
@@ -1674,7 +1674,7 @@ Json::Value RPCHandler::doRipplePathFind (Json::Value params, Resource::Charge&
// Parse saDstAmount. // Parse saDstAmount.
!params.isMember ("destination_amount") !params.isMember ("destination_amount")
|| !saDstAmount.bSetJson (params["destination_amount"]) || !saDstAmount.bSetJson (params["destination_amount"])
|| !saDstAmount.isPositive() || saDstAmount <= zero
|| (!!saDstAmount.getCurrency () && (!saDstAmount.getIssuer () || ACCOUNT_ONE == saDstAmount.getIssuer ()))) || (!!saDstAmount.getCurrency () && (!saDstAmount.getIssuer () || ACCOUNT_ONE == saDstAmount.getIssuer ())))
{ {
WriteLog (lsINFO, RPCHandler) << "Bad destination_amount."; WriteLog (lsINFO, RPCHandler) << "Bad destination_amount.";

View File

@@ -32,7 +32,7 @@ bool OfferCreateTransactor::isValidOffer (
std::unordered_set<uint160, beast::hardened_hash<uint160>>& usAccountTouched, std::unordered_set<uint160, beast::hardened_hash<uint160>>& usAccountTouched,
STAmount& saOfferFunds) STAmount& saOfferFunds)
{ {
if (sleOffer->isFieldPresent (sfExpiration) && if (sleOffer->isFieldPresent (sfExpiration) &&
sleOffer->getFieldU32 (sfExpiration) <= mEngine->getLedger ()->getParentCloseTimeNC ()) sleOffer->getFieldU32 (sfExpiration) <= mEngine->getLedger ()->getParentCloseTimeNC ())
{ {
// Offer is expired. Expired offers are considered unfunded. Delete it. // Offer is expired. Expired offers are considered unfunded. Delete it.
@@ -42,7 +42,7 @@ bool OfferCreateTransactor::isValidOffer (
return false; return false;
} }
if (uOfferOwnerID == uTakerAccountID) if (uOfferOwnerID == uTakerAccountID)
{ {
// Would take own offer. Consider old offer expired. Delete it. // Would take own offer. Consider old offer expired. Delete it.
@@ -52,8 +52,8 @@ bool OfferCreateTransactor::isValidOffer (
return false; return false;
} }
if (!saOfferGets.isPositive () || !saOfferPays.isPositive ()) if (saOfferGets <= zero || saOfferPays <= zero)
{ {
// Offer has bad amounts. Consider offer expired. Delete it. // Offer has bad amounts. Consider offer expired. Delete it.
m_journal.warning << "isValidOffer: BAD OFFER:" << m_journal.warning << "isValidOffer: BAD OFFER:" <<
@@ -64,13 +64,13 @@ bool OfferCreateTransactor::isValidOffer (
return false; return false;
} }
m_journal.trace << m_journal.trace <<
"isValidOffer: saOfferPays=" << saOfferPays.getFullText (); "isValidOffer: saOfferPays=" << saOfferPays.getFullText ();
saOfferFunds = mEngine->view ().accountFunds (uOfferOwnerID, saOfferPays); saOfferFunds = mEngine->view ().accountFunds (uOfferOwnerID, saOfferPays);
if (!saOfferFunds.isPositive ()) if (saOfferFunds <= zero)
{ {
// Offer is unfunded, possibly due to previous balance action. // Offer is unfunded, possibly due to previous balance action.
m_journal.debug << "isValidOffer: offer unfunded: delete"; m_journal.debug << "isValidOffer: offer unfunded: delete";
@@ -107,7 +107,7 @@ bool OfferCreateTransactor::canCross (
bool& isUnfunded, bool& isUnfunded,
TER& terResult) const TER& terResult) const
{ {
if (!saTakerFunds.isPositive ()) if (saTakerFunds <= zero)
{ {
// Taker is out of funds. Don't create the offer. // Taker is out of funds. Don't create the offer.
isUnfunded = true; isUnfunded = true;
@@ -115,7 +115,7 @@ bool OfferCreateTransactor::canCross (
return false; return false;
} }
if (!saSubTakerPays.isPositive() || !saSubTakerGets.isPositive()) if (saSubTakerPays <= zero || saSubTakerGets <= zero)
{ {
// Offer is completely consumed // Offer is completely consumed
terResult = tesSUCCESS; terResult = tesSUCCESS;
@@ -159,11 +159,11 @@ bool OfferCreateTransactor::canCross (
@param saTakerGets Limit for taker to get. @param saTakerGets Limit for taker to get.
@param saTakerPaid Actual amount the taker paid @param saTakerPaid Actual amount the taker paid
@param saTakerGot Actual amount the taker got @param saTakerGot Actual amount the taker got
@param saTakerIssuerFee Actual @param saTakerIssuerFee Actual
@param saOfferIssuerFee Actual @param saOfferIssuerFee Actual
@note Buy vs. Sell semantics: @note Buy vs. Sell semantics:
In Ripple, placed offers are always executed at the rate at which they were In Ripple, placed offers are always executed at the rate at which they were
placed. However, the offer we are processing hasn't been placed yet and it placed. However, the offer we are processing hasn't been placed yet and it
can cross with offers that have. Such crossing offers can be consumed by can cross with offers that have. Such crossing offers can be consumed by
@@ -174,7 +174,7 @@ bool OfferCreateTransactor::canCross (
are consumed. are consumed.
First, consider the case where a user is trying to place an offer to buy First, consider the case where a user is trying to place an offer to buy
1 BTC for 700 USD: 1 BTC for 700 USD:
If an offer to giving 0.5 BTC for 300 USD is on the books, the offers cross If an offer to giving 0.5 BTC for 300 USD is on the books, the offers cross
and under buy semantics the user buys 0.5 BTC for 300 USD (less than the and under buy semantics the user buys 0.5 BTC for 300 USD (less than the
350 USD he was willing to pay) and the offer is adjusted and placed on the 350 USD he was willing to pay) and the offer is adjusted and placed on the
@@ -201,8 +201,8 @@ bool OfferCreateTransactor::applyOffer (
{ {
saOfferGets.throwComparable (saTakerFunds); saOfferGets.throwComparable (saTakerFunds);
assert (saOfferFunds.isPositive () && saTakerFunds.isPositive ()); // Both must have funds. assert (saOfferFunds > zero && saTakerFunds > zero); // Both must have funds.
assert (saOfferGets.isPositive () && saOfferPays.isPositive ()); // Must not be a null offer. assert (saOfferGets > zero && saOfferPays > zero); // Must not be a null offer.
// Available = limited by funds. // Available = limited by funds.
// Limit offerer funds available, by transfer fees. // Limit offerer funds available, by transfer fees.
@@ -292,7 +292,7 @@ bool OfferCreateTransactor::applyOffer (
? saTakerFunds - saTakerPaid // Not enough funds to cover fee, stiff issuer the rounding error. ? saTakerFunds - saTakerPaid // Not enough funds to cover fee, stiff issuer the rounding error.
: saTakerCost - saTakerPaid; : saTakerCost - saTakerPaid;
WriteLog (lsINFO, STAmount) << "applyOffer: saTakerIssuerFee=" << saTakerIssuerFee.getFullText (); WriteLog (lsINFO, STAmount) << "applyOffer: saTakerIssuerFee=" << saTakerIssuerFee.getFullText ();
assert (!saTakerIssuerFee.isNegative ()); assert (saTakerIssuerFee >= zero);
} }
if (uOfferPaysRate == QUALITY_ONE) if (uOfferPaysRate == QUALITY_ONE)
@@ -314,17 +314,17 @@ bool OfferCreateTransactor::applyOffer (
return saTakerGot >= saOfferPaysAvailable; // True, if consumed offer. return saTakerGot >= saOfferPaysAvailable; // True, if consumed offer.
} }
/** Take as much as possible. /** Take as much as possible.
We adjusts account balances and charges fees on top to taker. We adjusts account balances and charges fees on top to taker.
@param uBookBase The order book to take against. @param uBookBase The order book to take against.
@param saTakerPays What the taker offers (w/ issuer) @param saTakerPays What the taker offers (w/ issuer)
@param saTakerGets What the taker wanted (w/ issuer) @param saTakerGets What the taker wanted (w/ issuer)
@param saTakerPaid What taker could have paid including saved not including @param saTakerPaid What taker could have paid including saved not including
fees. To reduce an offer. fees. To reduce an offer.
@param saTakerGot What taker got not including fees. To reduce an offer. @param saTakerGot What taker got not including fees. To reduce an offer.
@param bUnfunded if tesSUCCESS, consider offer unfunded after taking. @param bUnfunded if tesSUCCESS, consider offer unfunded after taking.
@return tesSUCCESS, terNO_ACCOUNT, telFAILED_PROCESSING, or @return tesSUCCESS, terNO_ACCOUNT, telFAILED_PROCESSING, or
tecFAILED_PROCESSING tecFAILED_PROCESSING
*/ */
TER OfferCreateTransactor::takeOffers ( TER OfferCreateTransactor::takeOffers (
@@ -361,7 +361,7 @@ TER OfferCreateTransactor::takeOffers (
TER terResult = temUNCERTAIN; TER terResult = temUNCERTAIN;
// Offers that became unfunded. // Offers that became unfunded.
std::unordered_set<uint256, beast::hardened_hash<uint256>> usOfferUnfundedBecame; std::unordered_set<uint256, beast::hardened_hash<uint256>> usOfferUnfundedBecame;
// Accounts touched. // Accounts touched.
std::unordered_set<uint160, beast::hardened_hash<uint160>> usAccountTouched; std::unordered_set<uint160, beast::hardened_hash<uint160>> usAccountTouched;
@@ -400,8 +400,8 @@ TER OfferCreateTransactor::takeOffers (
"/" << "/" <<
RippleAddress::createHumanAccountID (saTakerPays.getIssuer()) << RippleAddress::createHumanAccountID (saTakerPays.getIssuer()) <<
"' - XRP - '" << "' - XRP - '" <<
STAmount::createHumanCurrency(saTakerGets.getCurrency ()) << STAmount::createHumanCurrency(saTakerGets.getCurrency ()) <<
"/" << "/" <<
RippleAddress::createHumanAccountID (saTakerGets.getIssuer()) << RippleAddress::createHumanAccountID (saTakerGets.getIssuer()) <<
"'"; "'";
} }
@@ -416,27 +416,27 @@ TER OfferCreateTransactor::takeOffers (
std::uint64_t uTipQuality = directBookIter.getCurrentQuality(); std::uint64_t uTipQuality = directBookIter.getCurrentQuality();
#ifdef RIPPLE_AUTOBRIDGE #ifdef RIPPLE_AUTOBRIDGE
if (bridgeBookIn && bridgeBookIn->nextOffer() && if (bridgeBookIn && bridgeBookIn->nextOffer() &&
bridgeBookOut && bridgeBookOut->nextOffer()) bridgeBookOut && bridgeBookOut->nextOffer())
{ {
STAmount bridgeIn = STAmount::setRate (bridgeBookIn->getCurrentQuality()); STAmount bridgeIn = STAmount::setRate (bridgeBookIn->getCurrentQuality());
STAmount bridgeOut = STAmount::setRate (bridgeBookOut->getCurrentQuality()); STAmount bridgeOut = STAmount::setRate (bridgeBookOut->getCurrentQuality());
m_journal.error << m_journal.error <<
"The direct quality is: " << STAmount::setRate (uTipQuality); "The direct quality is: " << STAmount::setRate (uTipQuality);
m_journal.error << m_journal.error <<
"The bridge-to-XRP quality is: " << bridgeIn; "The bridge-to-XRP quality is: " << bridgeIn;
m_journal.error << m_journal.error <<
"The bridge-from-XRP quality is: " << bridgeOut; "The bridge-from-XRP quality is: " << bridgeOut;
m_journal.error << m_journal.error <<
"The bridge synthetic quality is: " << "The bridge synthetic quality is: " <<
STAmount::multiply (bridgeIn, bridgeOut, CURRENCY_ONE, ACCOUNT_ONE); STAmount::multiply (bridgeIn, bridgeOut, CURRENCY_ONE, ACCOUNT_ONE);
} }
#endif #endif
if (!canCross( if (!canCross(
saTakerFunds, saTakerFunds,
saSubTakerPays, saSubTakerPays,
@@ -461,7 +461,7 @@ TER OfferCreateTransactor::takeOffers (
m_journal.warning << m_journal.warning <<
"takeOffers: offer not found : " << offerIndex; "takeOffers: offer not found : " << offerIndex;
usMissingOffers.insert (missingOffer_t ( usMissingOffers.insert (missingOffer_t (
directBookIter.getCurrentIndex (), directBookIter.getCurrentIndex (),
directBookIter.getCurrentDirectory ())); directBookIter.getCurrentDirectory ()));
continue; continue;
@@ -600,12 +600,12 @@ TER OfferCreateTransactor::takeOffers (
// TODO check the synthetic case here (to ensure there // TODO check the synthetic case here (to ensure there
// is no corruption) // is no corruption)
if (!saOfferPays.isPositive () || !saOfferGets.isPositive ()) if (saOfferPays <= zero || saOfferGets <= zero)
{ {
m_journal.warning << m_journal.warning <<
"takeOffers: ILLEGAL OFFER RESULT."; "takeOffers: ILLEGAL OFFER RESULT.";
bUnfunded = true; bUnfunded = true;
terResult = bOpenLedger terResult = bOpenLedger
? telFAILED_PROCESSING ? telFAILED_PROCESSING
: tecFAILED_PROCESSING; : tecFAILED_PROCESSING;
} }
@@ -757,7 +757,7 @@ TER OfferCreateTransactor::doApply ()
// FIXME understand why we use SequenceNext instead of current transaction // FIXME understand why we use SequenceNext instead of current transaction
// sequence to determine the transaction. Why is the offer seuqnce // sequence to determine the transaction. Why is the offer seuqnce
// number insufficient? // number insufficient?
std::uint32_t const uAccountSequenceNext = mTxnAccount->getFieldU32 (sfSequence); std::uint32_t const uAccountSequenceNext = mTxnAccount->getFieldU32 (sfSequence);
std::uint32_t const uSequence = mTxn.getSequence (); std::uint32_t const uSequence = mTxn.getSequence ();
@@ -811,7 +811,7 @@ TER OfferCreateTransactor::doApply ()
terResult = temBAD_OFFER; terResult = temBAD_OFFER;
} }
else if (!saTakerPays.isPositive () || !saTakerGets.isPositive ()) else if (saTakerPays <= zero || saTakerGets <= zero)
{ {
m_journal.warning << m_journal.warning <<
"Malformed offer: bad amount"; "Malformed offer: bad amount";
@@ -840,7 +840,7 @@ TER OfferCreateTransactor::doApply ()
terResult = temBAD_ISSUER; terResult = temBAD_ISSUER;
} }
else if (!lesActive.accountFunds (mTxnAccountID, saTakerGets).isPositive ()) else if (lesActive.accountFunds (mTxnAccountID, saTakerGets) <= zero)
{ {
m_journal.warning << m_journal.warning <<
"delay: Offers must be at least partially funded."; "delay: Offers must be at least partially funded.";
@@ -878,7 +878,7 @@ TER OfferCreateTransactor::doApply ()
// might not even have been an offer - we don't care. // might not even have been an offer - we don't care.
if (m_journal.warning) m_journal.warning << if (m_journal.warning) m_journal.warning <<
"offer not found: " << "offer not found: " <<
RippleAddress::createHumanAccountID (mTxnAccountID) << RippleAddress::createHumanAccountID (mTxnAccountID) <<
" : " << uCancelSequence << " : " << uCancelSequence <<
" : " << uCancelIndex.ToString (); " : " << uCancelIndex.ToString ();
@@ -886,11 +886,11 @@ TER OfferCreateTransactor::doApply ()
} }
// We definitely know the time that the parent ledger closed but we do not // We definitely know the time that the parent ledger closed but we do not
// know the closing time of the ledger under construction. // know the closing time of the ledger under construction.
// FIXME: Make sure that expiration is documented in terms of the close time // FIXME: Make sure that expiration is documented in terms of the close time
// of the previous ledger. // of the previous ledger.
bool bExpired = bool bExpired =
bHaveExpiration && bHaveExpiration &&
(mEngine->getLedger ()->getParentCloseTimeNC () >= uExpiration); (mEngine->getLedger ()->getParentCloseTimeNC () >= uExpiration);
// If all is well and this isn't an offer to XRP, then we make sure we are // If all is well and this isn't an offer to XRP, then we make sure we are
@@ -911,7 +911,7 @@ TER OfferCreateTransactor::doApply ()
else if (isSetBit (sleTakerPays->getFieldU32 (sfFlags), lsfRequireAuth)) else if (isSetBit (sleTakerPays->getFieldU32 (sfFlags), lsfRequireAuth))
{ {
SLE::pointer sleRippleState (mEngine->entryCache ( SLE::pointer sleRippleState (mEngine->entryCache (
ltRIPPLE_STATE, ltRIPPLE_STATE,
Ledger::getRippleStateIndex ( Ledger::getRippleStateIndex (
mTxnAccountID, uPaysIssuerID, uPaysCurrency))); mTxnAccountID, uPaysIssuerID, uPaysCurrency)));
@@ -923,7 +923,7 @@ TER OfferCreateTransactor::doApply ()
if (!sleRippleState) if (!sleRippleState)
{ {
terResult = isSetBit (mParams, tapRETRY) terResult = isSetBit (mParams, tapRETRY)
? terNO_LINE ? terNO_LINE
: tecNO_LINE; : tecNO_LINE;
} }
@@ -986,7 +986,7 @@ TER OfferCreateTransactor::doApply ()
if (m_journal.debug) if (m_journal.debug)
{ {
m_journal.debug << m_journal.debug <<
"takeOffers: AFTER saTakerPays=" << "takeOffers: AFTER saTakerPays=" <<
saTakerPays.getFullText (); saTakerPays.getFullText ();
m_journal.debug << m_journal.debug <<
"takeOffers: AFTER saTakerGets=" << "takeOffers: AFTER saTakerGets=" <<
@@ -1019,11 +1019,11 @@ TER OfferCreateTransactor::doApply ()
// nothing to do // nothing to do
nothing (); nothing ();
} }
else if (saTakerPays.isNegative () || saTakerGets.isNegative ()) else if (saTakerPays < zero || saTakerGets < zero)
{ {
// If ledger is not final, can vote no. // If ledger is not final, can vote no.
// When we are processing an open ledger, failures are local and we charge no fee; // When we are processing an open ledger, failures are local and we charge no fee;
// otherwise we must claim a fee (even if they do nothing else due to an error) // otherwise we must claim a fee (even if they do nothing else due to an error)
// to prevent a DoS. // to prevent a DoS.
terResult = bOpenLedger ? telFAILED_PROCESSING : tecFAILED_PROCESSING; terResult = bOpenLedger ? telFAILED_PROCESSING : tecFAILED_PROCESSING;
} }
@@ -1033,11 +1033,11 @@ TER OfferCreateTransactor::doApply ()
lesActive.swapWith (lesCheckpoint); // Restore with just fees paid. lesActive.swapWith (lesCheckpoint); // Restore with just fees paid.
} }
else if ( else if (
!saTakerPays.isPositive() // Wants nothing more. saTakerPays <= zero // Wants nothing more.
|| !saTakerGets.isPositive() // Offering nothing more. || saTakerGets <= zero // Offering nothing more.
|| bImmediateOrCancel // Do not persist. || bImmediateOrCancel // Do not persist.
|| !lesActive.accountFunds (mTxnAccountID, saTakerGets).isPositive () // Not funded. || lesActive.accountFunds (mTxnAccountID, saTakerGets) <= zero // Not funded.
|| bUnfunded) // Consider unfunded. || bUnfunded) // Consider unfunded.
{ {
// Complete as is. // Complete as is.
nothing (); nothing ();
@@ -1047,7 +1047,7 @@ TER OfferCreateTransactor::doApply ()
// If we are here, the signing account had an insufficient reserve // If we are here, the signing account had an insufficient reserve
// *prior* to our processing. We use the prior balance to simplify // *prior* to our processing. We use the prior balance to simplify
// client writing and make the user experience better. // client writing and make the user experience better.
if (bOpenLedger) // Ledger is not final, can vote no. if (bOpenLedger) // Ledger is not final, can vote no.
{ {
// Hope for more reserve to come in or more offers to consume. If we // Hope for more reserve to come in or more offers to consume. If we
@@ -1077,12 +1077,12 @@ TER OfferCreateTransactor::doApply ()
{ {
// We need to place the remainder of the offer into its order book. // We need to place the remainder of the offer into its order book.
if (m_journal.trace) m_journal.trace << if (m_journal.trace) m_journal.trace <<
"offer not fully consumed:" << "offer not fully consumed:" <<
" saTakerPays=" << saTakerPays.getFullText () << " saTakerPays=" << saTakerPays.getFullText () <<
" saTakerGets=" << saTakerGets.getFullText (); " saTakerGets=" << saTakerGets.getFullText ();
// Add offer to owner's directory. // Add offer to owner's directory.
terResult = lesActive.dirAdd (uOwnerNode, terResult = lesActive.dirAdd (uOwnerNode,
Ledger::getOwnerDirIndex (mTxnAccountID), uLedgerIndex, Ledger::getOwnerDirIndex (mTxnAccountID), uLedgerIndex,
BIND_TYPE (&Ledger::ownerDirDescriber, P_1, P_2, mTxnAccountID)); BIND_TYPE (&Ledger::ownerDirDescriber, P_1, P_2, mTxnAccountID));
@@ -1109,7 +1109,7 @@ TER OfferCreateTransactor::doApply ()
// Add offer to order book. // Add offer to order book.
terResult = lesActive.dirAdd (uBookNode, uDirectory, uLedgerIndex, terResult = lesActive.dirAdd (uBookNode, uDirectory, uLedgerIndex,
BIND_TYPE (&Ledger::qualityDirDescriber, P_1, P_2, BIND_TYPE (&Ledger::qualityDirDescriber, P_1, P_2,
saTakerPays.getCurrency (), uPaysIssuerID, saTakerPays.getCurrency (), uPaysIssuerID,
saTakerGets.getCurrency (), uGetsIssuerID, uRate)); saTakerGets.getCurrency (), uGetsIssuerID, uRate));
} }
@@ -1187,15 +1187,15 @@ TER OfferCreateTransactor::doApply ()
{ {
SLE::pointer sleDirectory ( SLE::pointer sleDirectory (
lesActive.entryCache (ltDIR_NODE, indexes.second)); lesActive.entryCache (ltDIR_NODE, indexes.second));
if (sleDirectory) if (sleDirectory)
{ {
STVector256 svIndexes = sleDirectory->getFieldV256 (sfIndexes); STVector256 svIndexes = sleDirectory->getFieldV256 (sfIndexes);
std::vector<uint256>& vuiIndexes = svIndexes.peekValue(); std::vector<uint256>& vuiIndexes = svIndexes.peekValue();
auto it = std::find ( auto it = std::find (
vuiIndexes.begin (), vuiIndexes.end (), indexes.first); vuiIndexes.begin (), vuiIndexes.end (), indexes.first);
if (it != vuiIndexes.end ()) if (it != vuiIndexes.end ())
{ {
vuiIndexes.erase (it); vuiIndexes.erase (it);

View File

@@ -38,12 +38,12 @@ TER PaymentTransactor::doApply ()
mTxnAccountID, mTxnAccountID,
saDstAmount.getMantissa (), saDstAmount.getMantissa (),
saDstAmount.getExponent (), saDstAmount.getExponent (),
saDstAmount.isNegative ()); saDstAmount < zero);
uint160 const uSrcCurrency = saMaxAmount.getCurrency (); uint160 const uSrcCurrency = saMaxAmount.getCurrency ();
uint160 const uDstCurrency = saDstAmount.getCurrency (); uint160 const uDstCurrency = saDstAmount.getCurrency ();
bool const bXRPDirect = uSrcCurrency.isZero () && uDstCurrency.isZero (); bool const bXRPDirect = uSrcCurrency.isZero () && uDstCurrency.isZero ();
m_journal.trace << m_journal.trace <<
"saMaxAmount=" << saMaxAmount.getFullText () << "saMaxAmount=" << saMaxAmount.getFullText () <<
" saDstAmount=" << saDstAmount.getFullText (); " saDstAmount=" << saDstAmount.getFullText ();
@@ -52,7 +52,7 @@ TER PaymentTransactor::doApply ()
if (uTxFlags & tfPaymentMask) if (uTxFlags & tfPaymentMask)
{ {
m_journal.trace << m_journal.trace <<
"Malformed transaction: Invalid flags set."; "Malformed transaction: Invalid flags set.";
return temINVALID_FLAG; return temINVALID_FLAG;
@@ -64,14 +64,14 @@ TER PaymentTransactor::doApply ()
return temDST_NEEDED; return temDST_NEEDED;
} }
else if (bMax && !saMaxAmount.isPositive ()) else if (bMax && saMaxAmount <= zero)
{ {
m_journal.trace << m_journal.trace <<
"Malformed transaction: bad max amount: " << saMaxAmount.getFullText (); "Malformed transaction: bad max amount: " << saMaxAmount.getFullText ();
return temBAD_AMOUNT; return temBAD_AMOUNT;
} }
else if (!saDstAmount.isPositive ()) else if (saDstAmount <= zero)
{ {
m_journal.trace << m_journal.trace <<
"Malformed transaction: bad dst amount: " << saDstAmount.getFullText (); "Malformed transaction: bad dst amount: " << saDstAmount.getFullText ();
@@ -87,7 +87,7 @@ TER PaymentTransactor::doApply ()
} }
else if (mTxnAccountID == uDstAccountID && uSrcCurrency == uDstCurrency && !bPaths) else if (mTxnAccountID == uDstAccountID && uSrcCurrency == uDstCurrency && !bPaths)
{ {
m_journal.trace << m_journal.trace <<
"Malformed transaction: Redundant transaction:" << "Malformed transaction: Redundant transaction:" <<
" src=" << mTxnAccountID.ToString () << " src=" << mTxnAccountID.ToString () <<
" dst=" << uDstAccountID.ToString () << " dst=" << uDstAccountID.ToString () <<
@@ -159,7 +159,7 @@ TER PaymentTransactor::doApply ()
// Make retry work smaller, by rejecting this. // Make retry work smaller, by rejecting this.
m_journal.trace << m_journal.trace <<
"Delay transaction: Partial payment not allowed to create account."; "Delay transaction: Partial payment not allowed to create account.";
// Another transaction could create the account and then this // Another transaction could create the account and then this
// transaction would succeed. // transaction would succeed.
@@ -282,7 +282,7 @@ TER PaymentTransactor::doApply ()
if (transResultInfo (terResult, strToken, strHuman)) if (transResultInfo (terResult, strToken, strHuman))
{ {
m_journal.trace << m_journal.trace <<
strToken << ": " << strHuman; strToken << ": " << strHuman;
} }
else else

View File

@@ -45,7 +45,7 @@ TER RegularKeySetTransactor::doApply ()
return temINVALID_FLAG; return temINVALID_FLAG;
} }
if (mFeeDue.isZero ()) if (mFeeDue == zero)
{ {
mTxnAccount->setFlag (lsfPasswordSpent); mTxnAccount->setFlag (lsfPasswordSpent);
} }

View File

@@ -79,7 +79,7 @@ Transactor::Transactor (
SerializedTransaction const& txn, SerializedTransaction const& txn,
TransactionEngineParams params, TransactionEngineParams params,
TransactionEngine* engine, TransactionEngine* engine,
beast::Journal journal) beast::Journal journal)
: mTxn (txn) : mTxn (txn)
, mEngine (engine) , mEngine (engine)
, mParams (params) , mParams (params)
@@ -110,13 +110,13 @@ TER Transactor::payFee ()
// Only check fee is sufficient when the ledger is open. // Only check fee is sufficient when the ledger is open.
if (isSetBit (mParams, tapOPEN_LEDGER) && saPaid < mFeeDue) if (isSetBit (mParams, tapOPEN_LEDGER) && saPaid < mFeeDue)
{ {
m_journal.trace << "Insufficient fee paid: " << m_journal.trace << "Insufficient fee paid: " <<
saPaid.getText () << "/" << mFeeDue.getText (); saPaid.getText () << "/" << mFeeDue.getText ();
return telINSUF_FEE_P; return telINSUF_FEE_P;
} }
if (saPaid.isNegative () || !saPaid.isNative ()) if (saPaid < zero || !saPaid.isNative ())
return temBAD_FEE; return temBAD_FEE;
if (!saPaid) return tesSUCCESS; if (!saPaid) return tesSUCCESS;
@@ -262,7 +262,7 @@ TER Transactor::apply ()
// Restructure this to avoid the dependency on LedgerBase::mLock // Restructure this to avoid the dependency on LedgerBase::mLock
Ledger::ScopedLockType sl (mEngine->getLedger ()->mLock); Ledger::ScopedLockType sl (mEngine->getLedger ()->mLock);
mTxnAccount = mEngine->entryCache (ltACCOUNT_ROOT, mTxnAccount = mEngine->entryCache (ltACCOUNT_ROOT,
Ledger::getAccountRootIndex (mTxnAccountID)); Ledger::getAccountRootIndex (mTxnAccountID));
calculateFee (); calculateFee ();
@@ -274,7 +274,7 @@ TER Transactor::apply ()
{ {
if (mustHaveValidAccount ()) if (mustHaveValidAccount ())
{ {
m_journal.trace << m_journal.trace <<
"apply: delay transaction: source account does not exist " << "apply: delay transaction: source account does not exist " <<
mTxn.getSourceAccount ().humanAccountID (); mTxn.getSourceAccount ().humanAccountID ();
return terNO_ACCOUNT; return terNO_ACCOUNT;

View File

@@ -26,7 +26,7 @@ TER TrustSetTransactor::doApply ()
STAmount const saLimitAmount (mTxn.getFieldAmount (sfLimitAmount)); STAmount const saLimitAmount (mTxn.getFieldAmount (sfLimitAmount));
bool const bQualityIn (mTxn.isFieldPresent (sfQualityIn)); bool const bQualityIn (mTxn.isFieldPresent (sfQualityIn));
bool const bQualityOut (mTxn.isFieldPresent (sfQualityOut)); bool const bQualityOut (mTxn.isFieldPresent (sfQualityOut));
uint160 const uCurrencyID (saLimitAmount.getCurrency ()); uint160 const uCurrencyID (saLimitAmount.getCurrency ());
uint160 uDstAccountID (saLimitAmount.getIssuer ()); uint160 uDstAccountID (saLimitAmount.getIssuer ());
@@ -60,7 +60,7 @@ TER TrustSetTransactor::doApply ()
if (bSetAuth && !isSetBit (mTxnAccount->getFieldU32 (sfFlags), lsfRequireAuth)) if (bSetAuth && !isSetBit (mTxnAccount->getFieldU32 (sfFlags), lsfRequireAuth))
{ {
m_journal.trace << m_journal.trace <<
"Retry: Auth not required."; "Retry: Auth not required.";
return tefNO_AUTH_REQUIRED; return tefNO_AUTH_REQUIRED;
} }
@@ -73,9 +73,9 @@ TER TrustSetTransactor::doApply ()
return temBAD_LIMIT; return temBAD_LIMIT;
} }
if (saLimitAmount.isNegative ()) if (saLimitAmount < zero)
{ {
m_journal.trace << m_journal.trace <<
"Malformed transaction: Negative credit limit."; "Malformed transaction: Negative credit limit.";
return temBAD_LIMIT; return temBAD_LIMIT;
} }
@@ -83,7 +83,7 @@ TER TrustSetTransactor::doApply ()
// Check if destination makes sense. // Check if destination makes sense.
if (!uDstAccountID || uDstAccountID == ACCOUNT_ONE) if (!uDstAccountID || uDstAccountID == ACCOUNT_ONE)
{ {
m_journal.trace << m_journal.trace <<
"Malformed transaction: Destination account not specified."; "Malformed transaction: Destination account not specified.";
return temDST_NEEDED; return temDST_NEEDED;
@@ -92,13 +92,13 @@ TER TrustSetTransactor::doApply ()
if (mTxnAccountID == uDstAccountID) if (mTxnAccountID == uDstAccountID)
{ {
SLE::pointer selDelete ( SLE::pointer selDelete (
mEngine->entryCache (ltRIPPLE_STATE, mEngine->entryCache (ltRIPPLE_STATE,
Ledger::getRippleStateIndex ( Ledger::getRippleStateIndex (
mTxnAccountID, uDstAccountID, uCurrencyID))); mTxnAccountID, uDstAccountID, uCurrencyID)));
if (selDelete) if (selDelete)
{ {
m_journal.warning << m_journal.warning <<
"Clearing redundant line."; "Clearing redundant line.";
return mEngine->view ().trustDelete ( return mEngine->view ().trustDelete (
@@ -117,16 +117,16 @@ TER TrustSetTransactor::doApply ()
if (!sleDst) if (!sleDst)
{ {
m_journal.trace << m_journal.trace <<
"Delay transaction: Destination account does not exist."; "Delay transaction: Destination account does not exist.";
return tecNO_DST; return tecNO_DST;
} }
std::uint32_t const uOwnerCount (mTxnAccount->getFieldU32 (sfOwnerCount)); std::uint32_t const uOwnerCount (mTxnAccount->getFieldU32 (sfOwnerCount));
// The reserve required to create the line. // The reserve required to create the line.
std::uint64_t const uReserveCreate = std::uint64_t const uReserveCreate =
(uOwnerCount < 2) (uOwnerCount < 2)
? 0 ? 0
: mEngine->getLedger ()->getReserve (uOwnerCount + 1); : mEngine->getLedger ()->getReserve (uOwnerCount + 1);
STAmount saLimitAllow = saLimitAmount; STAmount saLimitAllow = saLimitAmount;
@@ -233,7 +233,7 @@ TER TrustSetTransactor::doApply ()
std::uint32_t const uFlagsIn (sleRippleState->getFieldU32 (sfFlags)); std::uint32_t const uFlagsIn (sleRippleState->getFieldU32 (sfFlags));
std::uint32_t uFlagsOut (uFlagsIn); std::uint32_t uFlagsOut (uFlagsIn);
if (bSetNoRipple && !bClearNoRipple && (bHigh ? saHighBalance : saLowBalance).isGEZero()) if (bSetNoRipple && !bClearNoRipple && (bHigh ? saHighBalance : saLowBalance) >= zero)
{ {
uFlagsOut |= (bHigh ? lsfHighNoRipple : lsfLowNoRipple); uFlagsOut |= (bHigh ? lsfHighNoRipple : lsfLowNoRipple);
} }
@@ -249,12 +249,12 @@ TER TrustSetTransactor::doApply ()
bool const bLowReserveSet = uLowQualityIn || uLowQualityOut || bool const bLowReserveSet = uLowQualityIn || uLowQualityOut ||
isSetBit (uFlagsOut, lsfLowNoRipple) || isSetBit (uFlagsOut, lsfLowNoRipple) ||
!!saLowLimit || saLowBalance.isPositive (); !!saLowLimit || saLowBalance > zero;
bool const bLowReserveClear = !bLowReserveSet; bool const bLowReserveClear = !bLowReserveSet;
bool const bHighReserveSet = uHighQualityIn || uHighQualityOut || bool const bHighReserveSet = uHighQualityIn || uHighQualityOut ||
isSetBit (uFlagsOut, lsfHighNoRipple) || isSetBit (uFlagsOut, lsfHighNoRipple) ||
!!saHighLimit || saHighBalance.isPositive (); !!saHighLimit || saHighBalance > zero;
bool const bHighReserveClear = !bHighReserveSet; bool const bHighReserveClear = !bHighReserveSet;
bool const bDefault = bLowReserveClear && bHighReserveClear; bool const bDefault = bLowReserveClear && bHighReserveClear;
@@ -321,7 +321,7 @@ TER TrustSetTransactor::doApply ()
{ {
m_journal.trace << m_journal.trace <<
"Delay transaction: Insufficent reserve to add trust line."; "Delay transaction: Insufficent reserve to add trust line.";
// Another transaction could provide XRP to the account and then // Another transaction could provide XRP to the account and then
// this transaction would succeed. // this transaction would succeed.
terResult = tecINSUF_RESERVE_LINE; terResult = tecINSUF_RESERVE_LINE;
@@ -339,13 +339,13 @@ TER TrustSetTransactor::doApply ()
&& (!bQualityIn || !uQualityIn) // Not setting quality in or setting default quality in. && (!bQualityIn || !uQualityIn) // Not setting quality in or setting default quality in.
&& (!bQualityOut || !uQualityOut)) // Not setting quality out or setting default quality out. && (!bQualityOut || !uQualityOut)) // Not setting quality out or setting default quality out.
{ {
m_journal.trace << m_journal.trace <<
"Redundant: Setting non-existent ripple line to defaults."; "Redundant: Setting non-existent ripple line to defaults.";
return tecNO_LINE_REDUNDANT; return tecNO_LINE_REDUNDANT;
} }
else if (mPriorBalance.getNValue () < uReserveCreate) // Reserve is not scaled by load. else if (mPriorBalance.getNValue () < uReserveCreate) // Reserve is not scaled by load.
{ {
m_journal.trace << m_journal.trace <<
"Delay transaction: Line does not exist. Insufficent reserve to create line."; "Delay transaction: Line does not exist. Insufficent reserve to create line.";
// Another transaction could create the account and then this transaction would succeed. // Another transaction could create the account and then this transaction would succeed.
@@ -358,10 +358,10 @@ TER TrustSetTransactor::doApply ()
else else
{ {
// Zero balance in currency. // Zero balance in currency.
STAmount saBalance (STAmount (uCurrencyID, ACCOUNT_ONE)); STAmount saBalance (STAmount (uCurrencyID, ACCOUNT_ONE));
m_journal.trace << m_journal.trace <<
"doTrustSet: Creating ripple line: " << "doTrustSet: Creating ripple line: " <<
Ledger::getRippleStateIndex (mTxnAccountID, uDstAccountID, uCurrencyID).ToString (); Ledger::getRippleStateIndex (mTxnAccountID, uDstAccountID, uCurrencyID).ToString ();

View File

@@ -27,6 +27,10 @@
#include <atomic> #include <atomic>
#include "../../beast/beast/cxx14/memory.h" #include "../../beast/beast/cxx14/memory.h"
#include "../../beast/beast/utility/Zero.h"
using beast::zero;
using beast::Zero;
#ifndef RIPPLE_TRACK_MUTEXES #ifndef RIPPLE_TRACK_MUTEXES
# define RIPPLE_TRACK_MUTEXES 0 # define RIPPLE_TRACK_MUTEXES 0

View File

@@ -482,7 +482,7 @@ void STAmount::add (Serializer& s) const
} }
else else
{ {
if (isZero ()) if (*this == zero)
s.add64 (cNotNative); s.add64 (cNotNative);
else if (mIsNegative) // 512 = not native else if (mIsNegative) // 512 = not native
s.add64 (mValue | (static_cast<std::uint64_t> (mOffset + 512 + 97) << (64 - 10))); s.add64 (mValue | (static_cast<std::uint64_t> (mOffset + 512 + 97) << (64 - 10)));
@@ -625,7 +625,8 @@ std::string STAmount::getRaw () const
std::string STAmount::getText () const std::string STAmount::getText () const
{ {
// keep full internal accuracy, but make more human friendly if posible // keep full internal accuracy, but make more human friendly if posible
if (isZero ()) return "0"; if (*this == zero)
return "0";
if (mIsNative) if (mIsNative)
{ {
@@ -821,9 +822,10 @@ STAmount operator+ (const STAmount& v1, const STAmount& v2)
{ {
v1.throwComparable (v2); v1.throwComparable (v2);
if (v2.isZero ()) return v1; if (v2 == zero)
return v1;
if (v1.isZero ()) if (v1 == zero)
{ {
// Result must be in terms of v1 currency and issuer. // Result must be in terms of v1 currency and issuer.
return STAmount (v1.getFName (), v1.mCurrency, v1.mIssuer, v2.mValue, v2.mOffset, v2.mIsNegative); return STAmount (v1.getFName (), v1.mCurrency, v1.mIssuer, v2.mValue, v2.mOffset, v2.mIsNegative);
@@ -867,7 +869,8 @@ STAmount operator- (const STAmount& v1, const STAmount& v2)
{ {
v1.throwComparable (v2); v1.throwComparable (v2);
if (v2.isZero ()) return v1; if (v2 == zero)
return v1;
if (v2.mIsNative) if (v2.mIsNative)
{ {
@@ -908,10 +911,10 @@ STAmount operator- (const STAmount& v1, const STAmount& v2)
STAmount STAmount::divide (const STAmount& num, const STAmount& den, const uint160& uCurrencyID, const uint160& uIssuerID) STAmount STAmount::divide (const STAmount& num, const STAmount& den, const uint160& uCurrencyID, const uint160& uIssuerID)
{ {
if (den.isZero ()) if (den == zero)
throw std::runtime_error ("division by zero"); throw std::runtime_error ("division by zero");
if (num.isZero ()) if (num == zero)
return STAmount (uCurrencyID, uIssuerID); return STAmount (uCurrencyID, uIssuerID);
std::uint64_t numVal = num.mValue, denVal = den.mValue; std::uint64_t numVal = num.mValue, denVal = den.mValue;
@@ -951,7 +954,7 @@ STAmount STAmount::divide (const STAmount& num, const STAmount& den, const uint1
STAmount STAmount::multiply (const STAmount& v1, const STAmount& v2, const uint160& uCurrencyID, const uint160& uIssuerID) STAmount STAmount::multiply (const STAmount& v1, const STAmount& v2, const uint160& uCurrencyID, const uint160& uIssuerID)
{ {
if (v1.isZero () || v2.isZero ()) if (v1 == zero || v2 == zero)
return STAmount (uCurrencyID, uIssuerID); return STAmount (uCurrencyID, uIssuerID);
if (v1.mIsNative && v2.mIsNative && uCurrencyID.isZero ()) if (v1.mIsNative && v2.mIsNative && uCurrencyID.isZero ())
@@ -1018,14 +1021,14 @@ STAmount STAmount::multiply (const STAmount& v1, const STAmount& v2, const uint1
// Zero is returned if the offer is worthless. // Zero is returned if the offer is worthless.
std::uint64_t STAmount::getRate (const STAmount& offerOut, const STAmount& offerIn) std::uint64_t STAmount::getRate (const STAmount& offerOut, const STAmount& offerIn)
{ {
if (offerOut.isZero ()) if (offerOut == zero)
return 0; return 0;
try try
{ {
STAmount r = divide (offerIn, offerOut, CURRENCY_ONE, ACCOUNT_ONE); STAmount r = divide (offerIn, offerOut, CURRENCY_ONE, ACCOUNT_ONE);
if (r.isZero ()) // offer is too good if (r == zero) // offer is too good
return 0; return 0;
assert ((r.getExponent () >= -100) && (r.getExponent () <= 155)); assert ((r.getExponent () >= -100) && (r.getExponent () <= 155));
@@ -1055,7 +1058,7 @@ STAmount STAmount::setRate (std::uint64_t rate)
STAmount STAmount::getPay (const STAmount& offerOut, const STAmount& offerIn, const STAmount& needed) STAmount STAmount::getPay (const STAmount& offerOut, const STAmount& offerIn, const STAmount& needed)
{ {
// Someone wants to get (needed) out of the offer, how much should they pay in? // Someone wants to get (needed) out of the offer, how much should they pay in?
if (offerOut.isZero ()) if (offerOut == zero)
return STAmount (offerIn.getCurrency (), offerIn.getIssuer ()); return STAmount (offerIn.getCurrency (), offerIn.getIssuer ());
if (needed >= offerOut) if (needed >= offerOut)
@@ -1217,7 +1220,7 @@ public:
{ {
pass (); pass ();
} }
return true; return true;
} }
@@ -1289,127 +1292,127 @@ public:
{ {
testcase ("native currency"); testcase ("native currency");
STAmount zero, one (1), hundred (100); STAmount zeroSt, one (1), hundred (100);
unexpected (serializeAndDeserialize (zero) != zero, "STAmount fail"); unexpected (serializeAndDeserialize (zeroSt) != zeroSt, "STAmount fail");
unexpected (serializeAndDeserialize (one) != one, "STAmount fail"); unexpected (serializeAndDeserialize (one) != one, "STAmount fail");
unexpected (serializeAndDeserialize (hundred) != hundred, "STAmount fail"); unexpected (serializeAndDeserialize (hundred) != hundred, "STAmount fail");
unexpected (!zero.isNative (), "STAmount fail"); unexpected (!zeroSt.isNative (), "STAmount fail");
unexpected (!hundred.isNative (), "STAmount fail"); unexpected (!hundred.isNative (), "STAmount fail");
unexpected (!zero.isZero (), "STAmount fail"); unexpected (zeroSt != zero, "STAmount fail");
unexpected (one.isZero (), "STAmount fail"); unexpected (one == zero, "STAmount fail");
unexpected (hundred.isZero (), "STAmount fail"); unexpected (hundred == zero, "STAmount fail");
unexpected ((zero < zero), "STAmount fail"); unexpected ((zeroSt < zeroSt), "STAmount fail");
unexpected (! (zero < one), "STAmount fail"); unexpected (! (zeroSt < one), "STAmount fail");
unexpected (! (zero < hundred), "STAmount fail"); unexpected (! (zeroSt < hundred), "STAmount fail");
unexpected ((one < zero), "STAmount fail"); unexpected ((one < zeroSt), "STAmount fail");
unexpected ((one < one), "STAmount fail"); unexpected ((one < one), "STAmount fail");
unexpected (! (one < hundred), "STAmount fail"); unexpected (! (one < hundred), "STAmount fail");
unexpected ((hundred < zero), "STAmount fail"); unexpected ((hundred < zeroSt), "STAmount fail");
unexpected ((hundred < one), "STAmount fail"); unexpected ((hundred < one), "STAmount fail");
unexpected ((hundred < hundred), "STAmount fail"); unexpected ((hundred < hundred), "STAmount fail");
unexpected ((zero > zero), "STAmount fail"); unexpected ((zeroSt > zeroSt), "STAmount fail");
unexpected ((zero > one), "STAmount fail"); unexpected ((zeroSt > one), "STAmount fail");
unexpected ((zero > hundred), "STAmount fail"); unexpected ((zeroSt > hundred), "STAmount fail");
unexpected (! (one > zero), "STAmount fail"); unexpected (! (one > zeroSt), "STAmount fail");
unexpected ((one > one), "STAmount fail"); unexpected ((one > one), "STAmount fail");
unexpected ((one > hundred), "STAmount fail"); unexpected ((one > hundred), "STAmount fail");
unexpected (! (hundred > zero), "STAmount fail"); unexpected (! (hundred > zeroSt), "STAmount fail");
unexpected (! (hundred > one), "STAmount fail"); unexpected (! (hundred > one), "STAmount fail");
unexpected ((hundred > hundred), "STAmount fail"); unexpected ((hundred > hundred), "STAmount fail");
unexpected (! (zero <= zero), "STAmount fail"); unexpected (! (zeroSt <= zeroSt), "STAmount fail");
unexpected (! (zero <= one), "STAmount fail"); unexpected (! (zeroSt <= one), "STAmount fail");
unexpected (! (zero <= hundred), "STAmount fail"); unexpected (! (zeroSt <= hundred), "STAmount fail");
unexpected ((one <= zero), "STAmount fail"); unexpected ((one <= zeroSt), "STAmount fail");
unexpected (! (one <= one), "STAmount fail"); unexpected (! (one <= one), "STAmount fail");
unexpected (! (one <= hundred), "STAmount fail"); unexpected (! (one <= hundred), "STAmount fail");
unexpected ((hundred <= zero), "STAmount fail"); unexpected ((hundred <= zeroSt), "STAmount fail");
unexpected ((hundred <= one), "STAmount fail"); unexpected ((hundred <= one), "STAmount fail");
unexpected (! (hundred <= hundred), "STAmount fail"); unexpected (! (hundred <= hundred), "STAmount fail");
unexpected (! (zero >= zero), "STAmount fail"); unexpected (! (zeroSt >= zeroSt), "STAmount fail");
unexpected ((zero >= one), "STAmount fail"); unexpected ((zeroSt >= one), "STAmount fail");
unexpected ((zero >= hundred), "STAmount fail"); unexpected ((zeroSt >= hundred), "STAmount fail");
unexpected (! (one >= zero), "STAmount fail"); unexpected (! (one >= zeroSt), "STAmount fail");
unexpected (! (one >= one), "STAmount fail"); unexpected (! (one >= one), "STAmount fail");
unexpected ((one >= hundred), "STAmount fail"); unexpected ((one >= hundred), "STAmount fail");
unexpected (! (hundred >= zero), "STAmount fail"); unexpected (! (hundred >= zeroSt), "STAmount fail");
unexpected (! (hundred >= one), "STAmount fail"); unexpected (! (hundred >= one), "STAmount fail");
unexpected (! (hundred >= hundred), "STAmount fail"); unexpected (! (hundred >= hundred), "STAmount fail");
unexpected (! (zero == zero), "STAmount fail"); unexpected (! (zeroSt == zeroSt), "STAmount fail");
unexpected ((zero == one), "STAmount fail"); unexpected ((zeroSt == one), "STAmount fail");
unexpected ((zero == hundred), "STAmount fail"); unexpected ((zeroSt == hundred), "STAmount fail");
unexpected ((one == zero), "STAmount fail"); unexpected ((one == zeroSt), "STAmount fail");
unexpected (! (one == one), "STAmount fail"); unexpected (! (one == one), "STAmount fail");
unexpected ((one == hundred), "STAmount fail"); unexpected ((one == hundred), "STAmount fail");
unexpected ((hundred == zero), "STAmount fail"); unexpected ((hundred == zeroSt), "STAmount fail");
unexpected ((hundred == one), "STAmount fail"); unexpected ((hundred == one), "STAmount fail");
unexpected (! (hundred == hundred), "STAmount fail"); unexpected (! (hundred == hundred), "STAmount fail");
unexpected ((zero != zero), "STAmount fail"); unexpected ((zeroSt != zeroSt), "STAmount fail");
unexpected (! (zero != one), "STAmount fail"); unexpected (! (zeroSt != one), "STAmount fail");
unexpected (! (zero != hundred), "STAmount fail"); unexpected (! (zeroSt != hundred), "STAmount fail");
unexpected (! (one != zero), "STAmount fail"); unexpected (! (one != zeroSt), "STAmount fail");
unexpected ((one != one), "STAmount fail"); unexpected ((one != one), "STAmount fail");
unexpected (! (one != hundred), "STAmount fail"); unexpected (! (one != hundred), "STAmount fail");
unexpected (! (hundred != zero), "STAmount fail"); unexpected (! (hundred != zeroSt), "STAmount fail");
unexpected (! (hundred != one), "STAmount fail"); unexpected (! (hundred != one), "STAmount fail");
@@ -1439,129 +1442,129 @@ public:
{ {
testcase ("custom currency"); testcase ("custom currency");
STAmount zero (CURRENCY_ONE, ACCOUNT_ONE), one (CURRENCY_ONE, ACCOUNT_ONE, 1), hundred (CURRENCY_ONE, ACCOUNT_ONE, 100); STAmount zeroSt (CURRENCY_ONE, ACCOUNT_ONE), one (CURRENCY_ONE, ACCOUNT_ONE, 1), hundred (CURRENCY_ONE, ACCOUNT_ONE, 100);
serializeAndDeserialize (one).getRaw (); serializeAndDeserialize (one).getRaw ();
unexpected (serializeAndDeserialize (zero) != zero, "STAmount fail"); unexpected (serializeAndDeserialize (zeroSt) != zeroSt, "STAmount fail");
unexpected (serializeAndDeserialize (one) != one, "STAmount fail"); unexpected (serializeAndDeserialize (one) != one, "STAmount fail");
unexpected (serializeAndDeserialize (hundred) != hundred, "STAmount fail"); unexpected (serializeAndDeserialize (hundred) != hundred, "STAmount fail");
unexpected (zero.isNative (), "STAmount fail"); unexpected (zeroSt.isNative (), "STAmount fail");
unexpected (hundred.isNative (), "STAmount fail"); unexpected (hundred.isNative (), "STAmount fail");
unexpected (!zero.isZero (), "STAmount fail"); unexpected (zeroSt != zero, "STAmount fail");
unexpected (one.isZero (), "STAmount fail"); unexpected (one == zero, "STAmount fail");
unexpected (hundred.isZero (), "STAmount fail"); unexpected (hundred == zero, "STAmount fail");
unexpected ((zero < zero), "STAmount fail"); unexpected ((zeroSt < zeroSt), "STAmount fail");
unexpected (! (zero < one), "STAmount fail"); unexpected (! (zeroSt < one), "STAmount fail");
unexpected (! (zero < hundred), "STAmount fail"); unexpected (! (zeroSt < hundred), "STAmount fail");
unexpected ((one < zero), "STAmount fail"); unexpected ((one < zeroSt), "STAmount fail");
unexpected ((one < one), "STAmount fail"); unexpected ((one < one), "STAmount fail");
unexpected (! (one < hundred), "STAmount fail"); unexpected (! (one < hundred), "STAmount fail");
unexpected ((hundred < zero), "STAmount fail"); unexpected ((hundred < zeroSt), "STAmount fail");
unexpected ((hundred < one), "STAmount fail"); unexpected ((hundred < one), "STAmount fail");
unexpected ((hundred < hundred), "STAmount fail"); unexpected ((hundred < hundred), "STAmount fail");
unexpected ((zero > zero), "STAmount fail"); unexpected ((zeroSt > zeroSt), "STAmount fail");
unexpected ((zero > one), "STAmount fail"); unexpected ((zeroSt > one), "STAmount fail");
unexpected ((zero > hundred), "STAmount fail"); unexpected ((zeroSt > hundred), "STAmount fail");
unexpected (! (one > zero), "STAmount fail"); unexpected (! (one > zeroSt), "STAmount fail");
unexpected ((one > one), "STAmount fail"); unexpected ((one > one), "STAmount fail");
unexpected ((one > hundred), "STAmount fail"); unexpected ((one > hundred), "STAmount fail");
unexpected (! (hundred > zero), "STAmount fail"); unexpected (! (hundred > zeroSt), "STAmount fail");
unexpected (! (hundred > one), "STAmount fail"); unexpected (! (hundred > one), "STAmount fail");
unexpected ((hundred > hundred), "STAmount fail"); unexpected ((hundred > hundred), "STAmount fail");
unexpected (! (zero <= zero), "STAmount fail"); unexpected (! (zeroSt <= zeroSt), "STAmount fail");
unexpected (! (zero <= one), "STAmount fail"); unexpected (! (zeroSt <= one), "STAmount fail");
unexpected (! (zero <= hundred), "STAmount fail"); unexpected (! (zeroSt <= hundred), "STAmount fail");
unexpected ((one <= zero), "STAmount fail"); unexpected ((one <= zeroSt), "STAmount fail");
unexpected (! (one <= one), "STAmount fail"); unexpected (! (one <= one), "STAmount fail");
unexpected (! (one <= hundred), "STAmount fail"); unexpected (! (one <= hundred), "STAmount fail");
unexpected ((hundred <= zero), "STAmount fail"); unexpected ((hundred <= zeroSt), "STAmount fail");
unexpected ((hundred <= one), "STAmount fail"); unexpected ((hundred <= one), "STAmount fail");
unexpected (! (hundred <= hundred), "STAmount fail"); unexpected (! (hundred <= hundred), "STAmount fail");
unexpected (! (zero >= zero), "STAmount fail"); unexpected (! (zeroSt >= zeroSt), "STAmount fail");
unexpected ((zero >= one), "STAmount fail"); unexpected ((zeroSt >= one), "STAmount fail");
unexpected ((zero >= hundred), "STAmount fail"); unexpected ((zeroSt >= hundred), "STAmount fail");
unexpected (! (one >= zero), "STAmount fail"); unexpected (! (one >= zeroSt), "STAmount fail");
unexpected (! (one >= one), "STAmount fail"); unexpected (! (one >= one), "STAmount fail");
unexpected ((one >= hundred), "STAmount fail"); unexpected ((one >= hundred), "STAmount fail");
unexpected (! (hundred >= zero), "STAmount fail"); unexpected (! (hundred >= zeroSt), "STAmount fail");
unexpected (! (hundred >= one), "STAmount fail"); unexpected (! (hundred >= one), "STAmount fail");
unexpected (! (hundred >= hundred), "STAmount fail"); unexpected (! (hundred >= hundred), "STAmount fail");
unexpected (! (zero == zero), "STAmount fail"); unexpected (! (zeroSt == zeroSt), "STAmount fail");
unexpected ((zero == one), "STAmount fail"); unexpected ((zeroSt == one), "STAmount fail");
unexpected ((zero == hundred), "STAmount fail"); unexpected ((zeroSt == hundred), "STAmount fail");
unexpected ((one == zero), "STAmount fail"); unexpected ((one == zeroSt), "STAmount fail");
unexpected (! (one == one), "STAmount fail"); unexpected (! (one == one), "STAmount fail");
unexpected ((one == hundred), "STAmount fail"); unexpected ((one == hundred), "STAmount fail");
unexpected ((hundred == zero), "STAmount fail"); unexpected ((hundred == zeroSt), "STAmount fail");
unexpected ((hundred == one), "STAmount fail"); unexpected ((hundred == one), "STAmount fail");
unexpected (! (hundred == hundred), "STAmount fail"); unexpected (! (hundred == hundred), "STAmount fail");
unexpected ((zero != zero), "STAmount fail"); unexpected ((zeroSt != zeroSt), "STAmount fail");
unexpected (! (zero != one), "STAmount fail"); unexpected (! (zeroSt != one), "STAmount fail");
unexpected (! (zero != hundred), "STAmount fail"); unexpected (! (zeroSt != hundred), "STAmount fail");
unexpected (! (one != zero), "STAmount fail"); unexpected (! (one != zeroSt), "STAmount fail");
unexpected ((one != one), "STAmount fail"); unexpected ((one != one), "STAmount fail");
unexpected (! (one != hundred), "STAmount fail"); unexpected (! (one != hundred), "STAmount fail");
unexpected (! (hundred != zero), "STAmount fail"); unexpected (! (hundred != zeroSt), "STAmount fail");
unexpected (! (hundred != one), "STAmount fail"); unexpected (! (hundred != one), "STAmount fail");
@@ -1708,27 +1711,27 @@ public:
(STAmount::cMinValue + STAmount::cMaxValue) / 2, STAmount::cMaxOffset - 1); (STAmount::cMinValue + STAmount::cMaxValue) / 2, STAmount::cMaxOffset - 1);
STAmount smallValue (CURRENCY_ONE, ACCOUNT_ONE, STAmount smallValue (CURRENCY_ONE, ACCOUNT_ONE,
(STAmount::cMinValue + STAmount::cMaxValue) / 2, STAmount::cMinOffset + 1); (STAmount::cMinValue + STAmount::cMaxValue) / 2, STAmount::cMinOffset + 1);
STAmount zero (CURRENCY_ONE, ACCOUNT_ONE, 0); STAmount zeroSt (CURRENCY_ONE, ACCOUNT_ONE, 0);
STAmount smallXsmall = STAmount::multiply (smallValue, smallValue, CURRENCY_ONE, ACCOUNT_ONE); STAmount smallXsmall = STAmount::multiply (smallValue, smallValue, CURRENCY_ONE, ACCOUNT_ONE);
expect (smallXsmall.isZero (), "smallXsmall != 0"); expect (smallXsmall == zero, "smallXsmall != 0");
STAmount bigDsmall = STAmount::divide (smallValue, bigValue, CURRENCY_ONE, ACCOUNT_ONE); STAmount bigDsmall = STAmount::divide (smallValue, bigValue, CURRENCY_ONE, ACCOUNT_ONE);
expect (bigDsmall.isZero (), beast::String ("small/big != 0: ") + bigDsmall.getText ()); expect (bigDsmall == zero, beast::String ("small/big != 0: ") + bigDsmall.getText ());
bigDsmall = STAmount::divide (smallValue, bigNative, CURRENCY_ONE, uint160 ()); bigDsmall = STAmount::divide (smallValue, bigNative, CURRENCY_ONE, uint160 ());
expect (bigDsmall.isZero (), beast::String ("small/bigNative != 0: ") + bigDsmall.getText ()); expect (bigDsmall == zero, beast::String ("small/bigNative != 0: ") + bigDsmall.getText ());
bigDsmall = STAmount::divide (smallValue, bigValue, uint160 (), uint160 ()); bigDsmall = STAmount::divide (smallValue, bigValue, uint160 (), uint160 ());
expect (bigDsmall.isZero (), beast::String ("(small/big)->N != 0: ") + bigDsmall.getText ()); expect (bigDsmall == zero, beast::String ("(small/big)->N != 0: ") + bigDsmall.getText ());
bigDsmall = STAmount::divide (smallValue, bigNative, uint160 (), uint160 ()); bigDsmall = STAmount::divide (smallValue, bigNative, uint160 (), uint160 ());
expect (bigDsmall.isZero (), beast::String ("(small/bigNative)->N != 0: ") + bigDsmall.getText ()); expect (bigDsmall == zero, beast::String ("(small/bigNative)->N != 0: ") + bigDsmall.getText ());
// very bad offer // very bad offer
std::uint64_t r = STAmount::getRate (smallValue, bigValue); std::uint64_t r = STAmount::getRate (smallValue, bigValue);

View File

@@ -203,7 +203,7 @@ STAmount STAmount::subRound (const STAmount& v1, const STAmount& v2, bool roundU
STAmount STAmount::mulRound (const STAmount& v1, const STAmount& v2, STAmount STAmount::mulRound (const STAmount& v1, const STAmount& v2,
const uint160& uCurrencyID, const uint160& uIssuerID, bool roundUp) const uint160& uCurrencyID, const uint160& uIssuerID, bool roundUp)
{ {
if (v1.isZero () || v2.isZero ()) if (v1 == zero || v2 == zero)
return STAmount (uCurrencyID, uIssuerID); return STAmount (uCurrencyID, uIssuerID);
if (v1.mIsNative && v2.mIsNative && uCurrencyID.isZero ()) if (v1.mIsNative && v2.mIsNative && uCurrencyID.isZero ())
@@ -267,10 +267,10 @@ STAmount STAmount::mulRound (const STAmount& v1, const STAmount& v2,
STAmount STAmount::divRound (const STAmount& num, const STAmount& den, STAmount STAmount::divRound (const STAmount& num, const STAmount& den,
const uint160& uCurrencyID, const uint160& uIssuerID, bool roundUp) const uint160& uCurrencyID, const uint160& uIssuerID, bool roundUp)
{ {
if (den.isZero ()) if (den == zero)
throw std::runtime_error ("division by zero"); throw std::runtime_error ("division by zero");
if (num.isZero ()) if (num == zero)
return STAmount (uCurrencyID, uIssuerID); return STAmount (uCurrencyID, uIssuerID);
std::uint64_t numVal = num.mValue, denVal = den.mValue; std::uint64_t numVal = num.mValue, denVal = den.mValue;

View File

@@ -70,13 +70,13 @@ static inline const uint160& get_u160_one ()
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
/** A type which can be exported to a well known binary format. /** A type which can be exported to a well known binary format.
A SerializedType: A SerializedType:
- Always a field - Always a field
- Can always go inside an eligible enclosing SerializedType - Can always go inside an eligible enclosing SerializedType
(such as STArray) (such as STArray)
- Has a field name - Has a field name
Like JSON, a SerializedObject is a basket which has rules Like JSON, a SerializedObject is a basket which has rules
on what it can hold. on what it can hold.
@@ -574,6 +574,11 @@ public:
return mValue; return mValue;
} }
int signum () const
{
return mValue ? (mIsNegative ? -1 : 1) : 0;
}
// When the currency is XRP, the value in raw units. S=signed // When the currency is XRP, the value in raw units. S=signed
std::uint64_t getNValue () const std::uint64_t getNValue () const
{ {
@@ -596,47 +601,24 @@ public:
{ {
return mIsNative; return mIsNative;
} }
bool isZero () const
{
return mValue == 0;
}
bool isNonZero () const
{
return mValue != 0;
}
bool isNegative () const
{
return mIsNegative && !isZero ();
}
bool isPositive () const
{
return !mIsNegative && !isZero ();
}
bool isLEZero () const
{
return mIsNegative || isZero ();
}
bool isGEZero () const
{
return !mIsNegative;
}
bool isLegalNet () const bool isLegalNet () const
{ {
return !mIsNative || (mValue <= cMaxNativeN); return !mIsNative || (mValue <= cMaxNativeN);
} }
explicit explicit
operator bool () const noexcept operator bool () const noexcept
{ {
return !isZero (); return *this != zero;
} }
void negate () void negate ()
{ {
if (!isZero ()) mIsNegative = !mIsNegative; if (*this != zero)
mIsNegative = !mIsNegative;
} }
void zero () void clear ()
{ {
// VFALCO: Why -100? // VFALCO: Why -100?
mOffset = mIsNative ? 0 : -100; mOffset = mIsNative ? 0 : -100;
@@ -645,19 +627,25 @@ public:
} }
// Zero while copying currency and issuer. // Zero while copying currency and issuer.
void zero (const STAmount& saTmpl) void clear (const STAmount& saTmpl)
{ {
mCurrency = saTmpl.mCurrency; mCurrency = saTmpl.mCurrency;
mIssuer = saTmpl.mIssuer; mIssuer = saTmpl.mIssuer;
mIsNative = saTmpl.mIsNative; mIsNative = saTmpl.mIsNative;
zero (); clear ();
} }
void zero (const uint160& uCurrencyID, const uint160& uIssuerID) void clear (const uint160& uCurrencyID, const uint160& uIssuerID)
{ {
mCurrency = uCurrencyID; mCurrency = uCurrencyID;
mIssuer = uIssuerID; mIssuer = uIssuerID;
mIsNative = !uCurrencyID; mIsNative = !uCurrencyID;
zero (); clear ();
}
STAmount& operator=(beast::Zero)
{
clear ();
return *this;
} }
int compare (const STAmount&) const; int compare (const STAmount&) const;
@@ -789,7 +777,7 @@ public:
STAmount getRound () const; STAmount getRound () const;
void roundSelf (); void roundSelf ();
static void canonicalizeRound (bool isNative, std::uint64_t& value, int& offset, bool roundUp); static void canonicalizeRound (bool isNative, std::uint64_t& value, int& offset, bool roundUp);
private: private:
@@ -1278,7 +1266,7 @@ public:
bool operator== (const STPathElement& t) const bool operator== (const STPathElement& t) const
{ {
return ((mType & typeAccount) == (t.mType & typeAccount)) && return ((mType & typeAccount) == (t.mType & typeAccount)) &&
(mAccountID == t.mAccountID) && (mCurrencyID == t.mCurrencyID) && (mIssuerID == t.mIssuerID); (mAccountID == t.mAccountID) && (mCurrencyID == t.mCurrencyID) && (mIssuerID == t.mIssuerID);
} }
@@ -1655,4 +1643,4 @@ private:
} // ripple } // ripple
#endif #endif