mirror of
https://github.com/XRPLF/rippled.git
synced 2026-04-29 15:37:57 +00:00
- Add the LendingProtocol amendment
- Add Loan Broker and Loan ledger objects:
- Also add new SFields, Keylet functions, and an Invariant to verify no
illegal field modification
- Update list of "constant" fields from spec
- Also add a general check for all object types for the type and index
fields
- refactor: Check transaction flags in preflight0
- Adds a flagMask parameter to preflight1 so that it's impossible to
forget to check flags.
- Also adds a short hash prefix to all Transactor log messages.
- refactor: Generalize Transactor preflight:
- Derived classes no longer need to explicitly check amendments, nor
call into preflight1 or preflight2.
- implemeng LoanBrokerSet
- Transactions: LoanDelete, LoanManage, LoanDraw, LoanPay
- LoanBrokerSet creation mostly done. Need update.
- Also added a lookup table for pseudo account fields.
- Update changed field name.
- Modify modifiable fields in an update. Note there are only two.
- Add a node field to dirLink, defaulting sfOwnerNode, so other
relationships can be updated.
- Create some helper classes for transaction fields
- Test that they work by converting some of the existing classes
- Finish creating helper classes for JTx fields
- Also change the pseudo account field lookup to a function that uses
a switch
- Update tests, update pseudo-account checking
- Generalize some of the Invariant checks using macro files
- Valid ledger entry type
- Valid new account root and pseudo account check
- Enumerate transaction privileges for invariants
- Allows them to be defined in transactions.macro instead of needing to
scrutinize every existing Invariant class.
- List is not necessarily comprehensive, but does cover every check
where more than one transaction type is involved.
- Reserve a few values between Vault and Lending for future use
- Pseudo-account improvements
- Define pseudo-account fields with an sfield flag
- Pseudo-account invariant checks rules whenever a pseudo-account is
created or modified.
- Move some helper functions.
- Check the regular key in the pseudo-transaction invariant check.
- Transactor::checkSign will always fail for a pseudo-account, so even
if someone figures out how to get a good signature, it won't work.
- Fix account creation to check both amendments
- Add a validity range for sfDebtMaximum
- Change more "failed" messages. The goal here is to be able to search
the log for "failed" and ONLY get test failures.
- NoModifiedUnmodifiableFields and ValidPseudoAccounts
- Move the Invariants_test class into the test namespace
- Clang wants an explicit ctor to emplace in a vector
- Refactor: Add a Transactor base function to make it easier to get the
owner reserve increment as a fee.
- Refactor: Add an overload jtx::fee(increment) to pay an owner reserve.
- Initial implementation of LoanBrokerDelete
- Generalize the LoanBroker lifecycle test
- Refactor ApplyView::dirAdd to give access to low-level operations
- Takes a page from #5362, which may turn out to be useful!
- Start writing Loan Broker invariants and tests
- Specifically those mentioned for LoanBrokerDelete
- Move all detail namespaces to be under ripple
- Avoids problems with namespace collisions / ambiguous symbol issues
with unity builds, especially when adding or removing files.
- Add LoanBrokerCoverDeposit transaction
- Add LoanBrokerCoverWithdraw transaction
- Start writing tests for LoanBrokerCover*
- Add support for `Asset` and `MPTIssue` to some `jtx` helper classes
and functions (`balance`, `expectLine`)
- Add support for pseudo-accounts to `jtx::Account` by allowing directly
setting the AccountID without a matching key.
- Add Asset and MPTIssue support to more jtx objects / functions
- Unfortunately, to work around some ambiguous symbol compilation
errors, I had to change the implicit conversion from IOU to Asset to
a conversion from IOU to PrettyAsset, and add a more explicit
`asset()` function. This workaround only required changing two
existing tests, so seems acceptable.
- Ensure that an account is not deleted with an XRP balance
- Updates the AccountRootsDeletedClean invariant
- Finish up the Loan Broker tests
- Move inclusion of Transactor headers to transactions.macro
- Only need to update in one place when adding a new transaction.
- Start implementing LoanSet transactor
- Add some more values and functions to make it easier to work with
basis point values / bips.
- Fix several earlier mistakes.
- Generalize the check*Sign functions to support CounterParty
- checkSign, checkSingleSign, and checkMultiSign in STTx and Transactor
- Start writing Loan tests
- Required adding support for counterparty signature to jtx framework:
arbitrary signature field destination, multiple signer callbacks
- Get Counterparty signing working
- Add more LoanSet unit tests, added LoanBroker LoanSequence field
- LoanSequence will prevent loan key collisions
- Change Loan object indexing, fix several broken LoanSet unit tests
- Loan objects will now only be indexed by LoanBrokerID and
LoanSequence, which is a new field in LoanBroker. Also changes
Loan.Sequence to Loan.LoanSequence to match up.
- Several tests weren't working because of `PrettyAsset` scaling. Also,
`PrettyAsset` calculations could overflow. Made that less likely by
changing the type of `scale_`.
- LoanSet will fail if an account tries to loan to itself.
- Ensure that an account is not deleted with a non-zero owner count
- Updates the AccountRootsDeletedClean invariant
- Add unit tests to create a Loan successfully
- Fix a few field initializations in LoanSet
- Refactor issuance validity check in VaultCreate
- Utility function: canAddHolding
- Call canAddHolding from any transactor that call addEmptyHolding
(LoanBrokerSet, LoanSet)
- Start implementing LoanManage transaction
- Also add a ValidLoan invariant
- Finish `LoanManage` functionality and tests, modulo LoanDraw/Pay
- Allow existing trust lines to loan brokers to be managed (by issuer)
- Implement LoanDelete, and fix a bunch of math errors in LoanManage
- Update to match latest spec: compute interest, LoanBroker reserves
- refactor: Define getFlagsMask in the base Transactor class
- Returns tfUniversalMask for most transactors
- Only transactors that use other flags need to override
- Implement LoanDraw, and made good progress on related tests
- Start implementing LoanPay transaction
- Implement LoanPay & most tests
- Also add an XRPL_ASSERT_PARTS, which splits the parts of the assert message
so I don't have to remember the proper formatting.
Start writing LoanPay transaction tests
784 lines
18 KiB
C++
784 lines
18 KiB
C++
//------------------------------------------------------------------------------
|
|
/*
|
|
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_PROTOCOL_STAMOUNT_H_INCLUDED
|
|
#define RIPPLE_PROTOCOL_STAMOUNT_H_INCLUDED
|
|
|
|
#include <xrpl/basics/CountedObject.h>
|
|
#include <xrpl/basics/LocalValue.h>
|
|
#include <xrpl/basics/Number.h>
|
|
#include <xrpl/beast/utility/instrumentation.h>
|
|
#include <xrpl/protocol/Asset.h>
|
|
#include <xrpl/protocol/IOUAmount.h>
|
|
#include <xrpl/protocol/Issue.h>
|
|
#include <xrpl/protocol/MPTAmount.h>
|
|
#include <xrpl/protocol/SField.h>
|
|
#include <xrpl/protocol/STBase.h>
|
|
#include <xrpl/protocol/Serializer.h>
|
|
#include <xrpl/protocol/XRPAmount.h>
|
|
#include <xrpl/protocol/json_get_or_throw.h>
|
|
|
|
namespace ripple {
|
|
|
|
// Internal form:
|
|
// 1: If amount is zero, then value is zero and offset is -100
|
|
// 2: Otherwise:
|
|
// legal offset range is -96 to +80 inclusive
|
|
// value range is 10^15 to (10^16 - 1) inclusive
|
|
// amount = value * [10 ^ offset]
|
|
|
|
// Wire form:
|
|
// High 8 bits are (offset+142), legal range is, 80 to 22 inclusive
|
|
// Low 56 bits are value, legal range is 10^15 to (10^16 - 1) inclusive
|
|
class STAmount final : public STBase, public CountedObject<STAmount>
|
|
{
|
|
public:
|
|
using mantissa_type = std::uint64_t;
|
|
using exponent_type = int;
|
|
using rep = std::pair<mantissa_type, exponent_type>;
|
|
|
|
private:
|
|
Asset mAsset;
|
|
mantissa_type mValue;
|
|
exponent_type mOffset;
|
|
bool mIsNegative;
|
|
|
|
public:
|
|
using value_type = STAmount;
|
|
|
|
static int const cMinOffset = -96;
|
|
static int const cMaxOffset = 80;
|
|
|
|
// Maximum native value supported by the code
|
|
static std::uint64_t const cMinValue = 1000000000000000ull;
|
|
static std::uint64_t const cMaxValue = 9999999999999999ull;
|
|
static std::uint64_t const cMaxNative = 9000000000000000000ull;
|
|
|
|
// Max native value on network.
|
|
static std::uint64_t const cMaxNativeN = 100000000000000000ull;
|
|
static std::uint64_t const cIssuedCurrency = 0x8000000000000000ull;
|
|
static std::uint64_t const cPositive = 0x4000000000000000ull;
|
|
static std::uint64_t const cMPToken = 0x2000000000000000ull;
|
|
static std::uint64_t const cValueMask = ~(cPositive | cMPToken);
|
|
|
|
static std::uint64_t const uRateOne;
|
|
|
|
//--------------------------------------------------------------------------
|
|
STAmount(SerialIter& sit, SField const& name);
|
|
|
|
struct unchecked
|
|
{
|
|
explicit unchecked() = default;
|
|
};
|
|
|
|
// Do not call canonicalize
|
|
template <AssetType A>
|
|
STAmount(
|
|
SField const& name,
|
|
A const& asset,
|
|
mantissa_type mantissa,
|
|
exponent_type exponent,
|
|
bool negative,
|
|
unchecked);
|
|
|
|
template <AssetType A>
|
|
STAmount(
|
|
A const& asset,
|
|
mantissa_type mantissa,
|
|
exponent_type exponent,
|
|
bool negative,
|
|
unchecked);
|
|
|
|
// Call canonicalize
|
|
template <AssetType A>
|
|
STAmount(
|
|
SField const& name,
|
|
A const& asset,
|
|
mantissa_type mantissa = 0,
|
|
exponent_type exponent = 0,
|
|
bool negative = false);
|
|
|
|
STAmount(SField const& name, std::int64_t mantissa);
|
|
|
|
STAmount(
|
|
SField const& name,
|
|
std::uint64_t mantissa = 0,
|
|
bool negative = false);
|
|
|
|
explicit STAmount(std::uint64_t mantissa = 0, bool negative = false);
|
|
|
|
explicit STAmount(SField const& name, STAmount const& amt);
|
|
|
|
template <AssetType A>
|
|
STAmount(
|
|
A const& asset,
|
|
std::uint64_t mantissa = 0,
|
|
int exponent = 0,
|
|
bool negative = false)
|
|
: mAsset(asset)
|
|
, mValue(mantissa)
|
|
, mOffset(exponent)
|
|
, mIsNegative(negative)
|
|
{
|
|
canonicalize();
|
|
}
|
|
|
|
// VFALCO Is this needed when we have the previous signature?
|
|
template <AssetType A>
|
|
STAmount(
|
|
A const& asset,
|
|
std::uint32_t mantissa,
|
|
int exponent = 0,
|
|
bool negative = false);
|
|
|
|
template <AssetType A>
|
|
STAmount(A const& asset, std::int64_t mantissa, int exponent = 0);
|
|
|
|
template <AssetType A>
|
|
STAmount(A const& asset, int mantissa, int exponent = 0);
|
|
|
|
template <AssetType A>
|
|
STAmount(A const& asset, Number const& number)
|
|
: STAmount(asset, number.mantissa(), number.exponent())
|
|
{
|
|
}
|
|
|
|
// Legacy support for new-style amounts
|
|
STAmount(IOUAmount const& amount, Issue const& issue);
|
|
STAmount(XRPAmount const& amount);
|
|
STAmount(MPTAmount const& amount, MPTIssue const& mptIssue);
|
|
operator Number() const;
|
|
|
|
//--------------------------------------------------------------------------
|
|
//
|
|
// Observers
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
int
|
|
exponent() const noexcept;
|
|
|
|
bool
|
|
native() const noexcept;
|
|
|
|
template <ValidIssueType TIss>
|
|
constexpr bool
|
|
holds() const noexcept;
|
|
|
|
bool
|
|
negative() const noexcept;
|
|
|
|
std::uint64_t
|
|
mantissa() const noexcept;
|
|
|
|
Asset const&
|
|
asset() const;
|
|
|
|
template <ValidIssueType TIss>
|
|
constexpr TIss const&
|
|
get() const;
|
|
|
|
Issue const&
|
|
issue() const;
|
|
|
|
// These three are deprecated
|
|
Currency const&
|
|
getCurrency() const;
|
|
|
|
AccountID const&
|
|
getIssuer() const;
|
|
|
|
int
|
|
signum() const noexcept;
|
|
|
|
/** Returns a zero value with the same issuer and currency. */
|
|
STAmount
|
|
zeroed() const;
|
|
|
|
void
|
|
setJson(Json::Value&) const;
|
|
|
|
STAmount const&
|
|
value() const noexcept;
|
|
|
|
//--------------------------------------------------------------------------
|
|
//
|
|
// Operators
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
explicit
|
|
operator bool() const noexcept;
|
|
|
|
STAmount&
|
|
operator+=(STAmount const&);
|
|
STAmount&
|
|
operator-=(STAmount const&);
|
|
|
|
STAmount& operator=(beast::Zero);
|
|
|
|
STAmount&
|
|
operator=(XRPAmount const& amount);
|
|
|
|
STAmount&
|
|
operator=(Number const&);
|
|
|
|
//--------------------------------------------------------------------------
|
|
//
|
|
// Modification
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
void
|
|
negate();
|
|
|
|
void
|
|
clear();
|
|
|
|
// Zero while copying currency and issuer.
|
|
void
|
|
clear(Asset const& asset);
|
|
|
|
void
|
|
setIssuer(AccountID const& uIssuer);
|
|
|
|
/** Set the Issue for this amount. */
|
|
void
|
|
setIssue(Asset const& asset);
|
|
|
|
//--------------------------------------------------------------------------
|
|
//
|
|
// STBase
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
SerializedTypeID
|
|
getSType() const override;
|
|
|
|
std::string
|
|
getFullText() const override;
|
|
|
|
std::string
|
|
getText() const override;
|
|
|
|
Json::Value getJson(JsonOptions = JsonOptions::none) const override;
|
|
|
|
void
|
|
add(Serializer& s) const override;
|
|
|
|
bool
|
|
isEquivalent(STBase const& t) const override;
|
|
|
|
bool
|
|
isDefault() const override;
|
|
|
|
XRPAmount
|
|
xrp() const;
|
|
IOUAmount
|
|
iou() const;
|
|
MPTAmount
|
|
mpt() const;
|
|
|
|
private:
|
|
static std::unique_ptr<STAmount>
|
|
construct(SerialIter&, SField const& name);
|
|
|
|
void
|
|
set(std::int64_t v);
|
|
void
|
|
canonicalize();
|
|
|
|
STBase*
|
|
copy(std::size_t n, void* buf) const override;
|
|
STBase*
|
|
move(std::size_t n, void* buf) override;
|
|
|
|
STAmount&
|
|
operator=(IOUAmount const& iou);
|
|
|
|
friend class detail::STVar;
|
|
|
|
friend STAmount
|
|
operator+(STAmount const& v1, STAmount const& v2);
|
|
};
|
|
|
|
template <AssetType A>
|
|
STAmount::STAmount(
|
|
SField const& name,
|
|
A const& asset,
|
|
mantissa_type mantissa,
|
|
exponent_type exponent,
|
|
bool negative,
|
|
unchecked)
|
|
: STBase(name)
|
|
, mAsset(asset)
|
|
, mValue(mantissa)
|
|
, mOffset(exponent)
|
|
, mIsNegative(negative)
|
|
{
|
|
}
|
|
|
|
template <AssetType A>
|
|
STAmount::STAmount(
|
|
A const& asset,
|
|
mantissa_type mantissa,
|
|
exponent_type exponent,
|
|
bool negative,
|
|
unchecked)
|
|
: mAsset(asset), mValue(mantissa), mOffset(exponent), mIsNegative(negative)
|
|
{
|
|
}
|
|
|
|
template <AssetType A>
|
|
STAmount::STAmount(
|
|
SField const& name,
|
|
A const& asset,
|
|
std::uint64_t mantissa,
|
|
int exponent,
|
|
bool negative)
|
|
: STBase(name)
|
|
, mAsset(asset)
|
|
, mValue(mantissa)
|
|
, mOffset(exponent)
|
|
, mIsNegative(negative)
|
|
{
|
|
// mValue is uint64, but needs to fit in the range of int64
|
|
XRPL_ASSERT(
|
|
mValue <= std::numeric_limits<std::int64_t>::max(),
|
|
"ripple::STAmount::STAmount(SField, A, std::uint64_t, int, bool) : "
|
|
"maximum mantissa input");
|
|
canonicalize();
|
|
}
|
|
|
|
template <AssetType A>
|
|
STAmount::STAmount(A const& asset, std::int64_t mantissa, int exponent)
|
|
: mAsset(asset), mOffset(exponent)
|
|
{
|
|
set(mantissa);
|
|
canonicalize();
|
|
}
|
|
|
|
template <AssetType A>
|
|
STAmount::STAmount(
|
|
A const& asset,
|
|
std::uint32_t mantissa,
|
|
int exponent,
|
|
bool negative)
|
|
: STAmount(asset, safe_cast<std::uint64_t>(mantissa), exponent, negative)
|
|
{
|
|
}
|
|
|
|
template <AssetType A>
|
|
STAmount::STAmount(A const& asset, int mantissa, int exponent)
|
|
: STAmount(asset, safe_cast<std::int64_t>(mantissa), exponent)
|
|
{
|
|
}
|
|
|
|
// Legacy support for new-style amounts
|
|
inline STAmount::STAmount(IOUAmount const& amount, Issue const& issue)
|
|
: mAsset(issue)
|
|
, mOffset(amount.exponent())
|
|
, mIsNegative(amount < beast::zero)
|
|
{
|
|
if (mIsNegative)
|
|
mValue = unsafe_cast<std::uint64_t>(-amount.mantissa());
|
|
else
|
|
mValue = unsafe_cast<std::uint64_t>(amount.mantissa());
|
|
|
|
canonicalize();
|
|
}
|
|
|
|
inline STAmount::STAmount(MPTAmount const& amount, MPTIssue const& mptIssue)
|
|
: mAsset(mptIssue), mOffset(0), mIsNegative(amount < beast::zero)
|
|
{
|
|
if (mIsNegative)
|
|
mValue = unsafe_cast<std::uint64_t>(-amount.value());
|
|
else
|
|
mValue = unsafe_cast<std::uint64_t>(amount.value());
|
|
|
|
canonicalize();
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
//
|
|
// Creation
|
|
//
|
|
//------------------------------------------------------------------------------
|
|
|
|
// VFALCO TODO The parameter type should be Quality not uint64_t
|
|
STAmount
|
|
amountFromQuality(std::uint64_t rate);
|
|
|
|
STAmount
|
|
amountFromString(Asset const& asset, std::string const& amount);
|
|
|
|
STAmount
|
|
amountFromJson(SField const& name, Json::Value const& v);
|
|
|
|
bool
|
|
amountFromJsonNoThrow(STAmount& result, Json::Value const& jvSource);
|
|
|
|
// IOUAmount and XRPAmount define toSTAmount, defining this
|
|
// trivial conversion here makes writing generic code easier
|
|
inline STAmount const&
|
|
toSTAmount(STAmount const& a)
|
|
{
|
|
return a;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
//
|
|
// Observers
|
|
//
|
|
//------------------------------------------------------------------------------
|
|
|
|
inline int
|
|
STAmount::exponent() const noexcept
|
|
{
|
|
return mOffset;
|
|
}
|
|
|
|
inline bool
|
|
STAmount::native() const noexcept
|
|
{
|
|
return mAsset.native();
|
|
}
|
|
|
|
template <ValidIssueType TIss>
|
|
constexpr bool
|
|
STAmount::holds() const noexcept
|
|
{
|
|
return mAsset.holds<TIss>();
|
|
}
|
|
|
|
inline bool
|
|
STAmount::negative() const noexcept
|
|
{
|
|
return mIsNegative;
|
|
}
|
|
|
|
inline std::uint64_t
|
|
STAmount::mantissa() const noexcept
|
|
{
|
|
return mValue;
|
|
}
|
|
|
|
inline Asset const&
|
|
STAmount::asset() const
|
|
{
|
|
return mAsset;
|
|
}
|
|
|
|
template <ValidIssueType TIss>
|
|
constexpr TIss const&
|
|
STAmount::get() const
|
|
{
|
|
return mAsset.get<TIss>();
|
|
}
|
|
|
|
inline Issue const&
|
|
STAmount::issue() const
|
|
{
|
|
return get<Issue>();
|
|
}
|
|
|
|
inline Currency const&
|
|
STAmount::getCurrency() const
|
|
{
|
|
return mAsset.get<Issue>().currency;
|
|
}
|
|
|
|
inline AccountID const&
|
|
STAmount::getIssuer() const
|
|
{
|
|
return mAsset.getIssuer();
|
|
}
|
|
|
|
inline int
|
|
STAmount::signum() const noexcept
|
|
{
|
|
return mValue ? (mIsNegative ? -1 : 1) : 0;
|
|
}
|
|
|
|
inline STAmount
|
|
STAmount::zeroed() const
|
|
{
|
|
return STAmount(mAsset);
|
|
}
|
|
|
|
inline STAmount::operator bool() const noexcept
|
|
{
|
|
return *this != beast::zero;
|
|
}
|
|
|
|
inline STAmount::operator Number() const
|
|
{
|
|
if (native())
|
|
return xrp();
|
|
if (mAsset.holds<MPTIssue>())
|
|
return mpt();
|
|
return iou();
|
|
}
|
|
|
|
inline STAmount&
|
|
STAmount::operator=(beast::Zero)
|
|
{
|
|
clear();
|
|
return *this;
|
|
}
|
|
|
|
inline STAmount&
|
|
STAmount::operator=(XRPAmount const& amount)
|
|
{
|
|
*this = STAmount(amount);
|
|
return *this;
|
|
}
|
|
|
|
inline STAmount&
|
|
STAmount::operator=(Number const& number)
|
|
{
|
|
mIsNegative = number.mantissa() < 0;
|
|
mValue = mIsNegative ? -number.mantissa() : number.mantissa();
|
|
mOffset = number.exponent();
|
|
canonicalize();
|
|
return *this;
|
|
}
|
|
|
|
inline void
|
|
STAmount::negate()
|
|
{
|
|
if (*this != beast::zero)
|
|
mIsNegative = !mIsNegative;
|
|
}
|
|
|
|
inline void
|
|
STAmount::clear()
|
|
{
|
|
// The -100 is used to allow 0 to sort less than a small positive values
|
|
// which have a negative exponent.
|
|
mOffset = native() ? 0 : -100;
|
|
mValue = 0;
|
|
mIsNegative = false;
|
|
}
|
|
|
|
inline void
|
|
STAmount::clear(Asset const& asset)
|
|
{
|
|
setIssue(asset);
|
|
clear();
|
|
}
|
|
|
|
inline void
|
|
STAmount::setIssuer(AccountID const& uIssuer)
|
|
{
|
|
mAsset.get<Issue>().account = uIssuer;
|
|
}
|
|
|
|
inline STAmount const&
|
|
STAmount::value() const noexcept
|
|
{
|
|
return *this;
|
|
}
|
|
|
|
inline bool
|
|
isLegalNet(STAmount const& value)
|
|
{
|
|
return !value.native() || (value.mantissa() <= STAmount::cMaxNativeN);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
//
|
|
// Operators
|
|
//
|
|
//------------------------------------------------------------------------------
|
|
|
|
bool
|
|
operator==(STAmount const& lhs, STAmount const& rhs);
|
|
bool
|
|
operator<(STAmount const& lhs, STAmount const& rhs);
|
|
|
|
inline bool
|
|
operator!=(STAmount const& lhs, STAmount const& rhs)
|
|
{
|
|
return !(lhs == rhs);
|
|
}
|
|
|
|
inline bool
|
|
operator>(STAmount const& lhs, STAmount const& rhs)
|
|
{
|
|
return rhs < lhs;
|
|
}
|
|
|
|
inline bool
|
|
operator<=(STAmount const& lhs, STAmount const& rhs)
|
|
{
|
|
return !(rhs < lhs);
|
|
}
|
|
|
|
inline bool
|
|
operator>=(STAmount const& lhs, STAmount const& rhs)
|
|
{
|
|
return !(lhs < rhs);
|
|
}
|
|
|
|
STAmount
|
|
operator-(STAmount const& value);
|
|
|
|
//------------------------------------------------------------------------------
|
|
//
|
|
// Arithmetic
|
|
//
|
|
//------------------------------------------------------------------------------
|
|
|
|
STAmount
|
|
operator+(STAmount const& v1, STAmount const& v2);
|
|
STAmount
|
|
operator-(STAmount const& v1, STAmount const& v2);
|
|
|
|
STAmount
|
|
divide(STAmount const& v1, STAmount const& v2, Asset const& asset);
|
|
|
|
STAmount
|
|
multiply(STAmount const& v1, STAmount const& v2, Asset const& asset);
|
|
|
|
// multiply rounding result in specified direction
|
|
STAmount
|
|
mulRound(
|
|
STAmount const& v1,
|
|
STAmount const& v2,
|
|
Asset const& asset,
|
|
bool roundUp);
|
|
|
|
// multiply following the rounding directions more precisely.
|
|
STAmount
|
|
mulRoundStrict(
|
|
STAmount const& v1,
|
|
STAmount const& v2,
|
|
Asset const& asset,
|
|
bool roundUp);
|
|
|
|
// divide rounding result in specified direction
|
|
STAmount
|
|
divRound(
|
|
STAmount const& v1,
|
|
STAmount const& v2,
|
|
Asset const& asset,
|
|
bool roundUp);
|
|
|
|
// divide following the rounding directions more precisely.
|
|
STAmount
|
|
divRoundStrict(
|
|
STAmount const& v1,
|
|
STAmount const& v2,
|
|
Asset const& asset,
|
|
bool roundUp);
|
|
|
|
// Someone is offering X for Y, what is the rate?
|
|
// Rate: smaller is better, the taker wants the most out: in/out
|
|
// VFALCO TODO Return a Quality object
|
|
std::uint64_t
|
|
getRate(STAmount const& offerOut, STAmount const& offerIn);
|
|
|
|
STAmount
|
|
roundToReference(
|
|
STAmount const value,
|
|
STAmount referenceValue,
|
|
Number::rounding_mode rounding = Number::getround());
|
|
|
|
/** Round an arbitrary precision Number to the precision of a given Asset.
|
|
*
|
|
* @param asset The relevant asset
|
|
* @param value The value to be rounded
|
|
* @param referenceValue Only relevant to IOU assets. A reference value to
|
|
* establish the precision limit of `value`. Should be larger than
|
|
* `value`.
|
|
* @param rounding Optional Number rounding mode
|
|
*/
|
|
template <AssetType A>
|
|
Number
|
|
roundToAsset(
|
|
A const& asset,
|
|
Number const& value,
|
|
Number const& referenceValue,
|
|
Number::rounding_mode rounding = Number::getround())
|
|
{
|
|
NumberRoundModeGuard mg(rounding);
|
|
STAmount const ret{asset, value};
|
|
if (ret.asset().native() || !ret.asset().holds<Issue>())
|
|
return ret;
|
|
return roundToReference(ret, STAmount{asset, referenceValue});
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
inline bool
|
|
isXRP(STAmount const& amount)
|
|
{
|
|
return amount.native();
|
|
}
|
|
|
|
// Since `canonicalize` does not have access to a ledger, this is needed to
|
|
// put the low-level routine stAmountCanonicalize on an amendment switch.
|
|
// Only transactions need to use this switchover. Outside of a transaction
|
|
// it's safe to unconditionally use the new behavior.
|
|
|
|
bool
|
|
getSTAmountCanonicalizeSwitchover();
|
|
|
|
void
|
|
setSTAmountCanonicalizeSwitchover(bool v);
|
|
|
|
/** RAII class to set and restore the STAmount canonicalize switchover.
|
|
*/
|
|
|
|
class STAmountSO
|
|
{
|
|
public:
|
|
explicit STAmountSO(bool v) : saved_(getSTAmountCanonicalizeSwitchover())
|
|
{
|
|
setSTAmountCanonicalizeSwitchover(v);
|
|
}
|
|
|
|
~STAmountSO()
|
|
{
|
|
setSTAmountCanonicalizeSwitchover(saved_);
|
|
}
|
|
|
|
private:
|
|
bool saved_;
|
|
};
|
|
|
|
} // namespace ripple
|
|
|
|
//------------------------------------------------------------------------------
|
|
namespace Json {
|
|
template <>
|
|
inline ripple::STAmount
|
|
getOrThrow(Json::Value const& v, ripple::SField const& field)
|
|
{
|
|
using namespace ripple;
|
|
Json::StaticString const& key = field.getJsonName();
|
|
if (!v.isMember(key))
|
|
Throw<JsonMissingKeyError>(key);
|
|
Json::Value const& inner = v[key];
|
|
return amountFromJson(field, inner);
|
|
}
|
|
} // namespace Json
|
|
#endif
|