mirror of
https://github.com/XRPLF/rippled.git
synced 2026-06-03 16:56:48 +00:00
Merge branch 'ripple/wasmi-host-functions' of https://github.com/XRPLF/rippled into ripple/se/fees
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
|
||||
#include <xrpl/basics/Number.h>
|
||||
#include <xrpl/protocol/AccountID.h>
|
||||
#include <xrpl/protocol/Issue.h>
|
||||
#include <xrpl/protocol/Asset.h>
|
||||
#include <xrpl/protocol/TER.h>
|
||||
#include <xrpl/protocol/UintTypes.h>
|
||||
|
||||
@@ -31,12 +31,12 @@ class Rules;
|
||||
/** Calculate Liquidity Provider Token (LPT) Currency.
|
||||
*/
|
||||
Currency
|
||||
ammLPTCurrency(Currency const& cur1, Currency const& cur2);
|
||||
ammLPTCurrency(Asset const& asset1, Asset const& asset2);
|
||||
|
||||
/** Calculate LPT Issue from AMM asset pair.
|
||||
*/
|
||||
Issue
|
||||
ammLPTIssue(Currency const& cur1, Currency const& cur2, AccountID const& ammAccountID);
|
||||
ammLPTIssue(Asset const& asset1, Asset const& asset2, AccountID const& ammAccountID);
|
||||
|
||||
/** Validate the amount.
|
||||
* If validZero is false and amount is beast::zero then invalid amount.
|
||||
@@ -46,19 +46,19 @@ ammLPTIssue(Currency const& cur1, Currency const& cur2, AccountID const& ammAcco
|
||||
NotTEC
|
||||
invalidAMMAmount(
|
||||
STAmount const& amount,
|
||||
std::optional<std::pair<Issue, Issue>> const& pair = std::nullopt,
|
||||
std::optional<std::pair<Asset, Asset>> const& pair = std::nullopt,
|
||||
bool validZero = false);
|
||||
|
||||
NotTEC
|
||||
invalidAMMAsset(
|
||||
Issue const& issue,
|
||||
std::optional<std::pair<Issue, Issue>> const& pair = std::nullopt);
|
||||
Asset const& asset,
|
||||
std::optional<std::pair<Asset, Asset>> const& pair = std::nullopt);
|
||||
|
||||
NotTEC
|
||||
invalidAMMAssetPair(
|
||||
Issue const& issue1,
|
||||
Issue const& issue2,
|
||||
std::optional<std::pair<Issue, Issue>> const& pair = std::nullopt);
|
||||
Asset const& asset1,
|
||||
Asset const& asset2,
|
||||
std::optional<std::pair<Asset, Asset>> const& pair = std::nullopt);
|
||||
|
||||
/** Get time slot of the auction slot.
|
||||
*/
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpl/protocol/IOUAmount.h>
|
||||
#include <xrpl/protocol/Protocol.h>
|
||||
#include <xrpl/protocol/STAmount.h>
|
||||
#include <xrpl/protocol/XRPAmount.h>
|
||||
|
||||
@@ -9,11 +10,12 @@
|
||||
namespace xrpl {
|
||||
|
||||
inline STAmount
|
||||
toSTAmount(IOUAmount const& iou, Issue const& iss)
|
||||
toSTAmount(IOUAmount const& iou, Asset const& asset)
|
||||
{
|
||||
XRPL_ASSERT(asset.holds<Issue>(), "xrpl::toSTAmount : is Issue");
|
||||
bool const isNeg = iou.signum() < 0;
|
||||
std::uint64_t const umant = isNeg ? -iou.mantissa() : iou.mantissa();
|
||||
return STAmount(iss, umant, iou.exponent(), isNeg, STAmount::unchecked());
|
||||
return STAmount(asset, umant, iou.exponent(), isNeg, STAmount::unchecked());
|
||||
}
|
||||
|
||||
inline STAmount
|
||||
@@ -31,12 +33,25 @@ toSTAmount(XRPAmount const& xrp)
|
||||
}
|
||||
|
||||
inline STAmount
|
||||
toSTAmount(XRPAmount const& xrp, Issue const& iss)
|
||||
toSTAmount(XRPAmount const& xrp, Asset const& asset)
|
||||
{
|
||||
XRPL_ASSERT(isXRP(iss.account) && isXRP(iss.currency), "xrpl::toSTAmount : is XRP");
|
||||
XRPL_ASSERT(isXRP(asset), "xrpl::toSTAmount : is XRP");
|
||||
return toSTAmount(xrp);
|
||||
}
|
||||
|
||||
inline STAmount
|
||||
toSTAmount(MPTAmount const& mpt)
|
||||
{
|
||||
return STAmount(mpt, noMPT());
|
||||
}
|
||||
|
||||
inline STAmount
|
||||
toSTAmount(MPTAmount const& mpt, Asset const& asset)
|
||||
{
|
||||
XRPL_ASSERT(asset.holds<MPTIssue>(), "xrpl::toSTAmount : is MPT");
|
||||
return STAmount(mpt, asset.get<MPTIssue>());
|
||||
}
|
||||
|
||||
template <class T>
|
||||
T
|
||||
toAmount(STAmount const& amt) = delete;
|
||||
@@ -76,6 +91,21 @@ toAmount<XRPAmount>(STAmount const& amt)
|
||||
return XRPAmount(sMant);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline MPTAmount
|
||||
toAmount<MPTAmount>(STAmount const& amt)
|
||||
{
|
||||
XRPL_ASSERT(
|
||||
amt.holds<MPTIssue>() && amt.mantissa() <= maxMPTokenAmount && amt.exponent() == 0,
|
||||
"xrpl::toAmount<MPTAmount> : maximum mantissa");
|
||||
if (amt.mantissa() > maxMPTokenAmount || amt.exponent() != 0)
|
||||
Throw<std::runtime_error>("toAmount<MPTAmount>: invalid mantissa or exponent");
|
||||
bool const isNeg = amt.negative();
|
||||
std::int64_t const sMant = isNeg ? -std::int64_t(amt.mantissa()) : amt.mantissa();
|
||||
|
||||
return MPTAmount(sMant);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
T
|
||||
toAmount(IOUAmount const& amt) = delete;
|
||||
@@ -98,23 +128,36 @@ toAmount<XRPAmount>(XRPAmount const& amt)
|
||||
return amt;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
T
|
||||
toAmount(MPTAmount const& amt) = delete;
|
||||
|
||||
template <>
|
||||
inline MPTAmount
|
||||
toAmount<MPTAmount>(MPTAmount const& amt)
|
||||
{
|
||||
return amt;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T
|
||||
toAmount(Issue const& issue, Number const& n, Number::rounding_mode mode = Number::getround())
|
||||
toAmount(Asset const& asset, Number const& n, Number::rounding_mode mode = Number::getround())
|
||||
{
|
||||
saveNumberRoundMode const rm(Number::getround());
|
||||
if (isXRP(issue))
|
||||
if (isXRP(asset))
|
||||
Number::setround(mode);
|
||||
|
||||
if constexpr (std::is_same_v<IOUAmount, T>)
|
||||
return IOUAmount(n);
|
||||
else if constexpr (std::is_same_v<XRPAmount, T>)
|
||||
return XRPAmount(static_cast<std::int64_t>(n));
|
||||
else if constexpr (std::is_same_v<MPTAmount, T>)
|
||||
return MPTAmount(static_cast<std::int64_t>(n));
|
||||
else if constexpr (std::is_same_v<STAmount, T>)
|
||||
{
|
||||
if (isXRP(issue))
|
||||
return STAmount(issue, static_cast<std::int64_t>(n));
|
||||
return STAmount(issue, n);
|
||||
if (isXRP(asset))
|
||||
return STAmount(asset, static_cast<std::int64_t>(n));
|
||||
return STAmount(asset, n);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -125,17 +168,23 @@ toAmount(Issue const& issue, Number const& n, Number::rounding_mode mode = Numbe
|
||||
|
||||
template <typename T>
|
||||
T
|
||||
toMaxAmount(Issue const& issue)
|
||||
toMaxAmount(Asset const& asset)
|
||||
{
|
||||
if constexpr (std::is_same_v<IOUAmount, T>)
|
||||
return IOUAmount(STAmount::cMaxValue, STAmount::cMaxOffset);
|
||||
else if constexpr (std::is_same_v<XRPAmount, T>)
|
||||
return XRPAmount(static_cast<std::int64_t>(STAmount::cMaxNativeN));
|
||||
else if constexpr (std::is_same_v<MPTAmount, T>)
|
||||
return MPTAmount(maxMPTokenAmount);
|
||||
else if constexpr (std::is_same_v<STAmount, T>)
|
||||
{
|
||||
if (isXRP(issue))
|
||||
return STAmount(issue, static_cast<std::int64_t>(STAmount::cMaxNativeN));
|
||||
return STAmount(issue, STAmount::cMaxValue, STAmount::cMaxOffset);
|
||||
return asset.visit(
|
||||
[](Issue const& issue) {
|
||||
if (isXRP(issue))
|
||||
return STAmount(issue, static_cast<std::int64_t>(STAmount::cMaxNativeN));
|
||||
return STAmount(issue, STAmount::cMaxValue, STAmount::cMaxOffset);
|
||||
},
|
||||
[](MPTIssue const& issue) { return STAmount(issue, maxMPTokenAmount); });
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -145,21 +194,23 @@ toMaxAmount(Issue const& issue)
|
||||
}
|
||||
|
||||
inline STAmount
|
||||
toSTAmount(Issue const& issue, Number const& n, Number::rounding_mode mode = Number::getround())
|
||||
toSTAmount(Asset const& asset, Number const& n, Number::rounding_mode mode = Number::getround())
|
||||
{
|
||||
return toAmount<STAmount>(issue, n, mode);
|
||||
return toAmount<STAmount>(asset, n, mode);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
Issue
|
||||
getIssue(T const& amt)
|
||||
Asset
|
||||
getAsset(T const& amt)
|
||||
{
|
||||
if constexpr (std::is_same_v<IOUAmount, T>)
|
||||
return noIssue();
|
||||
else if constexpr (std::is_same_v<XRPAmount, T>)
|
||||
return xrpIssue();
|
||||
else if constexpr (std::is_same_v<MPTAmount, T>)
|
||||
return noMPT();
|
||||
else if constexpr (std::is_same_v<STAmount, T>)
|
||||
return amt.issue();
|
||||
return amt.asset();
|
||||
else
|
||||
{
|
||||
constexpr bool alwaysFalse = !std::is_same_v<T, T>;
|
||||
@@ -175,6 +226,8 @@ get(STAmount const& a)
|
||||
return a.iou();
|
||||
else if constexpr (std::is_same_v<XRPAmount, T>)
|
||||
return a.xrp();
|
||||
else if constexpr (std::is_same_v<MPTAmount, T>)
|
||||
return a.mpt();
|
||||
else if constexpr (std::is_same_v<STAmount, T>)
|
||||
return a;
|
||||
else
|
||||
|
||||
@@ -2,20 +2,37 @@
|
||||
|
||||
#include <xrpl/basics/Number.h>
|
||||
#include <xrpl/basics/base_uint.h>
|
||||
#include <xrpl/protocol/Concepts.h>
|
||||
#include <xrpl/protocol/Issue.h>
|
||||
#include <xrpl/protocol/MPTIssue.h>
|
||||
#include <xrpl/protocol/Rules.h>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
class Asset;
|
||||
class STAmount;
|
||||
|
||||
template <typename TIss>
|
||||
concept ValidIssueType = std::is_same_v<TIss, Issue> || std::is_same_v<TIss, MPTIssue>;
|
||||
template <typename T>
|
||||
requires(
|
||||
std::is_same_v<T, XRPAmount> || std::is_same_v<T, IOUAmount> ||
|
||||
std::is_same_v<T, MPTAmount>)
|
||||
struct AmountType
|
||||
{
|
||||
using amount_type = T;
|
||||
};
|
||||
|
||||
template <typename A>
|
||||
concept AssetType = std::is_convertible_v<A, Asset> || std::is_convertible_v<A, Issue> ||
|
||||
std::is_convertible_v<A, MPTIssue> || std::is_convertible_v<A, MPTID>;
|
||||
/* Used to check for an asset with either badCurrency()
|
||||
* or MPT with 0 account.
|
||||
*/
|
||||
struct BadAsset
|
||||
{
|
||||
};
|
||||
|
||||
inline BadAsset const&
|
||||
badAsset()
|
||||
{
|
||||
static BadAsset const a;
|
||||
return a;
|
||||
}
|
||||
|
||||
/* Asset is an abstraction of three different issue types: XRP, IOU, MPT.
|
||||
* For historical reasons, two issue types XRP and IOU are wrapped in Issue
|
||||
@@ -26,6 +43,9 @@ class Asset
|
||||
{
|
||||
public:
|
||||
using value_type = std::variant<Issue, MPTIssue>;
|
||||
using token_type = std::variant<Currency, MPTID>;
|
||||
using AmtType =
|
||||
std::variant<AmountType<XRPAmount>, AmountType<IOUAmount>, AmountType<MPTAmount>>;
|
||||
|
||||
private:
|
||||
value_type issue_;
|
||||
@@ -69,36 +89,42 @@ public:
|
||||
constexpr value_type const&
|
||||
value() const;
|
||||
|
||||
constexpr token_type
|
||||
token() const;
|
||||
|
||||
void
|
||||
setJson(Json::Value& jv) const;
|
||||
|
||||
STAmount
|
||||
operator()(Number const&) const;
|
||||
|
||||
bool
|
||||
constexpr AmtType
|
||||
getAmountType() const;
|
||||
|
||||
// Custom, generic visit implementation
|
||||
template <typename... Visitors>
|
||||
constexpr auto
|
||||
visit(Visitors&&... visitors) const -> decltype(auto)
|
||||
{
|
||||
// Simple delegation to the reusable utility, passing the internal
|
||||
// variant data.
|
||||
return detail::visit(issue_, std::forward<Visitors>(visitors)...);
|
||||
}
|
||||
|
||||
constexpr bool
|
||||
native() const
|
||||
{
|
||||
return std::visit(
|
||||
[&]<ValidIssueType TIss>(TIss const& issue) {
|
||||
if constexpr (std::is_same_v<TIss, Issue>)
|
||||
return issue.native();
|
||||
if constexpr (std::is_same_v<TIss, MPTIssue>)
|
||||
return false;
|
||||
},
|
||||
issue_);
|
||||
return visit(
|
||||
[&](Issue const& issue) { return issue.native(); },
|
||||
[&](MPTIssue const&) { return false; });
|
||||
}
|
||||
|
||||
bool
|
||||
integral() const
|
||||
{
|
||||
return std::visit(
|
||||
[&]<ValidIssueType TIss>(TIss const& issue) {
|
||||
if constexpr (std::is_same_v<TIss, Issue>)
|
||||
return issue.native();
|
||||
if constexpr (std::is_same_v<TIss, MPTIssue>)
|
||||
return true;
|
||||
},
|
||||
issue_);
|
||||
return visit(
|
||||
[&](Issue const& issue) { return issue.native(); },
|
||||
[&](MPTIssue const&) { return true; });
|
||||
}
|
||||
|
||||
friend constexpr bool
|
||||
@@ -110,6 +136,10 @@ public:
|
||||
friend constexpr bool
|
||||
operator==(Currency const& lhs, Asset const& rhs);
|
||||
|
||||
// rhs is either badCurrency() or MPT issuer is 0
|
||||
friend constexpr bool
|
||||
operator==(BadAsset const& lhs, Asset const& rhs);
|
||||
|
||||
/** Return true if both assets refer to the same currency (regardless of
|
||||
* issuer) or MPT issuance. Otherwise return false.
|
||||
*/
|
||||
@@ -117,6 +147,12 @@ public:
|
||||
equalTokens(Asset const& lhs, Asset const& rhs);
|
||||
};
|
||||
|
||||
template <ValidIssueType TIss>
|
||||
constexpr bool is_issue_v = std::is_same_v<TIss, Issue>;
|
||||
|
||||
template <ValidIssueType TIss>
|
||||
constexpr bool is_mptissue_v = std::is_same_v<TIss, MPTIssue>;
|
||||
|
||||
inline Json::Value
|
||||
to_json(Asset const& asset)
|
||||
{
|
||||
@@ -156,6 +192,29 @@ Asset::value() const
|
||||
return issue_;
|
||||
}
|
||||
|
||||
constexpr Asset::token_type
|
||||
Asset::token() const
|
||||
{
|
||||
return visit(
|
||||
[&](Issue const& issue) -> Asset::token_type { return issue.currency; },
|
||||
[&](MPTIssue const& issue) -> Asset::token_type { return issue.getMptID(); });
|
||||
}
|
||||
|
||||
constexpr Asset::AmtType
|
||||
Asset::getAmountType() const
|
||||
{
|
||||
return visit(
|
||||
[&](Issue const& issue) -> Asset::AmtType {
|
||||
constexpr AmountType<XRPAmount> xrp;
|
||||
constexpr AmountType<IOUAmount> iou;
|
||||
return native() ? AmtType(xrp) : AmtType(iou);
|
||||
},
|
||||
[&](MPTIssue const& issue) -> Asset::AmtType {
|
||||
constexpr AmountType<MPTAmount> mpt;
|
||||
return AmtType(mpt);
|
||||
});
|
||||
}
|
||||
|
||||
constexpr bool
|
||||
operator==(Asset const& lhs, Asset const& rhs)
|
||||
{
|
||||
@@ -177,7 +236,7 @@ operator<=>(Asset const& lhs, Asset const& rhs)
|
||||
[]<ValidIssueType TLhs, ValidIssueType TRhs>(TLhs const& lhs_, TRhs const& rhs_) {
|
||||
if constexpr (std::is_same_v<TLhs, TRhs>)
|
||||
return std::weak_ordering(lhs_ <=> rhs_);
|
||||
else if constexpr (std::is_same_v<TLhs, Issue> && std::is_same_v<TRhs, MPTIssue>)
|
||||
else if constexpr (is_issue_v<TLhs> && is_mptissue_v<TRhs>)
|
||||
return std::weak_ordering::greater;
|
||||
else
|
||||
return std::weak_ordering::less;
|
||||
@@ -189,7 +248,17 @@ operator<=>(Asset const& lhs, Asset const& rhs)
|
||||
constexpr bool
|
||||
operator==(Currency const& lhs, Asset const& rhs)
|
||||
{
|
||||
return rhs.holds<Issue>() && rhs.get<Issue>().currency == lhs;
|
||||
return rhs.visit(
|
||||
[&](Issue const& issue) { return issue.currency == lhs; },
|
||||
[](MPTIssue const& issue) { return false; });
|
||||
}
|
||||
|
||||
constexpr bool
|
||||
operator==(BadAsset const&, Asset const& rhs)
|
||||
{
|
||||
return rhs.visit(
|
||||
[](Issue const& issue) -> bool { return badCurrency() == issue.currency; },
|
||||
[](MPTIssue const& issue) -> bool { return issue.getIssuer() == xrpAccount(); });
|
||||
}
|
||||
|
||||
constexpr bool
|
||||
@@ -223,4 +292,36 @@ validJSONAsset(Json::Value const& jv);
|
||||
Asset
|
||||
assetFromJson(Json::Value const& jv);
|
||||
|
||||
Json::Value
|
||||
to_json(Asset const& asset);
|
||||
|
||||
inline bool
|
||||
isConsistent(Asset const& asset)
|
||||
{
|
||||
return asset.visit(
|
||||
[](Issue const& issue) { return isConsistent(issue); },
|
||||
[](MPTIssue const&) { return true; });
|
||||
}
|
||||
|
||||
inline bool
|
||||
validAsset(Asset const& asset)
|
||||
{
|
||||
return asset.visit(
|
||||
[](Issue const& issue) { return isConsistent(issue) && issue.currency != badCurrency(); },
|
||||
[](MPTIssue const& issue) { return issue.getIssuer() != xrpAccount(); });
|
||||
}
|
||||
|
||||
template <class Hasher>
|
||||
void
|
||||
hash_append(Hasher& h, Asset const& r)
|
||||
{
|
||||
using beast::hash_append;
|
||||
r.visit(
|
||||
[&](Issue const& issue) { hash_append(h, issue); },
|
||||
[&](MPTIssue const& issue) { hash_append(h, issue); });
|
||||
}
|
||||
|
||||
std::ostream&
|
||||
operator<<(std::ostream& os, Asset const& x);
|
||||
|
||||
} // namespace xrpl
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
#include <xrpl/basics/CountedObject.h>
|
||||
#include <xrpl/basics/base_uint.h>
|
||||
#include <xrpl/protocol/Issue.h>
|
||||
#include <xrpl/protocol/Asset.h>
|
||||
|
||||
#include <boost/utility/base_from_member.hpp>
|
||||
|
||||
@@ -15,15 +15,15 @@ namespace xrpl {
|
||||
class Book final : public CountedObject<Book>
|
||||
{
|
||||
public:
|
||||
Issue in;
|
||||
Issue out;
|
||||
Asset in;
|
||||
Asset out;
|
||||
std::optional<uint256> domain;
|
||||
|
||||
Book()
|
||||
{
|
||||
}
|
||||
|
||||
Book(Issue const& in_, Issue const& out_, std::optional<uint256> const& domain_)
|
||||
Book(Asset const& in_, Asset const& out_, std::optional<uint256> const& domain_)
|
||||
: in(in_), out(out_), domain(domain_)
|
||||
{
|
||||
}
|
||||
@@ -112,16 +112,67 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct hash<xrpl::MPTIssue> : private boost::base_from_member<std::hash<xrpl::MPTID>, 0>
|
||||
{
|
||||
private:
|
||||
using id_hash_type = boost::base_from_member<std::hash<xrpl::MPTID>, 0>;
|
||||
|
||||
public:
|
||||
explicit hash() = default;
|
||||
|
||||
using value_type = std::size_t;
|
||||
using argument_type = xrpl::MPTIssue;
|
||||
|
||||
value_type
|
||||
operator()(argument_type const& value) const
|
||||
{
|
||||
value_type const result(id_hash_type::member(value.getMptID()));
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct hash<xrpl::Asset>
|
||||
{
|
||||
private:
|
||||
using value_type = std::size_t;
|
||||
using argument_type = xrpl::Asset;
|
||||
|
||||
using issue_hasher = std::hash<xrpl::Issue>;
|
||||
using mptissue_hasher = std::hash<xrpl::MPTIssue>;
|
||||
|
||||
issue_hasher m_issue_hasher;
|
||||
mptissue_hasher m_mptissue_hasher;
|
||||
|
||||
public:
|
||||
explicit hash() = default;
|
||||
|
||||
value_type
|
||||
operator()(argument_type const& asset) const
|
||||
{
|
||||
return asset.visit(
|
||||
[&](xrpl::Issue const& issue) {
|
||||
value_type const result(m_issue_hasher(issue));
|
||||
return result;
|
||||
},
|
||||
[&](xrpl::MPTIssue const& issue) {
|
||||
value_type const result(m_mptissue_hasher(issue));
|
||||
return result;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template <>
|
||||
struct hash<xrpl::Book>
|
||||
{
|
||||
private:
|
||||
using issue_hasher = std::hash<xrpl::Issue>;
|
||||
using asset_hasher = std::hash<xrpl::Asset>;
|
||||
using uint256_hasher = xrpl::uint256::hasher;
|
||||
|
||||
issue_hasher m_issue_hasher;
|
||||
asset_hasher m_asset_hasher;
|
||||
uint256_hasher m_uint256_hasher;
|
||||
|
||||
public:
|
||||
@@ -133,8 +184,8 @@ public:
|
||||
value_type
|
||||
operator()(argument_type const& value) const
|
||||
{
|
||||
value_type result(m_issue_hasher(value.in));
|
||||
boost::hash_combine(result, m_issue_hasher(value.out));
|
||||
value_type result(m_asset_hasher(value.in));
|
||||
boost::hash_combine(result, m_asset_hasher(value.out));
|
||||
|
||||
if (value.domain)
|
||||
boost::hash_combine(result, m_uint256_hasher(*value.domain));
|
||||
@@ -159,6 +210,22 @@ struct hash<xrpl::Issue> : std::hash<xrpl::Issue>
|
||||
// using Base::Base; // inherit ctors
|
||||
};
|
||||
|
||||
template <>
|
||||
struct hash<xrpl::MPTIssue> : std::hash<xrpl::MPTIssue>
|
||||
{
|
||||
explicit hash() = default;
|
||||
|
||||
using Base = std::hash<xrpl::MPTIssue>;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct hash<xrpl::Asset> : std::hash<xrpl::Asset>
|
||||
{
|
||||
explicit hash() = default;
|
||||
|
||||
using Base = std::hash<xrpl::Asset>;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct hash<xrpl::Book> : std::hash<xrpl::Book>
|
||||
{
|
||||
|
||||
86
include/xrpl/protocol/Concepts.h
Normal file
86
include/xrpl/protocol/Concepts.h
Normal file
@@ -0,0 +1,86 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpl/protocol/UintTypes.h>
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
class STAmount;
|
||||
class Asset;
|
||||
class Issue;
|
||||
class MPTIssue;
|
||||
class IOUAmount;
|
||||
class XRPAmount;
|
||||
class MPTAmount;
|
||||
|
||||
template <typename A>
|
||||
concept StepAmount =
|
||||
std::is_same_v<A, XRPAmount> || std::is_same_v<A, IOUAmount> || std::is_same_v<A, MPTAmount>;
|
||||
|
||||
template <typename TIss>
|
||||
concept ValidIssueType = std::is_same_v<TIss, Issue> || std::is_same_v<TIss, MPTIssue>;
|
||||
|
||||
template <typename A>
|
||||
concept AssetType = std::is_convertible_v<A, Asset> || std::is_convertible_v<A, Issue> ||
|
||||
std::is_convertible_v<A, MPTIssue> || std::is_convertible_v<A, MPTID>;
|
||||
|
||||
template <typename T>
|
||||
concept ValidPathAsset = (std::is_same_v<T, Currency> || std::is_same_v<T, MPTID>);
|
||||
|
||||
template <class TTakerPays, class TTakerGets>
|
||||
concept ValidTaker =
|
||||
((std::is_same_v<TTakerPays, IOUAmount> || std::is_same_v<TTakerPays, XRPAmount> ||
|
||||
std::is_same_v<TTakerPays, MPTAmount>) &&
|
||||
(std::is_same_v<TTakerGets, IOUAmount> || std::is_same_v<TTakerGets, XRPAmount> ||
|
||||
std::is_same_v<TTakerGets, MPTAmount>) &&
|
||||
(!std::is_same_v<TTakerPays, XRPAmount> || !std::is_same_v<TTakerGets, XRPAmount>));
|
||||
|
||||
namespace detail {
|
||||
|
||||
// This template combines multiple callable objects (lambdas) into a single
|
||||
// object that std::visit can use for overload resolution.
|
||||
template <typename... Ts>
|
||||
struct CombineVisitors : Ts...
|
||||
{
|
||||
// Bring all operator() overloads from base classes into this scope.
|
||||
// It's the mechanism that makes the CombineVisitors struct function
|
||||
// as a single callable object with multiple overloads.
|
||||
using Ts::operator()...;
|
||||
|
||||
// Perfect forwarding constructor to correctly initialize the base class
|
||||
// lambdas
|
||||
constexpr CombineVisitors(Ts&&... ts) : Ts(std::forward<Ts>(ts))...
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
// This function forces function template argument deduction, which is more
|
||||
// robust than class template argument deduction (CTAD) via the deduction guide.
|
||||
template <typename... Ts>
|
||||
constexpr CombineVisitors<std::decay_t<Ts>...>
|
||||
make_combine_visitors(Ts&&... ts)
|
||||
{
|
||||
// std::decay_t<Ts> is used to remove references/constness from the lambda
|
||||
// types before they are passed as template arguments to the CombineVisitors
|
||||
// struct.
|
||||
return CombineVisitors<std::decay_t<Ts>...>{std::forward<Ts>(ts)...};
|
||||
}
|
||||
|
||||
// This function takes ANY variant and ANY number of visitors, and performs the
|
||||
// visit. It is the reusable core logic.
|
||||
template <typename Variant, typename... Visitors>
|
||||
constexpr auto
|
||||
visit(Variant&& v, Visitors&&... visitors) -> decltype(auto)
|
||||
{
|
||||
// Use the function template helper instead of raw CTAD.
|
||||
auto visitor_set = make_combine_visitors(std::forward<Visitors>(visitors)...);
|
||||
|
||||
// Delegate to std::visit, perfectly forwarding the variant and the visitor
|
||||
// set.
|
||||
return std::visit(visitor_set, std::forward<Variant>(v));
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace xrpl
|
||||
@@ -187,7 +187,8 @@ enum LedgerEntryType : std::uint16_t {
|
||||
\
|
||||
LEDGER_OBJECT(MPToken, \
|
||||
LSF_FLAG2(lsfMPTLocked, 0x00000001) \
|
||||
LSF_FLAG(lsfMPTAuthorized, 0x00000002)) \
|
||||
LSF_FLAG(lsfMPTAuthorized, 0x00000002) \
|
||||
LSF_FLAG(lsfMPTAMM, 0x00000004)) \
|
||||
\
|
||||
LEDGER_OBJECT(Credential, \
|
||||
LSF_FLAG(lsfAccepted, 0x00010000)) \
|
||||
|
||||
@@ -22,11 +22,12 @@ public:
|
||||
using value_type = std::int64_t;
|
||||
|
||||
protected:
|
||||
value_type value_;
|
||||
value_type value_{};
|
||||
|
||||
public:
|
||||
MPTAmount() = default;
|
||||
constexpr MPTAmount(MPTAmount const& other) = default;
|
||||
constexpr MPTAmount(beast::Zero);
|
||||
constexpr MPTAmount&
|
||||
operator=(MPTAmount const& other) = default;
|
||||
|
||||
@@ -85,6 +86,11 @@ constexpr MPTAmount::MPTAmount(value_type value) : value_(value)
|
||||
{
|
||||
}
|
||||
|
||||
constexpr MPTAmount::MPTAmount(beast::Zero)
|
||||
{
|
||||
*this = beast::zero;
|
||||
}
|
||||
|
||||
constexpr MPTAmount&
|
||||
MPTAmount::operator=(beast::Zero)
|
||||
{
|
||||
@@ -116,6 +122,14 @@ MPTAmount::value() const
|
||||
return value_;
|
||||
}
|
||||
|
||||
// Output MPTAmount as just the value.
|
||||
template <class Char, class Traits>
|
||||
std::basic_ostream<Char, Traits>&
|
||||
operator<<(std::basic_ostream<Char, Traits>& os, MPTAmount const& q)
|
||||
{
|
||||
return os << q.value();
|
||||
}
|
||||
|
||||
inline std::string
|
||||
to_string(MPTAmount const& amount)
|
||||
{
|
||||
|
||||
@@ -17,7 +17,14 @@ private:
|
||||
public:
|
||||
MPTIssue() = default;
|
||||
|
||||
explicit MPTIssue(MPTID const& issuanceID);
|
||||
MPTIssue(MPTID const& issuanceID);
|
||||
|
||||
MPTIssue(std::uint32_t sequence, AccountID const& account);
|
||||
|
||||
operator MPTID const&() const
|
||||
{
|
||||
return mptID_;
|
||||
}
|
||||
|
||||
AccountID const&
|
||||
getIssuer() const;
|
||||
@@ -73,6 +80,47 @@ isXRP(MPTID const&)
|
||||
return false;
|
||||
}
|
||||
|
||||
inline AccountID
|
||||
getMPTIssuer(MPTID const& mptid)
|
||||
{
|
||||
static_assert(sizeof(MPTID) == (sizeof(std::uint32_t) + sizeof(AccountID)));
|
||||
// Extract the 20 bytes for the AccountID
|
||||
std::array<std::uint8_t, sizeof(AccountID)> bytes{};
|
||||
std::copy_n(mptid.data() + sizeof(std::uint32_t), sizeof(AccountID), bytes.begin());
|
||||
|
||||
// bit_cast is a "magic" compiler intrinsic that is
|
||||
// usually optimized away to nothing in the final assembly.
|
||||
return std::bit_cast<AccountID>(bytes);
|
||||
}
|
||||
|
||||
// Disallow temporary
|
||||
inline AccountID const&
|
||||
getMPTIssuer(MPTID const&&) = delete;
|
||||
inline AccountID const&
|
||||
getMPTIssuer(MPTID&&) = delete;
|
||||
|
||||
inline MPTID
|
||||
noMPT()
|
||||
{
|
||||
static MPTIssue const mpt{0, noAccount()};
|
||||
return mpt.getMptID();
|
||||
}
|
||||
|
||||
inline MPTID
|
||||
badMPT()
|
||||
{
|
||||
static MPTIssue const mpt{0, xrpAccount()};
|
||||
return mpt.getMptID();
|
||||
}
|
||||
|
||||
template <class Hasher>
|
||||
void
|
||||
hash_append(Hasher& h, MPTIssue const& r)
|
||||
{
|
||||
using beast::hash_append;
|
||||
hash_append(h, r.getMptID());
|
||||
}
|
||||
|
||||
Json::Value
|
||||
to_json(MPTIssue const& mptIssue);
|
||||
|
||||
@@ -82,4 +130,17 @@ to_string(MPTIssue const& mptIssue);
|
||||
MPTIssue
|
||||
mptIssueFromJson(Json::Value const& jv);
|
||||
|
||||
std::ostream&
|
||||
operator<<(std::ostream& os, MPTIssue const& x);
|
||||
|
||||
} // namespace xrpl
|
||||
|
||||
namespace std {
|
||||
|
||||
template <>
|
||||
struct hash<xrpl::MPTID> : xrpl::MPTID::hasher
|
||||
{
|
||||
explicit hash() = default;
|
||||
};
|
||||
|
||||
} // namespace std
|
||||
|
||||
130
include/xrpl/protocol/PathAsset.h
Normal file
130
include/xrpl/protocol/PathAsset.h
Normal file
@@ -0,0 +1,130 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpl/protocol/Asset.h>
|
||||
#include <xrpl/protocol/Concepts.h>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
/* Represent STPathElement's asset, which can be Currency or MPTID.
|
||||
*/
|
||||
class PathAsset
|
||||
{
|
||||
private:
|
||||
std::variant<Currency, MPTID> easset_;
|
||||
|
||||
public:
|
||||
PathAsset() = default;
|
||||
// Enables comparing Asset and PathAsset
|
||||
PathAsset(Asset const& asset);
|
||||
PathAsset(Currency const& currency) : easset_(currency)
|
||||
{
|
||||
}
|
||||
PathAsset(MPTID const& mpt) : easset_(mpt)
|
||||
{
|
||||
}
|
||||
|
||||
template <ValidPathAsset T>
|
||||
constexpr bool
|
||||
holds() const;
|
||||
|
||||
constexpr bool
|
||||
isXRP() const;
|
||||
|
||||
template <ValidPathAsset T>
|
||||
T const&
|
||||
get() const;
|
||||
|
||||
constexpr std::variant<Currency, MPTID> const&
|
||||
value() const;
|
||||
|
||||
// Custom, generic visit implementation
|
||||
template <typename... Visitors>
|
||||
constexpr auto
|
||||
visit(Visitors&&... visitors) const -> decltype(auto)
|
||||
{
|
||||
// Simple delegation to the reusable utility, passing the internal
|
||||
// variant data.
|
||||
return detail::visit(easset_, std::forward<Visitors>(visitors)...);
|
||||
}
|
||||
|
||||
friend constexpr bool
|
||||
operator==(PathAsset const& lhs, PathAsset const& rhs);
|
||||
};
|
||||
|
||||
template <ValidPathAsset PA>
|
||||
constexpr bool is_currency_v = std::is_same_v<PA, Currency>;
|
||||
|
||||
template <ValidPathAsset PA>
|
||||
constexpr bool is_mptid_v = std::is_same_v<PA, MPTID>;
|
||||
|
||||
inline PathAsset::PathAsset(Asset const& asset)
|
||||
{
|
||||
asset.visit(
|
||||
[&](Issue const& issue) { easset_ = issue.currency; },
|
||||
[&](MPTIssue const& issue) { easset_ = issue.getMptID(); });
|
||||
}
|
||||
|
||||
template <ValidPathAsset T>
|
||||
constexpr bool
|
||||
PathAsset::holds() const
|
||||
{
|
||||
return std::holds_alternative<T>(easset_);
|
||||
}
|
||||
|
||||
template <ValidPathAsset T>
|
||||
T const&
|
||||
PathAsset::get() const
|
||||
{
|
||||
if (!holds<T>())
|
||||
Throw<std::runtime_error>("PathAsset doesn't hold requested asset.");
|
||||
return std::get<T>(easset_);
|
||||
}
|
||||
|
||||
constexpr std::variant<Currency, MPTID> const&
|
||||
PathAsset::value() const
|
||||
{
|
||||
return easset_;
|
||||
}
|
||||
|
||||
constexpr bool
|
||||
PathAsset::isXRP() const
|
||||
{
|
||||
return visit(
|
||||
[&](Currency const& currency) { return xrpl::isXRP(currency); },
|
||||
[](MPTID const&) { return false; });
|
||||
}
|
||||
|
||||
constexpr bool
|
||||
operator==(PathAsset const& lhs, PathAsset const& rhs)
|
||||
{
|
||||
return std::visit(
|
||||
[]<ValidPathAsset TLhs, ValidPathAsset TRhs>(TLhs const& lhs_, TRhs const& rhs_) {
|
||||
if constexpr (std::is_same_v<TLhs, TRhs>)
|
||||
return lhs_ == rhs_;
|
||||
else
|
||||
return false;
|
||||
},
|
||||
lhs.value(),
|
||||
rhs.value());
|
||||
}
|
||||
|
||||
template <typename Hasher>
|
||||
void
|
||||
hash_append(Hasher& h, PathAsset const& pathAsset)
|
||||
{
|
||||
std::visit([&]<ValidPathAsset T>(T const& e) { hash_append(h, e); }, pathAsset.value());
|
||||
}
|
||||
|
||||
inline bool
|
||||
isXRP(PathAsset const& asset)
|
||||
{
|
||||
return asset.isXRP();
|
||||
}
|
||||
|
||||
std::string
|
||||
to_string(PathAsset const& asset);
|
||||
|
||||
std::ostream&
|
||||
operator<<(std::ostream& os, PathAsset const& x);
|
||||
|
||||
} // namespace xrpl
|
||||
@@ -164,12 +164,9 @@ public:
|
||||
constexpr TIss const&
|
||||
get() const;
|
||||
|
||||
Issue const&
|
||||
issue() const;
|
||||
|
||||
// These three are deprecated
|
||||
Currency const&
|
||||
getCurrency() const;
|
||||
template <ValidIssueType TIss>
|
||||
TIss&
|
||||
get();
|
||||
|
||||
AccountID const&
|
||||
getIssuer() const;
|
||||
@@ -225,9 +222,6 @@ public:
|
||||
void
|
||||
clear(Asset const& asset);
|
||||
|
||||
void
|
||||
setIssuer(AccountID const& uIssuer);
|
||||
|
||||
/** Set the Issue for this amount. */
|
||||
void
|
||||
setIssue(Asset const& asset);
|
||||
@@ -466,16 +460,11 @@ STAmount::get() const
|
||||
return mAsset.get<TIss>();
|
||||
}
|
||||
|
||||
inline Issue const&
|
||||
STAmount::issue() const
|
||||
template <ValidIssueType TIss>
|
||||
TIss&
|
||||
STAmount::get()
|
||||
{
|
||||
return get<Issue>();
|
||||
}
|
||||
|
||||
inline Currency const&
|
||||
STAmount::getCurrency() const
|
||||
{
|
||||
return mAsset.get<Issue>().currency;
|
||||
return mAsset.get<TIss>();
|
||||
}
|
||||
|
||||
inline AccountID const&
|
||||
@@ -505,11 +494,13 @@ operator bool() const noexcept
|
||||
inline STAmount::
|
||||
operator Number() const
|
||||
{
|
||||
if (native())
|
||||
return xrp();
|
||||
if (mAsset.holds<MPTIssue>())
|
||||
return mpt();
|
||||
return iou();
|
||||
return asset().visit(
|
||||
[&](Issue const& issue) -> Number {
|
||||
if (issue.native())
|
||||
return xrp();
|
||||
return iou();
|
||||
},
|
||||
[&](MPTIssue const&) -> Number { return mpt(); });
|
||||
}
|
||||
|
||||
inline STAmount&
|
||||
@@ -568,12 +559,6 @@ STAmount::clear(Asset const& asset)
|
||||
clear();
|
||||
}
|
||||
|
||||
inline void
|
||||
STAmount::setIssuer(AccountID const& uIssuer)
|
||||
{
|
||||
mAsset.get<Issue>().account = uIssuer;
|
||||
}
|
||||
|
||||
inline STAmount const&
|
||||
STAmount::value() const noexcept
|
||||
{
|
||||
|
||||
@@ -349,6 +349,8 @@ public:
|
||||
void
|
||||
setFieldH128(SField const& field, uint128 const&);
|
||||
void
|
||||
setFieldH192(SField const& field, uint192 const&);
|
||||
void
|
||||
setFieldH256(SField const& field, uint256 const&);
|
||||
void
|
||||
setFieldI32(SField const& field, std::int32_t);
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
#include <xrpl/basics/CountedObject.h>
|
||||
#include <xrpl/beast/utility/instrumentation.h>
|
||||
#include <xrpl/json/json_value.h>
|
||||
#include <xrpl/protocol/Asset.h>
|
||||
#include <xrpl/protocol/PathAsset.h>
|
||||
#include <xrpl/protocol/SField.h>
|
||||
#include <xrpl/protocol/STBase.h>
|
||||
#include <xrpl/protocol/UintTypes.h>
|
||||
@@ -16,7 +18,7 @@ class STPathElement final : public CountedObject<STPathElement>
|
||||
{
|
||||
unsigned int mType;
|
||||
AccountID mAccountID;
|
||||
Currency mCurrencyID;
|
||||
PathAsset mAssetID;
|
||||
AccountID mIssuerID;
|
||||
|
||||
bool is_offer_;
|
||||
@@ -28,8 +30,10 @@ public:
|
||||
typeAccount = 0x01, // Rippling through an account (vs taking an offer).
|
||||
typeCurrency = 0x10, // Currency follows.
|
||||
typeIssuer = 0x20, // Issuer follows.
|
||||
typeMPT = 0x40, // MPT follows.
|
||||
typeBoundary = 0xFF, // Boundary between alternate paths.
|
||||
typeAll = typeAccount | typeCurrency | typeIssuer,
|
||||
typeAsset = typeCurrency | typeMPT,
|
||||
typeAll = typeAccount | typeCurrency | typeIssuer | typeMPT,
|
||||
// Combination of all types.
|
||||
};
|
||||
|
||||
@@ -40,19 +44,19 @@ public:
|
||||
|
||||
STPathElement(
|
||||
std::optional<AccountID> const& account,
|
||||
std::optional<Currency> const& currency,
|
||||
std::optional<PathAsset> const& asset,
|
||||
std::optional<AccountID> const& issuer);
|
||||
|
||||
STPathElement(
|
||||
AccountID const& account,
|
||||
Currency const& currency,
|
||||
PathAsset const& asset,
|
||||
AccountID const& issuer,
|
||||
bool forceCurrency = false);
|
||||
bool forceAsset = false);
|
||||
|
||||
STPathElement(
|
||||
unsigned int uType,
|
||||
AccountID const& account,
|
||||
Currency const& currency,
|
||||
PathAsset const& asset,
|
||||
AccountID const& issuer);
|
||||
|
||||
auto
|
||||
@@ -70,6 +74,12 @@ public:
|
||||
bool
|
||||
hasCurrency() const;
|
||||
|
||||
bool
|
||||
hasMPT() const;
|
||||
|
||||
bool
|
||||
hasAsset() const;
|
||||
|
||||
bool
|
||||
isNone() const;
|
||||
|
||||
@@ -78,12 +88,21 @@ public:
|
||||
AccountID const&
|
||||
getAccountID() const;
|
||||
|
||||
PathAsset const&
|
||||
getPathAsset() const;
|
||||
|
||||
Currency const&
|
||||
getCurrency() const;
|
||||
|
||||
MPTID const&
|
||||
getMPTID() const;
|
||||
|
||||
AccountID const&
|
||||
getIssuerID() const;
|
||||
|
||||
bool
|
||||
isType(Type const& pe) const;
|
||||
|
||||
bool
|
||||
operator==(STPathElement const& t) const;
|
||||
|
||||
@@ -118,7 +137,7 @@ public:
|
||||
emplace_back(Args&&... args);
|
||||
|
||||
bool
|
||||
hasSeen(AccountID const& account, Currency const& currency, AccountID const& issuer) const;
|
||||
hasSeen(AccountID const& account, PathAsset const& asset, AccountID const& issuer) const;
|
||||
|
||||
Json::Value getJson(JsonOptions) const;
|
||||
|
||||
@@ -221,7 +240,7 @@ inline STPathElement::STPathElement() : mType(typeNone), is_offer_(true)
|
||||
|
||||
inline STPathElement::STPathElement(
|
||||
std::optional<AccountID> const& account,
|
||||
std::optional<Currency> const& currency,
|
||||
std::optional<PathAsset> const& asset,
|
||||
std::optional<AccountID> const& issuer)
|
||||
: mType(typeNone)
|
||||
{
|
||||
@@ -238,10 +257,10 @@ inline STPathElement::STPathElement(
|
||||
mAccountID != noAccount(), "xrpl::STPathElement::STPathElement : account is set");
|
||||
}
|
||||
|
||||
if (currency)
|
||||
if (asset)
|
||||
{
|
||||
mCurrencyID = *currency;
|
||||
mType |= typeCurrency;
|
||||
mAssetID = *asset;
|
||||
mType |= mAssetID.holds<Currency>() ? typeCurrency : typeMPT;
|
||||
}
|
||||
|
||||
if (issuer)
|
||||
@@ -256,20 +275,20 @@ inline STPathElement::STPathElement(
|
||||
|
||||
inline STPathElement::STPathElement(
|
||||
AccountID const& account,
|
||||
Currency const& currency,
|
||||
PathAsset const& asset,
|
||||
AccountID const& issuer,
|
||||
bool forceCurrency)
|
||||
bool forceAsset)
|
||||
: mType(typeNone)
|
||||
, mAccountID(account)
|
||||
, mCurrencyID(currency)
|
||||
, mAssetID(asset)
|
||||
, mIssuerID(issuer)
|
||||
, is_offer_(isXRP(mAccountID))
|
||||
{
|
||||
if (!is_offer_)
|
||||
mType |= typeAccount;
|
||||
|
||||
if (forceCurrency || !isXRP(currency))
|
||||
mType |= typeCurrency;
|
||||
if (forceAsset || !isXRP(mAssetID))
|
||||
mType |= asset.holds<Currency>() ? typeCurrency : typeMPT;
|
||||
|
||||
if (!isXRP(issuer))
|
||||
mType |= typeIssuer;
|
||||
@@ -280,14 +299,19 @@ inline STPathElement::STPathElement(
|
||||
inline STPathElement::STPathElement(
|
||||
unsigned int uType,
|
||||
AccountID const& account,
|
||||
Currency const& currency,
|
||||
PathAsset const& asset,
|
||||
AccountID const& issuer)
|
||||
: mType(uType)
|
||||
, mAccountID(account)
|
||||
, mCurrencyID(currency)
|
||||
, mAssetID(asset)
|
||||
, mIssuerID(issuer)
|
||||
, is_offer_(isXRP(mAccountID))
|
||||
{
|
||||
// uType could be assetType; i.e. either Currency or MPTID.
|
||||
// Get the actual type.
|
||||
mAssetID.visit(
|
||||
[&](Currency const&) { mType = mType & (~Type::typeMPT); },
|
||||
[&](MPTID const&) { mType = mType & (~Type::typeCurrency); });
|
||||
hash_value_ = get_hash(*this);
|
||||
}
|
||||
|
||||
@@ -309,16 +333,34 @@ STPathElement::isAccount() const
|
||||
return !isOffer();
|
||||
}
|
||||
|
||||
inline bool
|
||||
STPathElement::isType(Type const& pe) const
|
||||
{
|
||||
return (mType & pe) != 0u;
|
||||
}
|
||||
|
||||
inline bool
|
||||
STPathElement::hasIssuer() const
|
||||
{
|
||||
return getNodeType() & STPathElement::typeIssuer;
|
||||
return isType(STPathElement::typeIssuer);
|
||||
}
|
||||
|
||||
inline bool
|
||||
STPathElement::hasCurrency() const
|
||||
{
|
||||
return getNodeType() & STPathElement::typeCurrency;
|
||||
return isType(STPathElement::typeCurrency);
|
||||
}
|
||||
|
||||
inline bool
|
||||
STPathElement::hasMPT() const
|
||||
{
|
||||
return isType(STPathElement::typeMPT);
|
||||
}
|
||||
|
||||
inline bool
|
||||
STPathElement::hasAsset() const
|
||||
{
|
||||
return isType(STPathElement::typeAsset);
|
||||
}
|
||||
|
||||
inline bool
|
||||
@@ -335,10 +377,22 @@ STPathElement::getAccountID() const
|
||||
return mAccountID;
|
||||
}
|
||||
|
||||
inline PathAsset const&
|
||||
STPathElement::getPathAsset() const
|
||||
{
|
||||
return mAssetID;
|
||||
}
|
||||
|
||||
inline Currency const&
|
||||
STPathElement::getCurrency() const
|
||||
{
|
||||
return mCurrencyID;
|
||||
return mAssetID.get<Currency>();
|
||||
}
|
||||
|
||||
inline MPTID const&
|
||||
STPathElement::getMPTID() const
|
||||
{
|
||||
return mAssetID.get<MPTID>();
|
||||
}
|
||||
|
||||
inline AccountID const&
|
||||
@@ -351,7 +405,7 @@ inline bool
|
||||
STPathElement::operator==(STPathElement const& t) const
|
||||
{
|
||||
return (mType & typeAccount) == (t.mType & typeAccount) && hash_value_ == t.hash_value_ &&
|
||||
mAccountID == t.mAccountID && mCurrencyID == t.mCurrencyID && mIssuerID == t.mIssuerID;
|
||||
mAccountID == t.mAccountID && mAssetID == t.mAssetID && mIssuerID == t.mIssuerID;
|
||||
}
|
||||
|
||||
inline bool
|
||||
|
||||
@@ -122,6 +122,7 @@ enum TEMcodes : TERUnderlyingType {
|
||||
temBAD_TRANSFER_FEE,
|
||||
temINVALID_INNER_BATCH,
|
||||
|
||||
temBAD_MPT,
|
||||
temBAD_WASM,
|
||||
};
|
||||
|
||||
@@ -210,6 +211,7 @@ enum TERcodes : TERUnderlyingType {
|
||||
terADDRESS_COLLISION, // Failed to allocate AccountID when trying to
|
||||
// create a pseudo-account
|
||||
terNO_DELEGATE_PERMISSION, // Delegate does not have permission
|
||||
terLOCKED, // MPT is locked
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
// Keep it sorted in reverse chronological order.
|
||||
|
||||
XRPL_FEATURE(SmartEscrow, Supported::no, VoteBehavior::DefaultNo)
|
||||
XRPL_FEATURE(MPTokensV2, Supported::no, VoteBehavior::DefaultNo)
|
||||
XRPL_FIX (Security3_1_3, Supported::no, VoteBehavior::DefaultNo)
|
||||
XRPL_FIX (PermissionedDomainInvariant, Supported::yes, VoteBehavior::DefaultNo)
|
||||
XRPL_FIX (ExpiredNFTokenOfferRemoval, Supported::yes, VoteBehavior::DefaultNo)
|
||||
|
||||
@@ -161,8 +161,10 @@ LEDGER_ENTRY(ltDIR_NODE, 0x0064, DirectoryNode, directory, ({
|
||||
{sfOwner, soeOPTIONAL}, // for owner directories
|
||||
{sfTakerPaysCurrency, soeOPTIONAL}, // order book directories
|
||||
{sfTakerPaysIssuer, soeOPTIONAL}, // order book directories
|
||||
{sfTakerPaysMPT, soeOPTIONAL}, // order book directories
|
||||
{sfTakerGetsCurrency, soeOPTIONAL}, // order book directories
|
||||
{sfTakerGetsIssuer, soeOPTIONAL}, // order book directories
|
||||
{sfTakerGetsMPT, soeOPTIONAL}, // order book directories
|
||||
{sfExchangeRate, soeOPTIONAL}, // order book directories
|
||||
{sfIndexes, soeREQUIRED},
|
||||
{sfRootIndex, soeREQUIRED},
|
||||
|
||||
@@ -162,6 +162,8 @@ TYPED_SFIELD(sfTakerGetsIssuer, UINT160, 4)
|
||||
// 192-bit (common)
|
||||
TYPED_SFIELD(sfMPTokenIssuanceID, UINT192, 1)
|
||||
TYPED_SFIELD(sfShareMPTID, UINT192, 2)
|
||||
TYPED_SFIELD(sfTakerPaysMPT, UINT192, 3)
|
||||
TYPED_SFIELD(sfTakerGetsMPT, UINT192, 4)
|
||||
|
||||
// 256-bit (common)
|
||||
TYPED_SFIELD(sfLedgerHash, UINT256, 1)
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
TRANSACTION(ttPAYMENT, 0, Payment,
|
||||
Delegation::delegable,
|
||||
uint256{},
|
||||
createAcct,
|
||||
createAcct | mayCreateMPT,
|
||||
({
|
||||
{sfDestination, soeREQUIRED},
|
||||
{sfAmount, soeREQUIRED, soeMPTSupported},
|
||||
@@ -129,10 +129,10 @@ TRANSACTION(ttREGULAR_KEY_SET, 5, SetRegularKey,
|
||||
TRANSACTION(ttOFFER_CREATE, 7, OfferCreate,
|
||||
Delegation::delegable,
|
||||
uint256{},
|
||||
noPriv,
|
||||
mayCreateMPT,
|
||||
({
|
||||
{sfTakerPays, soeREQUIRED},
|
||||
{sfTakerGets, soeREQUIRED},
|
||||
{sfTakerPays, soeREQUIRED, soeMPTSupported},
|
||||
{sfTakerGets, soeREQUIRED, soeMPTSupported},
|
||||
{sfExpiration, soeOPTIONAL},
|
||||
{sfOfferSequence, soeOPTIONAL},
|
||||
{sfDomainID, soeOPTIONAL},
|
||||
@@ -239,7 +239,7 @@ TRANSACTION(ttCHECK_CREATE, 16, CheckCreate,
|
||||
noPriv,
|
||||
({
|
||||
{sfDestination, soeREQUIRED},
|
||||
{sfSendMax, soeREQUIRED},
|
||||
{sfSendMax, soeREQUIRED, soeMPTSupported},
|
||||
{sfExpiration, soeOPTIONAL},
|
||||
{sfDestinationTag, soeOPTIONAL},
|
||||
{sfInvoiceID, soeOPTIONAL},
|
||||
@@ -252,11 +252,11 @@ TRANSACTION(ttCHECK_CREATE, 16, CheckCreate,
|
||||
TRANSACTION(ttCHECK_CASH, 17, CheckCash,
|
||||
Delegation::delegable,
|
||||
uint256{},
|
||||
noPriv,
|
||||
mayCreateMPT,
|
||||
({
|
||||
{sfCheckID, soeREQUIRED},
|
||||
{sfAmount, soeOPTIONAL},
|
||||
{sfDeliverMin, soeOPTIONAL},
|
||||
{sfAmount, soeOPTIONAL, soeMPTSupported},
|
||||
{sfDeliverMin, soeOPTIONAL, soeMPTSupported},
|
||||
}))
|
||||
|
||||
/** This transaction type cancels an existing check. */
|
||||
@@ -409,12 +409,12 @@ TRANSACTION(ttCLAWBACK, 30, Clawback,
|
||||
TRANSACTION(ttAMM_CLAWBACK, 31, AMMClawback,
|
||||
Delegation::delegable,
|
||||
featureAMMClawback,
|
||||
mayDeleteAcct | overrideFreeze,
|
||||
mayDeleteAcct | overrideFreeze | mayAuthorizeMPT,
|
||||
({
|
||||
{sfHolder, soeREQUIRED},
|
||||
{sfAsset, soeREQUIRED},
|
||||
{sfAsset2, soeREQUIRED},
|
||||
{sfAmount, soeOPTIONAL},
|
||||
{sfAsset, soeREQUIRED, soeMPTSupported},
|
||||
{sfAsset2, soeREQUIRED, soeMPTSupported},
|
||||
{sfAmount, soeOPTIONAL, soeMPTSupported},
|
||||
}))
|
||||
|
||||
/** This transaction type creates an AMM instance */
|
||||
@@ -424,10 +424,10 @@ TRANSACTION(ttAMM_CLAWBACK, 31, AMMClawback,
|
||||
TRANSACTION(ttAMM_CREATE, 35, AMMCreate,
|
||||
Delegation::delegable,
|
||||
featureAMM,
|
||||
createPseudoAcct,
|
||||
createPseudoAcct | mayCreateMPT,
|
||||
({
|
||||
{sfAmount, soeREQUIRED},
|
||||
{sfAmount2, soeREQUIRED},
|
||||
{sfAmount, soeREQUIRED, soeMPTSupported},
|
||||
{sfAmount2, soeREQUIRED, soeMPTSupported},
|
||||
{sfTradingFee, soeREQUIRED},
|
||||
}))
|
||||
|
||||
@@ -440,10 +440,10 @@ TRANSACTION(ttAMM_DEPOSIT, 36, AMMDeposit,
|
||||
featureAMM,
|
||||
noPriv,
|
||||
({
|
||||
{sfAsset, soeREQUIRED},
|
||||
{sfAsset2, soeREQUIRED},
|
||||
{sfAmount, soeOPTIONAL},
|
||||
{sfAmount2, soeOPTIONAL},
|
||||
{sfAsset, soeREQUIRED, soeMPTSupported},
|
||||
{sfAsset2, soeREQUIRED, soeMPTSupported},
|
||||
{sfAmount, soeOPTIONAL, soeMPTSupported},
|
||||
{sfAmount2, soeOPTIONAL, soeMPTSupported},
|
||||
{sfEPrice, soeOPTIONAL},
|
||||
{sfLPTokenOut, soeOPTIONAL},
|
||||
{sfTradingFee, soeOPTIONAL},
|
||||
@@ -456,12 +456,12 @@ TRANSACTION(ttAMM_DEPOSIT, 36, AMMDeposit,
|
||||
TRANSACTION(ttAMM_WITHDRAW, 37, AMMWithdraw,
|
||||
Delegation::delegable,
|
||||
featureAMM,
|
||||
mayDeleteAcct,
|
||||
mayDeleteAcct | mayAuthorizeMPT,
|
||||
({
|
||||
{sfAsset, soeREQUIRED},
|
||||
{sfAsset2, soeREQUIRED},
|
||||
{sfAmount, soeOPTIONAL},
|
||||
{sfAmount2, soeOPTIONAL},
|
||||
{sfAsset, soeREQUIRED, soeMPTSupported},
|
||||
{sfAsset2, soeREQUIRED, soeMPTSupported},
|
||||
{sfAmount, soeOPTIONAL, soeMPTSupported},
|
||||
{sfAmount2, soeOPTIONAL, soeMPTSupported},
|
||||
{sfEPrice, soeOPTIONAL},
|
||||
{sfLPTokenIn, soeOPTIONAL},
|
||||
}))
|
||||
@@ -475,8 +475,8 @@ TRANSACTION(ttAMM_VOTE, 38, AMMVote,
|
||||
featureAMM,
|
||||
noPriv,
|
||||
({
|
||||
{sfAsset, soeREQUIRED},
|
||||
{sfAsset2, soeREQUIRED},
|
||||
{sfAsset, soeREQUIRED, soeMPTSupported},
|
||||
{sfAsset2, soeREQUIRED, soeMPTSupported},
|
||||
{sfTradingFee, soeREQUIRED},
|
||||
}))
|
||||
|
||||
@@ -489,8 +489,8 @@ TRANSACTION(ttAMM_BID, 39, AMMBid,
|
||||
featureAMM,
|
||||
noPriv,
|
||||
({
|
||||
{sfAsset, soeREQUIRED},
|
||||
{sfAsset2, soeREQUIRED},
|
||||
{sfAsset, soeREQUIRED, soeMPTSupported},
|
||||
{sfAsset2, soeREQUIRED, soeMPTSupported},
|
||||
{sfBidMin, soeOPTIONAL},
|
||||
{sfBidMax, soeOPTIONAL},
|
||||
{sfAuthAccounts, soeOPTIONAL},
|
||||
@@ -503,10 +503,10 @@ TRANSACTION(ttAMM_BID, 39, AMMBid,
|
||||
TRANSACTION(ttAMM_DELETE, 40, AMMDelete,
|
||||
Delegation::delegable,
|
||||
featureAMM,
|
||||
mustDeleteAcct,
|
||||
mustDeleteAcct | mayDeleteMPT,
|
||||
({
|
||||
{sfAsset, soeREQUIRED},
|
||||
{sfAsset2, soeREQUIRED},
|
||||
{sfAsset, soeREQUIRED, soeMPTSupported},
|
||||
{sfAsset2, soeREQUIRED, soeMPTSupported},
|
||||
}))
|
||||
|
||||
/** This transactions creates a crosschain sequence number */
|
||||
|
||||
@@ -404,6 +404,8 @@ JSS(min_ledger); // in: LedgerCleaner
|
||||
JSS(minimum_fee); // out: TxQ
|
||||
JSS(minimum_level); // out: TxQ
|
||||
JSS(missingCommand); // error
|
||||
JSS(mpt_issuance_id_a); // out: BookChanges
|
||||
JSS(mpt_issuance_id_b); // out: BookChanges
|
||||
JSS(name); // out: AmendmentTableImpl, PeerImp
|
||||
JSS(needed_state_hashes); // out: InboundLedger
|
||||
JSS(needed_transaction_hashes); // out: InboundLedger
|
||||
|
||||
Reference in New Issue
Block a user