Skip to content

Commit

Permalink
Add MPTIssue to STIssue (#5200)
Browse files Browse the repository at this point in the history
Replace Issue in STIssue with Asset. STIssue with MPTIssue is only used in MPT tests.
Will be used in Vault and in transactions with STIssue fields once MPT is integrated into DEX.
  • Loading branch information
gregtatcam authored Dec 16, 2024
1 parent eabca84 commit 5cd72f2
Show file tree
Hide file tree
Showing 22 changed files with 463 additions and 143 deletions.
33 changes: 27 additions & 6 deletions include/xrpl/protocol/Asset.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,19 +26,28 @@

namespace ripple {

class Asset;

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>;

/* 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
* type. Many functions and classes there were first written for Issue
* have been rewritten for Asset.
*/
class Asset
{
private:
public:
using value_type = std::variant<Issue, MPTIssue>;

private:
value_type issue_;

public:
Expand Down Expand Up @@ -92,8 +101,8 @@ class Asset
friend constexpr bool
operator==(Asset const& lhs, Asset const& rhs);

friend constexpr bool
operator!=(Asset const& lhs, Asset const& rhs);
friend constexpr std::weak_ordering
operator<=>(Asset const& lhs, Asset const& rhs);

friend constexpr bool
operator==(Currency const& lhs, Asset const& rhs);
Expand Down Expand Up @@ -151,10 +160,22 @@ operator==(Asset const& lhs, Asset const& rhs)
rhs.issue_);
}

constexpr bool
operator!=(Asset const& lhs, Asset const& rhs)
constexpr std::weak_ordering
operator<=>(Asset const& lhs, Asset const& rhs)
{
return !(lhs == rhs);
return std::visit(
[]<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>)
return std::weak_ordering::greater;
else
return std::weak_ordering::less;
},
lhs.issue_,
rhs.issue_);
}

constexpr bool
Expand Down
2 changes: 1 addition & 1 deletion include/xrpl/protocol/Indexes.h
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@ nft_sells(uint256 const& id) noexcept;

/** AMM entry */
Keylet
amm(Issue const& issue1, Issue const& issue2) noexcept;
amm(Asset const& issue1, Asset const& issue2) noexcept;

Keylet
amm(uint256 const& amm) noexcept;
Expand Down
5 changes: 4 additions & 1 deletion include/xrpl/protocol/Issue.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ class Issue

bool
native() const;

friend constexpr std::weak_ordering
operator<=>(Issue const& lhs, Issue const& rhs);
};

bool
Expand Down Expand Up @@ -95,7 +98,7 @@ operator==(Issue const& lhs, Issue const& rhs)

/** Strict weak ordering. */
/** @{ */
[[nodiscard]] inline constexpr std::weak_ordering
[[nodiscard]] constexpr std::weak_ordering
operator<=>(Issue const& lhs, Issue const& rhs)
{
if (auto const c{lhs.currency <=> rhs.currency}; c != 0)
Expand Down
10 changes: 5 additions & 5 deletions include/xrpl/protocol/MPTIssue.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@ class MPTIssue
friend constexpr bool
operator==(MPTIssue const& lhs, MPTIssue const& rhs);

friend constexpr bool
operator!=(MPTIssue const& lhs, MPTIssue const& rhs);
friend constexpr std::weak_ordering
operator<=>(MPTIssue const& lhs, MPTIssue const& rhs);

bool
native() const
Expand All @@ -70,10 +70,10 @@ operator==(MPTIssue const& lhs, MPTIssue const& rhs)
return lhs.mptID_ == rhs.mptID_;
}

constexpr bool
operator!=(MPTIssue const& lhs, MPTIssue const& rhs)
constexpr std::weak_ordering
operator<=>(MPTIssue const& lhs, MPTIssue const& rhs)
{
return !(lhs == rhs);
return lhs.mptID_ <=> rhs.mptID_;
}

/** MPT is a non-native token.
Expand Down
13 changes: 8 additions & 5 deletions include/xrpl/protocol/SOTemplate.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ enum SOEStyle {
};

/** Amount fields that can support MPT */
enum SOETxMPTAmount { soeMPTNone, soeMPTSupported, soeMPTNotSupported };
enum SOETxMPTIssue { soeMPTNone, soeMPTSupported, soeMPTNotSupported };

//------------------------------------------------------------------------------

Expand All @@ -50,7 +50,7 @@ class SOElement
// Use std::reference_wrapper so SOElement can be stored in a std::vector.
std::reference_wrapper<SField const> sField_;
SOEStyle style_;
SOETxMPTAmount supportMpt_ = soeMPTNone;
SOETxMPTIssue supportMpt_ = soeMPTNone;

private:
void
Expand All @@ -72,10 +72,13 @@ class SOElement
{
init(fieldName);
}

template <typename T>
requires(std::is_same_v<T, STAmount> || std::is_same_v<T, STIssue>)
SOElement(
TypedField<STAmount> const& fieldName,
TypedField<T> const& fieldName,
SOEStyle style,
SOETxMPTAmount supportMpt = soeMPTNotSupported)
SOETxMPTIssue supportMpt = soeMPTNotSupported)
: sField_(fieldName), style_(style), supportMpt_(supportMpt)
{
init(fieldName);
Expand All @@ -93,7 +96,7 @@ class SOElement
return style_;
}

SOETxMPTAmount
SOETxMPTIssue
supportMPT() const
{
return supportMpt_;
Expand Down
5 changes: 0 additions & 5 deletions include/xrpl/protocol/STAmount.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,6 @@

namespace ripple {

template <typename A>
concept AssetType =
std::is_same_v<A, Asset> || std::is_convertible_v<A, Issue> ||
std::is_convertible_v<A, MPTIssue> || std::is_convertible_v<A, MPTID>;

// Internal form:
// 1: If amount is zero, then value is zero and offset is -100
// 2: Otherwise:
Expand Down
102 changes: 68 additions & 34 deletions include/xrpl/protocol/STIssue.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
#define RIPPLE_PROTOCOL_STISSUE_H_INCLUDED

#include <xrpl/basics/CountedObject.h>
#include <xrpl/protocol/Issue.h>
#include <xrpl/protocol/Asset.h>
#include <xrpl/protocol/SField.h>
#include <xrpl/protocol/STBase.h>
#include <xrpl/protocol/Serializer.h>
Expand All @@ -31,31 +31,40 @@ namespace ripple {
class STIssue final : public STBase, CountedObject<STIssue>
{
private:
Issue issue_{xrpIssue()};
Asset asset_{xrpIssue()};

public:
using value_type = Issue;
using value_type = Asset;

STIssue() = default;

explicit STIssue(SerialIter& sit, SField const& name);

explicit STIssue(SField const& name, Issue const& issue);
template <AssetType A>
explicit STIssue(SField const& name, A const& issue);

explicit STIssue(SField const& name);

Issue const&
issue() const;
template <ValidIssueType TIss>
TIss const&
get() const;

Issue const&
template <ValidIssueType TIss>
bool
holds() const;

value_type const&
value() const noexcept;

void
setIssue(Issue const& issue);
setIssue(Asset const& issue);

SerializedTypeID
getSType() const override;

std::string
getText() const override;

Json::Value getJson(JsonOptions) const override;

void
Expand All @@ -67,6 +76,18 @@ class STIssue final : public STBase, CountedObject<STIssue>
bool
isDefault() const override;

friend constexpr bool
operator==(STIssue const& lhs, STIssue const& rhs);

friend constexpr std::weak_ordering
operator<=>(STIssue const& lhs, STIssue const& rhs);

friend constexpr bool
operator==(STIssue const& lhs, Asset const& rhs);

friend constexpr std::weak_ordering
operator<=>(STIssue const& lhs, Asset const& rhs);

private:
STBase*
copy(std::size_t n, void* buf) const override;
Expand All @@ -76,59 +97,72 @@ class STIssue final : public STBase, CountedObject<STIssue>
friend class detail::STVar;
};

template <AssetType A>
STIssue::STIssue(SField const& name, A const& asset)
: STBase{name}, asset_{asset}
{
if (holds<Issue>() && !isConsistent(asset_.get<Issue>()))
Throw<std::runtime_error>(
"Invalid asset: currency and account native mismatch");
}

STIssue
issueFromJson(SField const& name, Json::Value const& v);

inline Issue const&
STIssue::issue() const
template <ValidIssueType TIss>
bool
STIssue::holds() const
{
return asset_.holds<TIss>();
}

template <ValidIssueType TIss>
TIss const&
STIssue::get() const
{
return issue_;
if (!holds<TIss>(asset_))
Throw<std::runtime_error>("Asset doesn't hold the requested issue");
return std::get<TIss>(asset_);
}

inline Issue const&
inline STIssue::value_type const&
STIssue::value() const noexcept
{
return issue_;
return asset_;
}

inline void
STIssue::setIssue(Issue const& issue)
STIssue::setIssue(Asset const& asset)
{
if (isXRP(issue_.currency) != isXRP(issue_.account))
if (holds<Issue>() && !isConsistent(asset_.get<Issue>()))
Throw<std::runtime_error>(
"invalid issue: currency and account native mismatch");
"Invalid asset: currency and account native mismatch");

issue_ = issue;
asset_ = asset;
}

inline bool
constexpr bool
operator==(STIssue const& lhs, STIssue const& rhs)
{
return lhs.issue() == rhs.issue();
}

inline bool
operator!=(STIssue const& lhs, STIssue const& rhs)
{
return !operator==(lhs, rhs);
return lhs.asset_ == rhs.asset_;
}

inline bool
operator<(STIssue const& lhs, STIssue const& rhs)
constexpr std::weak_ordering
operator<=>(STIssue const& lhs, STIssue const& rhs)
{
return lhs.issue() < rhs.issue();
return lhs.asset_ <=> rhs.asset_;
}

inline bool
operator==(STIssue const& lhs, Issue const& rhs)
constexpr bool
operator==(STIssue const& lhs, Asset const& rhs)
{
return lhs.issue() == rhs;
return lhs.asset_ == rhs;
}

inline bool
operator<(STIssue const& lhs, Issue const& rhs)
constexpr std::weak_ordering
operator<=>(STIssue const& lhs, Asset const& rhs)
{
return lhs.issue() < rhs;
return lhs.asset_ <=> rhs;
}

} // namespace ripple
Expand Down
4 changes: 2 additions & 2 deletions include/xrpl/protocol/STXChainBridge.h
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ STXChainBridge::lockingChainDoor() const
inline Issue const&
STXChainBridge::lockingChainIssue() const
{
return lockingChainIssue_.value();
return lockingChainIssue_.value().get<Issue>();
};

inline AccountID const&
Expand All @@ -182,7 +182,7 @@ STXChainBridge::issuingChainDoor() const
inline Issue const&
STXChainBridge::issuingChainIssue() const
{
return issuingChainIssue_.value();
return issuingChainIssue_.value().get<Issue>();
};

inline STXChainBridge::value_type const&
Expand Down
6 changes: 4 additions & 2 deletions src/libxrpl/protocol/Indexes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
//==============================================================================

#include <xrpl/beast/utility/instrumentation.h>
#include <xrpl/protocol/Asset.h>
#include <xrpl/protocol/Indexes.h>
#include <xrpl/protocol/LedgerFormats.h>
#include <xrpl/protocol/SField.h>
Expand Down Expand Up @@ -417,9 +418,10 @@ nft_sells(uint256 const& id) noexcept
}

Keylet
amm(Issue const& issue1, Issue const& issue2) noexcept
amm(Asset const& issue1, Asset const& issue2) noexcept
{
auto const& [minI, maxI] = std::minmax(issue1, issue2);
auto const& [minI, maxI] =
std::minmax(issue1.get<Issue>(), issue2.get<Issue>());
return amm(indexHash(
LedgerNameSpace::AMM,
minI.account,
Expand Down
Loading

0 comments on commit 5cd72f2

Please sign in to comment.