Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add MPTIssue to STIssue #5200

Merged
merged 13 commits into from
Dec 16, 2024
33 changes: 27 additions & 6 deletions include/xrpl/protocol/Asset.h
Bronek marked this conversation as resolved.
Show resolved Hide resolved
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>;
Bronek marked this conversation as resolved.
Show resolved Hide resolved

/* 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;
},
Copy link
Collaborator

@Bronek Bronek Dec 10, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is correct as long as we have exactly these two types i.e. Issue, MPTIssue inside issue_. As soon as that changes it will be no longer correct, meaning that this code is brittle. This is why I would prefer index comparison instead.

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
Bronek marked this conversation as resolved.
Show resolved Hide resolved
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>
Bronek marked this conversation as resolved.
Show resolved Hide resolved
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()};
Bronek marked this conversation as resolved.
Show resolved Hide resolved

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
Bronek marked this conversation as resolved.
Show resolved Hide resolved
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>(
Bronek marked this conversation as resolved.
Show resolved Hide resolved
"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;
Bronek marked this conversation as resolved.
Show resolved Hide resolved
}

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>());
Bronek marked this conversation as resolved.
Show resolved Hide resolved
return amm(indexHash(
LedgerNameSpace::AMM,
minI.account,
Expand Down
Loading
Loading