20#include <xrpl/basics/LocalValue.h> 
   21#include <xrpl/basics/Log.h> 
   22#include <xrpl/basics/Number.h> 
   23#include <xrpl/basics/base_uint.h> 
   24#include <xrpl/basics/contract.h> 
   25#include <xrpl/basics/safe_cast.h> 
   26#include <xrpl/beast/core/LexicalCast.h> 
   27#include <xrpl/beast/utility/Zero.h> 
   28#include <xrpl/beast/utility/instrumentation.h> 
   29#include <xrpl/json/json_forwards.h> 
   30#include <xrpl/json/json_value.h> 
   31#include <xrpl/protocol/AccountID.h> 
   32#include <xrpl/protocol/Asset.h> 
   33#include <xrpl/protocol/IOUAmount.h> 
   34#include <xrpl/protocol/Issue.h> 
   35#include <xrpl/protocol/MPTAmount.h> 
   36#include <xrpl/protocol/MPTIssue.h> 
   37#include <xrpl/protocol/Protocol.h> 
   38#include <xrpl/protocol/SField.h> 
   39#include <xrpl/protocol/STAmount.h> 
   40#include <xrpl/protocol/STBase.h> 
   41#include <xrpl/protocol/STNumber.h> 
   42#include <xrpl/protocol/Serializer.h> 
   43#include <xrpl/protocol/SystemParameters.h> 
   44#include <xrpl/protocol/UintTypes.h> 
   45#include <xrpl/protocol/XRPAmount.h> 
   46#include <xrpl/protocol/jss.h> 
   48#include <boost/algorithm/string/classification.hpp> 
   49#include <boost/algorithm/string/split.hpp> 
   50#include <boost/multiprecision/detail/default_ops.hpp> 
   51#include <boost/multiprecision/fwd.hpp> 
   52#include <boost/regex/v5/regbase.hpp> 
   53#include <boost/regex/v5/regex.hpp> 
   54#include <boost/regex/v5/regex_fwd.hpp> 
   55#include <boost/regex/v5/regex_match.hpp> 
   80        Throw<std::runtime_error>(error);
 
   82        amount.
exponent() == 0, 
"ripple::getInt64Value : exponent is zero");
 
   88        "ripple::getInt64Value : mantissa must roundtrip");
 
 
  149            Throw<std::runtime_error>(
"negative zero is not canonical");
 
  161        Throw<std::runtime_error>(
"invalid native currency");
 
  166        Throw<std::runtime_error>(
"invalid native account");
 
  169    int offset = 
static_cast<int>(
value >> (64 - 10));
 
  171    value &= ~(1023ull << (64 - 10));
 
  175        bool isNegative = (offset & 256) == 0;
 
  176        offset = (offset & 255) - 97;  
 
  181            Throw<std::runtime_error>(
"invalid currency value");
 
  193        Throw<std::runtime_error>(
"invalid currency value");
 
 
  213    , mIsNegative(negative)
 
  217        "ripple::STAmount::STAmount(SField, std::uint64_t, bool) : maximum " 
 
  223    , mAsset(from.mAsset)
 
  224    , mValue(from.mValue)
 
  225    , mOffset(from.mOffset)
 
  226    , mIsNegative(from.mIsNegative)
 
  230        "ripple::STAmount::STAmount(SField, STAmount) : maximum input");
 
 
  240    , mIsNegative(mantissa != 0 && negative)
 
  244        "ripple::STAmount::STAmount(std::uint64_t, bool) : maximum mantissa " 
 
  249    : mAsset(
xrpIssue()), mOffset(0), mIsNegative(amount < 
beast::zero)
 
  252        mValue = unsafe_cast<std::uint64_t>(-amount.
drops());
 
  254        mValue = unsafe_cast<std::uint64_t>(amount.
drops());
 
 
  274    return emplace(n, buf, std::move(*
this));
 
 
  286        Throw<std::logic_error>(
 
  287            "Cannot return non-native STAmount as XRPAmount");
 
  290    XRPL_ASSERT(
mOffset == 0, 
"ripple::STAmount::xrp : amount is canonical");
 
 
  301    if (
native() || !holds<Issue>())
 
  302        Throw<std::logic_error>(
"Cannot return non-IOU STAmount as IOUAmount");
 
 
  316    if (!holds<MPTIssue>())
 
  317        Throw<std::logic_error>(
"Cannot return STAmount as MPTAmount");
 
  320    XRPL_ASSERT(
mOffset == 0, 
"ripple::STAmount::mpt : amount is canonical");
 
 
  333        "ripple::STAmount::operator=(IOUAmount) : is not XRP");
 
 
  367        Throw<std::runtime_error>(
"Can't add amounts that are't comparable!");
 
  369    if (v2 == beast::zero)
 
  372    if (v1 == beast::zero)
 
  422    if ((fv >= -10) && (fv <= 10))
 
 
  465    if (offerOut == beast::zero)
 
  470        if (r == beast::zero)  
 
  474            "ripple::getRate : exponent inside range");
 
  476        return (ret << (64 - 8)) | r.
mantissa();
 
 
  512    if (a == beast::zero || b == beast::zero)
 
  540        return ((rhs.
negative() ? -rhs : rhs) +
 
  541                (lhs.
negative() ? -lhs : lhs)) <= maxLoss;
 
  562    UNREACHABLE(
"STAmount::canAdd : unexpected STAmount type");
 
 
  592    if (b == beast::zero)
 
  637    UNREACHABLE(
"STAmount::canSubtract : unexpected STAmount type");
 
 
  686    if (*
this == beast::zero)
 
  695    bool const scientific(
 
  711    XRPL_ASSERT(
mOffset + 43 > 0, 
"ripple::STAmount::getText : minimum offset");
 
  713    size_t const pad_prefix = 27;
 
  714    size_t const pad_suffix = 23;
 
  718    val.
append(pad_prefix, 
'0');
 
  720    val.
append(pad_suffix, 
'0');
 
  722    size_t const offset(
mOffset + 43);
 
  724    auto pre_from(val.
begin());
 
  725    auto const pre_to(val.
begin() + offset);
 
  727    auto const post_from(val.
begin() + offset);
 
  728    auto post_to(val.
end());
 
  733        pre_from += pad_prefix;
 
  736        post_to >= post_from,
 
  737        "ripple::STAmount::getText : first distance check");
 
  739    pre_from = 
std::find_if(pre_from, pre_to, [](
char c) { 
return c != 
'0'; });
 
  744        post_to -= pad_suffix;
 
  747        post_to >= post_from,
 
  748        "ripple::STAmount::getText : second distance check");
 
  753                  [](
char c) { 
return c != 
'0'; })
 
  757    if (pre_from == pre_to)
 
  760        ret.
append(pre_from, pre_to);
 
  762    if (post_to != post_from)
 
  765        ret.
append(post_from, post_to);
 
 
  784        XRPL_ASSERT(
mOffset == 0, 
"ripple::STAmount::add : zero offset");
 
  793        auto u8 = 
static_cast<unsigned char>(
cMPToken >> 56);
 
  795            u8 |= 
static_cast<unsigned char>(
cPositive >> 56);
 
  802        if (*
this == beast::zero)
 
 
  822    return v && (*v == *
this);
 
 
  866            Throw<std::runtime_error>(
"Native currency amount out of range");
 
  869            Throw<std::runtime_error>(
"MPT amount out of range");
 
  875            auto set = [&](
auto const& val) {
 
  898                    Throw<std::runtime_error>(
 
  899                        "Native currency amount out of range");
 
  901                    Throw<std::runtime_error>(
"MPT amount out of range");
 
  909            Throw<std::runtime_error>(
"Native currency amount out of range");
 
  911            Throw<std::runtime_error>(
"MPT amount out of range");
 
  938            Throw<std::runtime_error>(
"value overflow");
 
  953        Throw<std::runtime_error>(
"value overflow");
 
  957        "ripple::STAmount::canonicalize : value inside range");
 
  960        "ripple::STAmount::canonicalize : offset inside range");
 
  963        "ripple::STAmount::canonicalize : value or offset set");
 
 
  990    int exponent = 
static_cast<int>(rate >> (64 - 8)) - 100;
 
 
 1000        Throw<std::runtime_error>(
 
 1001            "XRP and MPT must be specified as integral amount.");
 
 1002    return {asset, parts.mantissa, parts.exponent, parts.negative};
 
 
 1017        Throw<std::runtime_error>(
 
 1018            "XRP may not be specified with a null Json value");
 
 1023            Throw<std::runtime_error>(
"Invalid Asset's Json specification");
 
 1025        value = v[jss::value];
 
 1026        if (v.
isMember(jss::mpt_issuance_id))
 
 1029            currencyOrMPTID = v[jss::mpt_issuance_id];
 
 1033            currencyOrMPTID = v[jss::currency];
 
 1034            issuer = v[jss::issuer];
 
 1047        boost::split(elements, val, boost::is_any_of(
"\t\n\r ,/"));
 
 1049        if (elements.
size() > 3)
 
 1050            Throw<std::runtime_error>(
"invalid amount string");
 
 1052        value = elements[0];
 
 1054        if (elements.
size() > 1)
 
 1055            currencyOrMPTID = elements[1];
 
 1057        if (elements.
size() > 2)
 
 1058            issuer = elements[2];
 
 1065    bool const native = !currencyOrMPTID.
isString() ||
 
 1072            Throw<std::runtime_error>(
"XRP may not be specified as an object");
 
 1082                Throw<std::runtime_error>(
"invalid MPTokenIssuanceID");
 
 1089                Throw<std::runtime_error>(
"invalid currency");
 
 1092                Throw<std::runtime_error>(
"invalid issuer");
 
 1094                Throw<std::runtime_error>(
"invalid issuer");
 
 1103        if (value.
asInt() >= 0)
 
 1122            Throw<std::runtime_error>(
 
 1123                "XRP and MPT must be specified as integral amount.");
 
 1127        Throw<std::runtime_error>(
"invalid amount type");
 
 
 1144            << 
"amountFromJsonNoThrow: caught: " << e.
what();
 
 
 1166        Throw<std::runtime_error>(
 
 1167            "Can't compare amounts that are't comparable!");
 
 
 1225    boost::multiprecision::uint128_t ret;
 
 1227    boost::multiprecision::multiply(ret, multiplier, multiplicand);
 
 1232        Throw<std::overflow_error>(
 
 1237    return static_cast<uint64_t
>(ret);
 
 
 1247    boost::multiprecision::uint128_t ret;
 
 1249    boost::multiprecision::multiply(ret, multiplier, multiplicand);
 
 1255        Throw<std::overflow_error>(
 
 1261    return static_cast<uint64_t
>(ret);
 
 
 1267    if (den == beast::zero)
 
 1268        Throw<std::runtime_error>(
"division by zero");
 
 1270    if (num == beast::zero)
 
 1305        numOffset - denOffset - 17,
 
 
 1312    if (v1 == beast::zero || v2 == beast::zero)
 
 1320        if (minV > 3000000000ull)  
 
 1321            Throw<std::runtime_error>(
"Native value overflow");
 
 1323        if (((maxV >> 32) * minV) > 2095475792ull)  
 
 1324            Throw<std::runtime_error>(
"Native value overflow");
 
 1333        if (minV > 3037000499ull)  
 
 1334            Throw<std::runtime_error>(
"MPT value overflow");
 
 1336        if (((maxV >> 32) * minV) > 2147483648ull)  
 
 1337            Throw<std::runtime_error>(
"MPT value overflow");
 
 1339        return STAmount(asset, minV * maxV);
 
 1345        return STAmount{asset, r.mantissa(), r.exponent()};
 
 1378        offset1 + offset2 + 14,
 
 
 1418            value += (loops >= 2) ? 9 : 10;  
 
 
 1452            bool hadRemainder = 
false;
 
 1460                hadRemainder |= (value != (newValue * 10));
 
 1465                (hadRemainder && roundUp) ? 10 : 9;  
 
 
 1487class DontAffectNumberRoundMode
 
 1494    DontAffectNumberRoundMode(DontAffectNumberRoundMode 
const&) = 
delete;
 
 1496    DontAffectNumberRoundMode&
 
 1497    operator=(DontAffectNumberRoundMode 
const&) = 
delete;
 
 1508    typename MightSaveRound>
 
 1516    if (v1 == beast::zero || v2 == beast::zero)
 
 1519    bool const xrp = asset.
native();
 
 1526        if (minV > 3000000000ull)  
 
 1527            Throw<std::runtime_error>(
"Native value overflow");
 
 1529        if (((maxV >> 32) * minV) > 2095475792ull)  
 
 1530            Throw<std::runtime_error>(
"Native value overflow");
 
 1540        if (minV > 3037000499ull)  
 
 1541            Throw<std::runtime_error>(
"MPT value overflow");
 
 1543        if (((maxV >> 32) * minV) > 2147483648ull)  
 
 1544            Throw<std::runtime_error>(
"MPT value overflow");
 
 1546        return STAmount(asset, minV * maxV);
 
 1583    int offset = offset1 + offset2 + 14;
 
 1584    if (resultNegative != roundUp)
 
 1586        CanonicalizeFunc(xrp, amount, offset, roundUp);
 
 1592        return STAmount(asset, amount, offset, resultNegative);
 
 1595    if (roundUp && !resultNegative && !result)
 
 1609        return STAmount(asset, amount, offset, resultNegative);
 
 
 1621    return mulRoundImpl<canonicalizeRound, DontAffectNumberRoundMode>(
 
 1622        v1, v2, asset, roundUp);
 
 
 1632    return mulRoundImpl<canonicalizeRoundStrict, NumberRoundModeGuard>(
 
 1633        v1, v2, asset, roundUp);
 
 
 1638template <
typename MightSaveRound>
 
 1646    if (den == beast::zero)
 
 1647        Throw<std::runtime_error>(
"division by zero");
 
 1649    if (num == beast::zero)
 
 1684        numVal, 
tenTo17, denVal, (resultNegative != roundUp) ? denVal - 1 : 0);
 
 1686    int offset = numOffset - denOffset - 17;
 
 1688    if (resultNegative != roundUp)
 
 1697        MightSaveRound 
const savedRound(
 
 1698            roundUp ^ resultNegative ? upward : downward);
 
 1699        return STAmount(asset, amount, offset, resultNegative);
 
 1702    if (roundUp && !resultNegative && !result)
 
 1716        return STAmount(asset, amount, offset, resultNegative);
 
 
 1728    return divRoundImpl<DontAffectNumberRoundMode>(num, den, asset, roundUp);
 
 
 1738    return divRoundImpl<NumberRoundModeGuard>(num, den, asset, roundUp);
 
 
bool isObjectOrNull() const
 
std::string asString() const
Returns the unquoted string value.
 
bool isNull() const
isNull() tests to see if this field is null.
 
bool isMember(char const *key) const
Return true if the object has a member named key.
 
Value get(UInt index, Value const &defaultValue) const
If the array contains at least index+1 elements, returns the element value, otherwise returns default...
 
void setJson(Json::Value &jv) const
 
constexpr TIss const & get() const
 
constexpr bool holds() const
 
std::string getText() const
 
Floating point representation of amounts with high dynamic range.
 
int exponent() const noexcept
 
std::int64_t mantissa() const noexcept
 
A currency issued by an account.
 
constexpr value_type value() const
Returns the underlying value.
 
constexpr MPTID const & getMptID() const
 
constexpr bool holds() const noexcept
 
Json::Value getJson(JsonOptions=JsonOptions::none) const override
 
static std::uint64_t const cMaxNativeN
 
STAmount & operator=(beast::Zero)
 
int exponent() const noexcept
 
STBase * move(std::size_t n, void *buf) override
 
Asset const & asset() const
 
static std::uint64_t const cPositive
 
constexpr TIss const & get() const
 
static int const cMaxOffset
 
static int const cMinOffset
 
STAmount & operator+=(STAmount const &)
 
static std::uint64_t const cMinValue
 
static std::unique_ptr< STAmount > construct(SerialIter &, SField const &name)
 
void setIssue(Asset const &asset)
Set the Issue for this amount.
 
void setJson(Json::Value &) const
 
bool isDefault() const override
 
STAmount & operator-=(STAmount const &)
 
void add(Serializer &s) const override
 
static std::uint64_t const cIssuedCurrency
 
static std::uint64_t const cMPToken
 
SerializedTypeID getSType() const override
 
static std::uint64_t const cMaxValue
 
STAmount const & value() const noexcept
 
std::string getText() const override
 
bool negative() const noexcept
 
bool isEquivalent(STBase const &t) const override
 
STBase * copy(std::size_t n, void *buf) const override
 
static std::uint64_t const cValueMask
 
Issue const & issue() const
 
std::uint64_t mantissa() const noexcept
 
std::string getFullText() const override
 
STAmount(SerialIter &sit, SField const &name)
 
bool native() const noexcept
 
static std::uint64_t const uRateOne
 
A type which can be exported to a well known binary format.
 
SField const & getFName() const
 
static STBase * emplace(std::size_t n, void *buf, T &&val)
 
int addBitString(base_uint< Bits, Tag > const &v)
 
int add8(unsigned char i)
 
constexpr value_type drops() const
Returns the number of drops.
 
constexpr bool parseHex(std::string_view sv)
Parse a hex string into a base_uint.
 
T make_reverse_iterator(T... args)
 
@ objectValue
object value (collection of name/value pairs).
 
TER valid(STTx const &tx, ReadView const &view, AccountID const &src, beast::Journal j)
 
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
 
Issue const & xrpIssue()
Returns an asset specifier that represents XRP.
 
static void canonicalizeRoundStrict(bool native, std::uint64_t &value, int &offset, bool roundUp)
 
STAmount divide(STAmount const &amount, Rate const &rate)
 
NumberParts partsFromString(std::string const &number)
 
bool isXRP(AccountID const &c)
 
bool canSubtract(STAmount const &amt1, STAmount const &amt2)
Determines if it is safe to subtract one STAmount from another.
 
bool to_issuer(AccountID &, std::string const &)
Convert hex or base58 string to AccountID.
 
static bool areComparable(STAmount const &v1, STAmount const &v2)
 
STAmount divRoundStrict(STAmount const &v1, STAmount const &v2, Asset const &asset, bool roundUp)
 
STAmount amountFromJson(SField const &name, Json::Value const &v)
 
bool canAdd(STAmount const &amt1, STAmount const &amt2)
Safely checks if two STAmount values can be added without overflow, underflow, or precision loss.
 
static std::uint64_t const tenTo17
 
std::uint64_t constexpr maxMPTokenAmount
The maximum amount of MPTokenIssuance.
 
STAmount amountFromQuality(std::uint64_t rate)
 
static std::string const & systemCurrencyCode()
 
bool set(T &target, std::string const &name, Section const §ion)
Set a value from a configuration Section If the named value is not found or doesn't parse as a T,...
 
static std::uint64_t const tenTo14m1
 
STAmount multiply(STAmount const &amount, Rate const &rate)
 
std::uint64_t getRate(STAmount const &offerOut, STAmount const &offerIn)
 
static std::int64_t getSNValue(STAmount const &amount)
 
bool validJSONAsset(Json::Value const &jv)
 
beast::Journal debugLog()
Returns a debug journal.
 
Issue const & noIssue()
Returns an asset specifier that represents no account and currency.
 
static std::int64_t getInt64Value(STAmount const &amount, bool valid, char const *error)
 
bool amountFromJsonNoThrow(STAmount &result, Json::Value const &jvSource)
 
static std::int64_t getMPTValue(STAmount const &amount)
 
bool operator<(Slice const &lhs, Slice const &rhs) noexcept
 
STAmount divRound(STAmount const &v1, STAmount const &v2, Asset const &asset, bool roundUp)
 
static std::uint64_t muldiv(std::uint64_t multiplier, std::uint64_t multiplicand, std::uint64_t divisor)
 
Number operator-(Number const &x, Number const &y)
 
STAmount amountFromString(Asset const &asset, std::string const &amount)
 
STAmount mulRound(STAmount const &v1, STAmount const &v2, Asset const &asset, bool roundUp)
 
constexpr base_uint< Bits, Tag > operator+(base_uint< Bits, Tag > const &a, base_uint< Bits, Tag > const &b)
 
static STAmount mulRoundImpl(STAmount const &v1, STAmount const &v2, Asset const &asset, bool roundUp)
 
constexpr bool operator==(base_uint< Bits, Tag > const &lhs, base_uint< Bits, Tag > const &rhs)
 
static STAmount divRoundImpl(STAmount const &num, STAmount const &den, Asset const &asset, bool roundUp)
 
STAmount mulRoundStrict(STAmount const &v1, STAmount const &v2, Asset const &asset, bool roundUp)
 
static std::uint64_t muldiv_round(std::uint64_t multiplier, std::uint64_t multiplicand, std::uint64_t divisor, std::uint64_t rounding)
 
static std::uint64_t const tenTo14
 
bool getSTNumberSwitchover()
 
bool to_currency(Currency &, std::string const &)
Tries to convert a string to a Currency, returns true on success.
 
static void canonicalizeRound(bool native, std::uint64_t &value, int &offset, bool)
 
Note, should be treated as flags that can be | and &.