mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-06 17:27:55 +00:00
New classes and types for handling asset amounts:
* Quality opaque type for order book quality * Amount replacement for STAmount * Amounts, in/out amount pair for offers * 'core' namespace with type aliases for Ripple primitives.
This commit is contained in:
@@ -820,6 +820,10 @@
|
|||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\src\ripple\validators\ripple_validators.cpp" />
|
<ClCompile Include="..\..\src\ripple\validators\ripple_validators.cpp" />
|
||||||
|
<ClCompile Include="..\..\src\ripple_app\book\tests\Quality.test.cpp">
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||||
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\src\ripple_app\consensus\DisputedTx.cpp">
|
<ClCompile Include="..\..\src\ripple_app\consensus\DisputedTx.cpp">
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||||
@@ -2479,6 +2483,10 @@
|
|||||||
<ClInclude Include="..\..\src\ripple\validators\impl\Validation.h" />
|
<ClInclude Include="..\..\src\ripple\validators\impl\Validation.h" />
|
||||||
<ClInclude Include="..\..\src\ripple\validators\impl\Validator.h" />
|
<ClInclude Include="..\..\src\ripple\validators\impl\Validator.h" />
|
||||||
<ClInclude Include="..\..\src\ripple\validators\ripple_validators.h" />
|
<ClInclude Include="..\..\src\ripple\validators\ripple_validators.h" />
|
||||||
|
<ClInclude Include="..\..\src\ripple_app\book\Amount.h" />
|
||||||
|
<ClInclude Include="..\..\src\ripple_app\book\Amounts.h" />
|
||||||
|
<ClInclude Include="..\..\src\ripple_app\book\Quality.h" />
|
||||||
|
<ClInclude Include="..\..\src\ripple_app\book\Types.h" />
|
||||||
<ClInclude Include="..\..\src\ripple_app\consensus\DisputedTx.h" />
|
<ClInclude Include="..\..\src\ripple_app\consensus\DisputedTx.h" />
|
||||||
<ClInclude Include="..\..\src\ripple_app\consensus\LedgerConsensus.h" />
|
<ClInclude Include="..\..\src\ripple_app\consensus\LedgerConsensus.h" />
|
||||||
<ClInclude Include="..\..\src\ripple_app\contracts\Contract.h" />
|
<ClInclude Include="..\..\src\ripple_app\contracts\Contract.h" />
|
||||||
|
|||||||
@@ -319,6 +319,15 @@
|
|||||||
<Filter Include="[2] Old Ripple\ripple_app\transactors">
|
<Filter Include="[2] Old Ripple\ripple_app\transactors">
|
||||||
<UniqueIdentifier>{dcb7c75c-4f1d-486c-8079-52dc43644ae6}</UniqueIdentifier>
|
<UniqueIdentifier>{dcb7c75c-4f1d-486c-8079-52dc43644ae6}</UniqueIdentifier>
|
||||||
</Filter>
|
</Filter>
|
||||||
|
<Filter Include="[1] Ripple\common\tests">
|
||||||
|
<UniqueIdentifier>{1aa56407-a927-42be-862b-cd5324b4d63b}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="[2] Old Ripple\ripple_app\book">
|
||||||
|
<UniqueIdentifier>{56248509-436d-4034-ab4e-64afbb532418}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="[2] Old Ripple\ripple_app\book\tests">
|
||||||
|
<UniqueIdentifier>{28b72c9f-02e3-4b57-9386-957478e1f0b7}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="..\..\src\ripple_basics\containers\RangeSet.cpp">
|
<ClCompile Include="..\..\src\ripple_basics\containers\RangeSet.cpp">
|
||||||
@@ -1500,6 +1509,12 @@
|
|||||||
<ClCompile Include="..\..\src\ripple_app\tx\LocalTxs.cpp">
|
<ClCompile Include="..\..\src\ripple_app\tx\LocalTxs.cpp">
|
||||||
<Filter>[2] Old Ripple\ripple_app\tx</Filter>
|
<Filter>[2] Old Ripple\ripple_app\tx</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\src\ripple\common\tests\cross_offer.test.cpp">
|
||||||
|
<Filter>[1] Ripple\common\tests</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\src\ripple_app\book\tests\Quality.test.cpp">
|
||||||
|
<Filter>[2] Old Ripple\ripple_app\book\tests</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="..\..\src\ripple_basics\containers\RangeSet.h">
|
<ClInclude Include="..\..\src\ripple_basics\containers\RangeSet.h">
|
||||||
@@ -3063,6 +3078,18 @@
|
|||||||
<ClInclude Include="..\..\src\ripple_app\tx\LocalTxs.h">
|
<ClInclude Include="..\..\src\ripple_app\tx\LocalTxs.h">
|
||||||
<Filter>[2] Old Ripple\ripple_app\tx</Filter>
|
<Filter>[2] Old Ripple\ripple_app\tx</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\src\ripple_app\book\Amount.h">
|
||||||
|
<Filter>[2] Old Ripple\ripple_app\book</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\src\ripple_app\book\Amounts.h">
|
||||||
|
<Filter>[2] Old Ripple\ripple_app\book</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\src\ripple_app\book\Quality.h">
|
||||||
|
<Filter>[2] Old Ripple\ripple_app\book</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\src\ripple_app\book\Types.h">
|
||||||
|
<Filter>[2] Old Ripple\ripple_app\book</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<CustomBuild Include="..\..\src\ripple_data\protocol\ripple.proto">
|
<CustomBuild Include="..\..\src\ripple_data\protocol\ripple.proto">
|
||||||
|
|||||||
330
src/ripple_app/book/Amount.h
Normal file
330
src/ripple_app/book/Amount.h
Normal file
@@ -0,0 +1,330 @@
|
|||||||
|
//------------------------------------------------------------------------------
|
||||||
|
/*
|
||||||
|
This file is part of rippled: https://github.com/ripple/rippled
|
||||||
|
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
purpose with or without fee is hereby granted, provided that the above
|
||||||
|
copyright notice and this permission notice appear in all copies.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
#ifndef RIPPLE_CORE_AMOUNT_H_INCLUDED
|
||||||
|
#define RIPPLE_CORE_AMOUNT_H_INCLUDED
|
||||||
|
|
||||||
|
#include "../../ripple_data/protocol/SerializedObject.h"
|
||||||
|
|
||||||
|
#include "../../beast/beast/utility/noexcept.h"
|
||||||
|
#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 core {
|
||||||
|
|
||||||
|
/** Custom floating point asset amount.
|
||||||
|
The "representation" may be integral or non-integral. For integral
|
||||||
|
representations, the exponent is always zero and the value held in the
|
||||||
|
mantissa is an exact quantity.
|
||||||
|
*/
|
||||||
|
class AmountType
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
std::uint64_t m_mantissa;
|
||||||
|
int m_exponent;
|
||||||
|
bool m_negative;
|
||||||
|
bool m_integral;
|
||||||
|
|
||||||
|
AmountType (std::uint64_t mantissa,
|
||||||
|
int exponent, bool negative, bool integral)
|
||||||
|
: m_mantissa (mantissa)
|
||||||
|
, m_exponent (exponent)
|
||||||
|
, m_negative (negative)
|
||||||
|
, m_integral (integral)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
/** Default construction.
|
||||||
|
The value is uninitialized.
|
||||||
|
*/
|
||||||
|
AmountType() noexcept
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Construct from an integer.
|
||||||
|
The representation is set to integral.
|
||||||
|
*/
|
||||||
|
/** @{ */
|
||||||
|
template <class Integer>
|
||||||
|
AmountType (Integer value,
|
||||||
|
std::enable_if_t <std::is_signed <Integer>::value>* = 0) noexcept
|
||||||
|
: m_mantissa (value)
|
||||||
|
, m_exponent (0)
|
||||||
|
, m_negative (value < 0)
|
||||||
|
, m_integral (true)
|
||||||
|
{
|
||||||
|
static_assert (std::is_integral<Integer>::value,
|
||||||
|
"Cannot construct from non-integral type.");
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Integer>
|
||||||
|
AmountType (Integer value,
|
||||||
|
std::enable_if_t <! std::is_signed <Integer>::value>* = 0) noexcept
|
||||||
|
: m_mantissa (value)
|
||||||
|
, m_exponent (0)
|
||||||
|
, m_negative (false)
|
||||||
|
{
|
||||||
|
static_assert (std::is_integral<Integer>::value,
|
||||||
|
"Cannot construct from non-integral type.");
|
||||||
|
}
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
/** Assign the value zero.
|
||||||
|
The representation is preserved.
|
||||||
|
*/
|
||||||
|
AmountType&
|
||||||
|
operator= (Zero) noexcept
|
||||||
|
{
|
||||||
|
m_mantissa = 0;
|
||||||
|
// VFALCO Why -100?
|
||||||
|
// "We have to use something in range."
|
||||||
|
// "This makes zero the smallest value."
|
||||||
|
m_exponent = m_integral ? 0 : -100;
|
||||||
|
m_exponent = 0;
|
||||||
|
m_negative = false;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns the value in canonical format. */
|
||||||
|
AmountType
|
||||||
|
normal() const noexcept
|
||||||
|
{
|
||||||
|
if (m_integral)
|
||||||
|
{
|
||||||
|
AmountType result;
|
||||||
|
if (m_mantissa == 0)
|
||||||
|
{
|
||||||
|
result.m_exponent = 0;
|
||||||
|
result.m_negative = false;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
return AmountType();
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Comparison
|
||||||
|
//
|
||||||
|
|
||||||
|
int
|
||||||
|
signum() const noexcept
|
||||||
|
{
|
||||||
|
if (m_mantissa == 0)
|
||||||
|
return 0;
|
||||||
|
return m_negative ? -1 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
operator== (AmountType const& other) const noexcept
|
||||||
|
{
|
||||||
|
return
|
||||||
|
m_negative == other.m_negative &&
|
||||||
|
m_mantissa == other.m_mantissa &&
|
||||||
|
m_exponent == other.m_exponent;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
operator!= (AmountType const& other) const noexcept
|
||||||
|
{
|
||||||
|
return ! (*this == other);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
operator< (AmountType const& other) const noexcept
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
operator>= (AmountType const& other) const noexcept
|
||||||
|
{
|
||||||
|
return ! (*this < other);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
operator> (AmountType const& other) const noexcept
|
||||||
|
{
|
||||||
|
return other < *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
operator<= (AmountType const& other) const noexcept
|
||||||
|
{
|
||||||
|
return ! (other < *this);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Arithmetic
|
||||||
|
//
|
||||||
|
|
||||||
|
AmountType
|
||||||
|
operator-() const noexcept
|
||||||
|
{
|
||||||
|
return AmountType (m_mantissa, m_exponent, ! m_negative, m_integral);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Output
|
||||||
|
//
|
||||||
|
|
||||||
|
std::ostream&
|
||||||
|
operator<< (std::ostream& os)
|
||||||
|
{
|
||||||
|
int const sig (signum());
|
||||||
|
|
||||||
|
if (sig == 0)
|
||||||
|
return os << "0";
|
||||||
|
else if (sig < 0)
|
||||||
|
os << "-";
|
||||||
|
|
||||||
|
if (m_integral)
|
||||||
|
return os << m_mantissa;
|
||||||
|
|
||||||
|
if (m_exponent != 0 && (m_exponent < -25 || m_exponent > -5))
|
||||||
|
return os << m_mantissa << "e" << m_exponent;
|
||||||
|
|
||||||
|
//if (m_exponent > 0)
|
||||||
|
// return os <<
|
||||||
|
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
typedef STAmount Amount;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
66
src/ripple_app/book/Amounts.h
Normal file
66
src/ripple_app/book/Amounts.h
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
//------------------------------------------------------------------------------
|
||||||
|
/*
|
||||||
|
This file is part of rippled: https://github.com/ripple/rippled
|
||||||
|
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
purpose with or without fee is hereby granted, provided that the above
|
||||||
|
copyright notice and this permission notice appear in all copies.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
#ifndef RIPPLE_CORE_AMOUNTS_H_INCLUDED
|
||||||
|
#define RIPPLE_CORE_AMOUNTS_H_INCLUDED
|
||||||
|
|
||||||
|
#include "Amount.h"
|
||||||
|
|
||||||
|
namespace ripple {
|
||||||
|
namespace core {
|
||||||
|
|
||||||
|
struct Amounts
|
||||||
|
{
|
||||||
|
Amounts() = default;
|
||||||
|
|
||||||
|
Amounts (Amount const& in_, Amount const& out_)
|
||||||
|
: in (in_)
|
||||||
|
, out (out_)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns `true` if either quantity is not positive. */
|
||||||
|
bool
|
||||||
|
empty() const noexcept
|
||||||
|
{
|
||||||
|
return ! in.isPositive() || ! out.isPositive();
|
||||||
|
}
|
||||||
|
|
||||||
|
Amount in;
|
||||||
|
Amount out;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline
|
||||||
|
bool
|
||||||
|
operator== (Amounts const& lhs, Amounts const& rhs) noexcept
|
||||||
|
{
|
||||||
|
return lhs.in == rhs.in && lhs.out == rhs.out;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline
|
||||||
|
bool
|
||||||
|
operator!= (Amounts const& lhs, Amounts const& rhs) noexcept
|
||||||
|
{
|
||||||
|
return ! (lhs == rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
198
src/ripple_app/book/Quality.h
Normal file
198
src/ripple_app/book/Quality.h
Normal file
@@ -0,0 +1,198 @@
|
|||||||
|
//------------------------------------------------------------------------------
|
||||||
|
/*
|
||||||
|
This file is part of rippled: https://github.com/ripple/rippled
|
||||||
|
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
purpose with or without fee is hereby granted, provided that the above
|
||||||
|
copyright notice and this permission notice appear in all copies.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
#ifndef RIPPLE_CORE_QUALITY_H_INCLUDED
|
||||||
|
#define RIPPLE_CORE_QUALITY_H_INCLUDED
|
||||||
|
|
||||||
|
#include "Amount.h"
|
||||||
|
#include "Amounts.h"
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <limits>
|
||||||
|
#include <ostream>
|
||||||
|
|
||||||
|
namespace ripple {
|
||||||
|
namespace core {
|
||||||
|
|
||||||
|
/** Represents the logical ratio of output currency to input currency.
|
||||||
|
Internally this is stored using a custom floating point representation,
|
||||||
|
as the inverse of the ratio, so that quality will be descending in
|
||||||
|
a sequence of actual values that represent qualities.
|
||||||
|
*/
|
||||||
|
class Quality
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// Type of the internal representation. Higher qualities
|
||||||
|
// have lower unsigned integer representations.
|
||||||
|
typedef std::uint64_t value_type;
|
||||||
|
|
||||||
|
private:
|
||||||
|
value_type m_value;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Quality() = default;
|
||||||
|
|
||||||
|
explicit
|
||||||
|
Quality (std::uint64_t value)
|
||||||
|
: m_value (value)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Create a quality from the ratio of two amounts. */
|
||||||
|
explicit
|
||||||
|
Quality (Amounts const& amount)
|
||||||
|
: m_value (Amount::getRate (amount.out, amount.in))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Advances to the next higher quality level. */
|
||||||
|
/** @{ */
|
||||||
|
Quality&
|
||||||
|
operator++()
|
||||||
|
{
|
||||||
|
assert (m_value > 0);
|
||||||
|
--m_value;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Quality
|
||||||
|
operator++ (int)
|
||||||
|
{
|
||||||
|
Quality prev (*this);
|
||||||
|
--*this;
|
||||||
|
return prev;
|
||||||
|
}
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
/** Advances to the next lower quality level. */
|
||||||
|
/** @{ */
|
||||||
|
Quality&
|
||||||
|
operator--()
|
||||||
|
{
|
||||||
|
assert (m_value < std::numeric_limits<value_type>::max());
|
||||||
|
++m_value;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Quality
|
||||||
|
operator-- (int)
|
||||||
|
{
|
||||||
|
Quality prev (*this);
|
||||||
|
++*this;
|
||||||
|
return prev;
|
||||||
|
}
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
/** Returns `true` if lhs is lower quality than `rhs`.
|
||||||
|
Lower quality means the taker receives a worse deal.
|
||||||
|
Higher quality is better for the taker.
|
||||||
|
*/
|
||||||
|
friend
|
||||||
|
bool
|
||||||
|
operator< (Quality const& lhs, Quality const& rhs) noexcept
|
||||||
|
{
|
||||||
|
return lhs.m_value > rhs.m_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend
|
||||||
|
bool
|
||||||
|
operator== (Quality const& lhs, Quality const& rhs) noexcept
|
||||||
|
{
|
||||||
|
return lhs.m_value == rhs.m_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend
|
||||||
|
std::ostream&
|
||||||
|
operator<< (std::ostream& os, Quality const& quality)
|
||||||
|
{
|
||||||
|
os << quality.m_value;
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns the quality as Amount. */
|
||||||
|
Amount
|
||||||
|
rate() const
|
||||||
|
{
|
||||||
|
return Amount::setRate (m_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns the scaled amount with in capped.
|
||||||
|
Math is avoided if the result is exact. The output is clamped
|
||||||
|
to prevent money creation.
|
||||||
|
*/
|
||||||
|
Amounts
|
||||||
|
ceil_in (Amounts const& amount, Amount const& limit) const
|
||||||
|
{
|
||||||
|
if (amount.in > limit)
|
||||||
|
{
|
||||||
|
// VFALCO TODO make mulRound avoid math when v2==one
|
||||||
|
#if 0
|
||||||
|
Amounts result (limit, Amount::mulRound (
|
||||||
|
limit, rate(), amount.out, true));
|
||||||
|
#else
|
||||||
|
Amounts result (limit, Amount::divRound (
|
||||||
|
limit, rate(), amount.out, true));
|
||||||
|
#endif
|
||||||
|
// Clamp out
|
||||||
|
if (result.out > amount.out)
|
||||||
|
result.out = amount.out;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns the scaled amount with out capped.
|
||||||
|
Math is avoided if the result is exact. The input is clamped
|
||||||
|
to prevent money creation.
|
||||||
|
*/
|
||||||
|
Amounts
|
||||||
|
ceil_out (Amounts const& amount, Amount const& limit) const
|
||||||
|
{
|
||||||
|
if (amount.out > limit)
|
||||||
|
{
|
||||||
|
// VFALCO TODO make divRound avoid math when v2==one
|
||||||
|
#if 0
|
||||||
|
Amounts result (Amount::divRound (
|
||||||
|
limit, rate(), amount.in, true), limit);
|
||||||
|
#else
|
||||||
|
Amounts result (Amount::mulRound (
|
||||||
|
limit, rate(), amount.in, true), limit);
|
||||||
|
#endif
|
||||||
|
// Clamp in
|
||||||
|
if (result.in > amount.in)
|
||||||
|
result.in = amount.in;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
return amount;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
inline
|
||||||
|
bool
|
||||||
|
operator!= (Quality const& lhs, Quality const& rhs) noexcept
|
||||||
|
{
|
||||||
|
return ! (lhs == rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
63
src/ripple_app/book/Types.h
Normal file
63
src/ripple_app/book/Types.h
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
//------------------------------------------------------------------------------
|
||||||
|
/*
|
||||||
|
This file is part of rippled: https://github.com/ripple/rippled
|
||||||
|
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
purpose with or without fee is hereby granted, provided that the above
|
||||||
|
copyright notice and this permission notice appear in all copies.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
#ifndef RIPPLE_CORE_TYPES_H_INCLUDED
|
||||||
|
#define RIPPLE_CORE_TYPES_H_INCLUDED
|
||||||
|
|
||||||
|
#include "../ledger/LedgerEntrySet.h"
|
||||||
|
#include "../../ripple/types/api/RippleAssets.h"
|
||||||
|
#include "../../ripple/types/api/UInt160.h"
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
namespace ripple {
|
||||||
|
namespace core {
|
||||||
|
|
||||||
|
/** A mutable view that overlays an immutable ledger to track changes. */
|
||||||
|
typedef LedgerEntrySet LedgerView;
|
||||||
|
|
||||||
|
/** Identifies an account. */
|
||||||
|
typedef uint160 Account;
|
||||||
|
|
||||||
|
/** Asset identifiers. */
|
||||||
|
typedef RippleCurrency Currency;
|
||||||
|
typedef RippleIssuer Issuer;
|
||||||
|
typedef RippleAsset Asset;
|
||||||
|
typedef RippleAssetRef AssetRef;
|
||||||
|
|
||||||
|
/** Uniquely identifies an order book. */
|
||||||
|
typedef RippleBook Book;
|
||||||
|
typedef RippleBookRef BookRef;
|
||||||
|
|
||||||
|
/** A clock representing network time.
|
||||||
|
This measures seconds since the Ripple epoch as seen
|
||||||
|
by the ledger close clock.
|
||||||
|
*/
|
||||||
|
class Clock // : public abstract_clock <std::chrono::seconds>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef std::uint32_t time_point;
|
||||||
|
typedef std::chrono::seconds duration;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
249
src/ripple_app/book/tests/Quality.test.cpp
Normal file
249
src/ripple_app/book/tests/Quality.test.cpp
Normal file
@@ -0,0 +1,249 @@
|
|||||||
|
//------------------------------------------------------------------------------
|
||||||
|
/*
|
||||||
|
This file is part of rippled: https://github.com/ripple/rippled
|
||||||
|
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
purpose with or without fee is hereby granted, provided that the above
|
||||||
|
copyright notice and this permission notice appear in all copies.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
#include "../Quality.h"
|
||||||
|
|
||||||
|
#include "../../../beast/beast/unit_test/suite.h"
|
||||||
|
#include "../../../beast/beast/cxx14/type_traits.h"
|
||||||
|
|
||||||
|
namespace ripple {
|
||||||
|
namespace core {
|
||||||
|
|
||||||
|
class Quality_test : public beast::unit_test::suite
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// Create a raw, non-integral amount from mantissa and exponent
|
||||||
|
Amount
|
||||||
|
static raw (std::uint64_t mantissa, int exponent)
|
||||||
|
{
|
||||||
|
return Amount (uint160(3), uint160(3), mantissa, exponent);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Integer>
|
||||||
|
static
|
||||||
|
Amount
|
||||||
|
amount (Integer integer,
|
||||||
|
std::enable_if_t <std::is_signed <Integer>::value>* = 0)
|
||||||
|
{
|
||||||
|
static_assert (std::is_integral <Integer>::value, "");
|
||||||
|
return Amount (integer, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Integer>
|
||||||
|
static
|
||||||
|
Amount
|
||||||
|
amount (Integer integer,
|
||||||
|
std::enable_if_t <! std::is_signed <Integer>::value>* = 0)
|
||||||
|
{
|
||||||
|
static_assert (std::is_integral <Integer>::value, "");
|
||||||
|
if (integer < 0)
|
||||||
|
return Amount (-integer, true);
|
||||||
|
return Amount (integer, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class In, class Out>
|
||||||
|
static
|
||||||
|
Amounts
|
||||||
|
amounts (In in, Out out)
|
||||||
|
{
|
||||||
|
return Amounts (amount(in), amount(out));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class In1, class Out1, class Int, class In2, class Out2>
|
||||||
|
void
|
||||||
|
ceil_in (Quality const& q,
|
||||||
|
In1 in, Out1 out, Int limit, In2 in_expected, Out2 out_expected)
|
||||||
|
{
|
||||||
|
auto expect_result (amounts (in_expected, out_expected));
|
||||||
|
auto actual_result (q.ceil_in (amounts(in, out), amount(limit)));
|
||||||
|
|
||||||
|
expect (actual_result == expect_result);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class In1, class Out1, class Int, class In2, class Out2>
|
||||||
|
void
|
||||||
|
ceil_out (Quality const& q,
|
||||||
|
In1 in, Out1 out, Int limit, In2 in_expected, Out2 out_expected)
|
||||||
|
{
|
||||||
|
auto const expect_result (amounts (in_expected, out_expected));
|
||||||
|
auto const actual_result (q.ceil_out (amounts(in, out), amount(limit)));
|
||||||
|
|
||||||
|
expect (actual_result == expect_result);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
test_ceil_in ()
|
||||||
|
{
|
||||||
|
testcase ("ceil_in");
|
||||||
|
|
||||||
|
{
|
||||||
|
// 1 in, 1 out:
|
||||||
|
Quality q (Amounts (amount(1), amount(1)));
|
||||||
|
|
||||||
|
ceil_in (q,
|
||||||
|
1, 1, // 1 in, 1 out
|
||||||
|
1, // limit: 1
|
||||||
|
1, 1); // 1 in, 1 out
|
||||||
|
|
||||||
|
ceil_in (q,
|
||||||
|
10, 10, // 10 in, 10 out
|
||||||
|
5, // limit: 5
|
||||||
|
5, 5); // 5 in, 5 out
|
||||||
|
|
||||||
|
ceil_in (q,
|
||||||
|
5, 5, // 5 in, 5 out
|
||||||
|
10, // limit: 10
|
||||||
|
5, 5); // 5 in, 5 out
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// 1 in, 2 out:
|
||||||
|
Quality q (Amounts (amount(1), amount(2)));
|
||||||
|
|
||||||
|
ceil_in (q,
|
||||||
|
40, 80, // 40 in, 80 out
|
||||||
|
40, // limit: 40
|
||||||
|
40, 80); // 40 in, 20 out
|
||||||
|
|
||||||
|
ceil_in (q,
|
||||||
|
40, 80, // 40 in, 80 out
|
||||||
|
20, // limit: 20
|
||||||
|
20, 40); // 20 in, 40 out
|
||||||
|
|
||||||
|
ceil_in (q,
|
||||||
|
40, 80, // 40 in, 80 out
|
||||||
|
60, // limit: 60
|
||||||
|
40, 80); // 40 in, 80 out
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// 2 in, 1 out:
|
||||||
|
Quality q (Amounts (amount(2), amount(1)));
|
||||||
|
|
||||||
|
ceil_in (q,
|
||||||
|
40, 20, // 40 in, 20 out
|
||||||
|
20, // limit: 20
|
||||||
|
20, 10); // 20 in, 10 out
|
||||||
|
|
||||||
|
ceil_in (q,
|
||||||
|
40, 20, // 40 in, 20 out
|
||||||
|
40, // limit: 40
|
||||||
|
40, 20); // 40 in, 20 out
|
||||||
|
|
||||||
|
ceil_in (q,
|
||||||
|
40, 20, // 40 in, 20 out
|
||||||
|
50, // limit: 40
|
||||||
|
40, 20); // 40 in, 20 out
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
test_ceil_out ()
|
||||||
|
{
|
||||||
|
testcase ("ceil_out");
|
||||||
|
|
||||||
|
{
|
||||||
|
// 1 in, 1 out:
|
||||||
|
Quality q (Amounts (amount(1),amount(1)));
|
||||||
|
|
||||||
|
ceil_out (q,
|
||||||
|
1, 1, // 1 in, 1 out
|
||||||
|
1, // limit 1
|
||||||
|
1, 1); // 1 in, 1 out
|
||||||
|
|
||||||
|
ceil_out (q,
|
||||||
|
10, 10, // 10 in, 10 out
|
||||||
|
5, // limit 5
|
||||||
|
5, 5); // 5 in, 5 out
|
||||||
|
|
||||||
|
ceil_out (q,
|
||||||
|
10, 10, // 10 in, 10 out
|
||||||
|
20, // limit 20
|
||||||
|
10, 10); // 10 in, 10 out
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// 1 in, 2 out:
|
||||||
|
Quality q (Amounts (amount(1),amount(2)));
|
||||||
|
|
||||||
|
ceil_out (q,
|
||||||
|
40, 80, // 40 in, 80 out
|
||||||
|
40, // limit 40
|
||||||
|
20, 40); // 20 in, 40 out
|
||||||
|
|
||||||
|
ceil_out (q,
|
||||||
|
40, 80, // 40 in, 80 out
|
||||||
|
80, // limit 80
|
||||||
|
40, 80); // 40 in, 80 out
|
||||||
|
|
||||||
|
ceil_out (q,
|
||||||
|
40, 80, // 40 in, 80 out
|
||||||
|
100, // limit 100
|
||||||
|
40, 80); // 40 in, 80 out
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// 2 in, 1 out:
|
||||||
|
Quality q (Amounts (amount(2),amount(1)));
|
||||||
|
|
||||||
|
ceil_out (q,
|
||||||
|
40, 20, // 40 in, 20 out
|
||||||
|
20, // limit 20
|
||||||
|
40, 20); // 40 in, 20 out
|
||||||
|
|
||||||
|
ceil_out (q,
|
||||||
|
40, 20, // 40 in, 20 out
|
||||||
|
40, // limit 40
|
||||||
|
40, 20); // 40 in, 20 out
|
||||||
|
|
||||||
|
ceil_out (q,
|
||||||
|
40, 20, // 40 in, 20 out
|
||||||
|
10, // limit 10
|
||||||
|
20, 10); // 20 in, 10 out
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
test_raw()
|
||||||
|
{
|
||||||
|
{
|
||||||
|
Quality q (0x5d048191fb9130daull); // 126836389.7680090
|
||||||
|
Amounts const value (
|
||||||
|
amount(349469768), // 349.469768 XRP
|
||||||
|
raw (2755280000000000ull, -15)); // 2.75528
|
||||||
|
Amount const limit (
|
||||||
|
raw (4131113916555555, -16)); // .4131113916555555
|
||||||
|
Amounts const result (q.ceil_out (value, limit));
|
||||||
|
expect (! result.in.isZero());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
run()
|
||||||
|
{
|
||||||
|
test_ceil_in ();
|
||||||
|
test_ceil_out ();
|
||||||
|
test_raw();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
BEAST_DEFINE_TESTSUITE_MANUAL(Quality,core,ripple);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -37,3 +37,5 @@
|
|||||||
#include "tx/Transaction.cpp"
|
#include "tx/Transaction.cpp"
|
||||||
#include "tx/TransactionEngine.cpp"
|
#include "tx/TransactionEngine.cpp"
|
||||||
#include "tx/TransactionMeta.cpp"
|
#include "tx/TransactionMeta.cpp"
|
||||||
|
|
||||||
|
#include "book/tests/Quality.test.cpp"
|
||||||
|
|||||||
Reference in New Issue
Block a user