Skip to content

Commit

Permalink
Use STEitherAmount as a variant of STAmount and STMPTAmount (#30)
Browse files Browse the repository at this point in the history
* Use STEitherAmount as a variant of STAmount and MPTAmount

* Split AMOUNT fields into two types SF_AMOUNT (don't support MPT)
and SF_EITHER_AMOUNT (support MPT).
Add TypedFieldAmount to declare Amount fields.
Extend STObject with getters/setters for SF_AMOUNT fields.

* Remove STBase and CountedObject inheritance from STAmount and STMPTAmount

* Consolidate errors. Remove redundant checks.

* Add invalid MPT amount check in STTx::passesLocalChecks()
to provide one single check for all tx.
Update unit-tests.
Fix payment for unauthorized holder

* Fix serialization. Extend unit-tests.

* Refactor Payment and Clawback transactors
to have separate functions for MPT/IOU
handling since there is little overlap
between them.
Remove the check for DeletableAccounts

* Fix Linux build

* Address reviewer's feedback

* Replace MPT:pair<uint32,AccountID> with MPTID:uint192
* Remove SFieldMPT
* Replated TypedFieldAmount with generic
  TypedFieldVariant to handle STEitherAmount
* Update comments

* Fix clang-format

* Fix clang-format
  • Loading branch information
gregtatcam authored Aug 26, 2024
1 parent 9578002 commit d2925bd
Show file tree
Hide file tree
Showing 99 changed files with 3,351 additions and 2,019 deletions.
2 changes: 1 addition & 1 deletion Builds/levelization/results/loops.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Loop: test.jtx test.unit_test
test.unit_test == test.jtx

Loop: xrpl.basics xrpl.json
xrpl.json ~= xrpl.basics
xrpl.json == xrpl.basics

Loop: xrpld.app xrpld.core
xrpld.app > xrpld.core
Expand Down
187 changes: 63 additions & 124 deletions include/xrpl/basics/MPTAmount.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,176 +41,115 @@ class MPTAmount : private boost::totally_ordered<MPTAmount>,
private boost::additive<MPTAmount, std::int64_t>
{
public:
using mpt_type = std::int64_t;
using value_type = std::int64_t;

protected:
mpt_type mpt_;
value_type value_;

public:
MPTAmount() = default;
constexpr MPTAmount(MPTAmount const& other) = default;
constexpr MPTAmount&
operator=(MPTAmount const& other) = default;

constexpr MPTAmount(beast::Zero) : mpt_(0)
{
}

constexpr explicit MPTAmount(mpt_type value) : mpt_(value)
{
}

constexpr MPTAmount& operator=(beast::Zero)
{
mpt_ = 0;
return *this;
}

MPTAmount&
operator=(mpt_type value)
{
mpt_ = value;
return *this;
}

constexpr MPTAmount
operator*(mpt_type const& rhs) const
{
return MPTAmount{mpt_ * rhs};
}

friend constexpr MPTAmount
operator*(mpt_type lhs, MPTAmount const& rhs)
{
// multiplication is commutative
return rhs * lhs;
}
constexpr explicit MPTAmount(value_type value);

MPTAmount&
operator+=(MPTAmount const& other)
{
mpt_ += other.mpt();
return *this;
}

MPTAmount&
operator-=(MPTAmount const& other)
{
mpt_ -= other.mpt();
return *this;
}

MPTAmount&
operator+=(mpt_type const& rhs)
{
mpt_ += rhs;
return *this;
}
constexpr MPTAmount& operator=(beast::Zero);

MPTAmount&
operator-=(mpt_type const& rhs)
{
mpt_ -= rhs;
return *this;
}
operator+=(MPTAmount const& other);

MPTAmount&
operator*=(mpt_type const& rhs)
{
mpt_ *= rhs;
return *this;
}
operator-=(MPTAmount const& other);

MPTAmount
operator-() const
{
return MPTAmount{-mpt_};
}
operator-() const;

bool
operator==(MPTAmount const& other) const
{
return mpt_ == other.mpt_;
}
operator==(MPTAmount const& other) const;

bool
operator==(mpt_type other) const
{
return mpt_ == other;
}
operator==(value_type other) const;

bool
operator<(MPTAmount const& other) const
{
return mpt_ < other.mpt_;
}
operator<(MPTAmount const& other) const;

/** Returns true if the amount is not zero */
explicit constexpr operator bool() const noexcept
{
return mpt_ != 0;
}
explicit constexpr operator bool() const noexcept;

/** Return the sign of the amount */
constexpr int
signum() const noexcept
{
return (mpt_ < 0) ? -1 : (mpt_ ? 1 : 0);
}
signum() const noexcept;

Json::Value
jsonClipped() const
{
static_assert(
std::is_signed_v<mpt_type> && std::is_integral_v<mpt_type>,
"Expected MPTAmount to be a signed integral type");

constexpr auto min = std::numeric_limits<Json::Int>::min();
constexpr auto max = std::numeric_limits<Json::Int>::max();

if (mpt_ < min)
return min;
if (mpt_ > max)
return max;
return static_cast<Json::Int>(mpt_);
}
jsonClipped() const;

/** Returns the underlying value. Code SHOULD NOT call this
function unless the type has been abstracted away,
e.g. in a templated function.
*/
constexpr mpt_type
mpt() const
{
return mpt_;
}
constexpr value_type
value() const;

friend std::istream&
operator>>(std::istream& s, MPTAmount& val)
{
s >> val.mpt_;
return s;
}
operator>>(std::istream& s, MPTAmount& val);

static MPTAmount
minPositiveAmount()
{
return MPTAmount{1};
}
minPositiveAmount();
};

constexpr MPTAmount::MPTAmount(value_type value) : value_(value)
{
}

constexpr MPTAmount& MPTAmount::operator=(beast::Zero)
{
value_ = 0;
return *this;
}

/** Returns true if the amount is not zero */
constexpr MPTAmount::operator bool() const noexcept
{
return value_ != 0;
}

/** Return the sign of the amount */
constexpr int
MPTAmount::signum() const noexcept
{
return (value_ < 0) ? -1 : (value_ ? 1 : 0);
}

/** Returns the underlying value. Code SHOULD NOT call this
function unless the type has been abstracted away,
e.g. in a templated function.
*/
constexpr MPTAmount::value_type
MPTAmount::value() const
{
return value_;
}

inline std::istream&
operator>>(std::istream& s, MPTAmount& val)
{
s >> val.value_;
return s;
}

// Output MPTAmount as just the value.
template <class Char, class Traits>
std::basic_ostream<Char, Traits>&
operator<<(std::basic_ostream<Char, Traits>& os, const MPTAmount& q)
{
return os << q.mpt();
return os << q.value();
}

inline std::string
to_string(MPTAmount const& amount)
{
return std::to_string(amount.mpt());
return std::to_string(amount.value());
}

inline MPTAmount
Expand All @@ -225,8 +164,8 @@ mulRatio(
if (!den)
Throw<std::runtime_error>("division by zero");

int128_t const amt128(amt.mpt());
auto const neg = amt.mpt() < 0;
int128_t const amt128(amt.value());
auto const neg = amt.value() < 0;
auto const m = amt128 * num;
auto r = m / den;
if (m % den)
Expand All @@ -236,9 +175,9 @@ mulRatio(
if (neg && !roundUp)
r -= 1;
}
if (r > std::numeric_limits<MPTAmount::mpt_type>::max())
if (r > std::numeric_limits<MPTAmount::value_type>::max())
Throw<std::overflow_error>("XRP mulRatio overflow");
return MPTAmount(r.convert_to<MPTAmount::mpt_type>());
return MPTAmount(r.convert_to<MPTAmount::value_type>());
}

} // namespace ripple
Expand Down
2 changes: 1 addition & 1 deletion include/xrpl/basics/Number.h
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ inline Number::Number(XRPAmount const& x) : Number{x.drops()}
{
}

inline Number::Number(MPTAmount const& x) : Number{x.mpt()}
inline Number::Number(MPTAmount const& x) : Number{x.value()}
{
}

Expand Down
1 change: 1 addition & 0 deletions include/xrpl/basics/base_uint.h
Original file line number Diff line number Diff line change
Expand Up @@ -634,6 +634,7 @@ operator<<(std::ostream& out, base_uint<Bits, Tag> const& u)
#ifndef __INTELLISENSE__
static_assert(sizeof(uint128) == 128 / 8, "There should be no padding bytes");
static_assert(sizeof(uint160) == 160 / 8, "There should be no padding bytes");
static_assert(sizeof(uint192) == 192 / 8, "There should be no padding bytes");
static_assert(sizeof(uint256) == 256 / 8, "There should be no padding bytes");
#endif

Expand Down
Loading

0 comments on commit d2925bd

Please sign in to comment.