Skip to content

Commit

Permalink
Add MPT to STIssue
Browse files Browse the repository at this point in the history
  • Loading branch information
gregtatcam committed Sep 19, 2024
1 parent e106609 commit c0ed04b
Show file tree
Hide file tree
Showing 16 changed files with 172 additions and 75 deletions.
24 changes: 24 additions & 0 deletions include/xrpl/protocol/Asset.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,16 @@

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_same_v<A, Asset> ||
std::is_convertible_v<A, Issue> || std::is_convertible_v<A, MPTIssue>;

class Asset
{
private:
Expand Down Expand Up @@ -78,6 +84,9 @@ class Asset

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

friend constexpr bool
operator<(Asset const& lhs, Asset const& rhs);
};

template <ValidIssueType TIss>
Expand Down Expand Up @@ -132,6 +141,21 @@ operator!=(Asset const& lhs, Asset const& rhs)
return !(lhs == rhs);
}

constexpr bool
operator<(Asset const& lhs, Asset const& rhs)
{
return std::visit(
[&]<typename TLhs, typename TRhs>(
TLhs const& issLhs, TRhs const& issRhs) {
if constexpr (std::is_same_v<TLhs, TRhs>)
return issLhs < issRhs;
else
return false;
},
lhs.issue_,
rhs.issue_);
}

inline bool
isXRP(Asset const& asset)
{
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 @@ -267,7 +267,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
4 changes: 0 additions & 4 deletions include/xrpl/protocol/STAmount.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,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>;

// Internal form:
// 1: If amount is zero, then value is zero and offset is -100
// 2: Otherwise:
Expand Down
74 changes: 51 additions & 23 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 @@ -76,35 +85,54 @@ 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 std::holds_alternative<TIss>(asset_.value());
}

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
operator==(STIssue const& lhs, STIssue const& rhs)
{
return lhs.issue() == rhs.issue();
return lhs.value() == rhs.value();
}

inline bool
Expand All @@ -116,19 +144,19 @@ operator!=(STIssue const& lhs, STIssue const& rhs)
inline bool
operator<(STIssue const& lhs, STIssue const& rhs)
{
return lhs.issue() < rhs.issue();
return lhs.value() < rhs.value();
}

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

inline bool
operator<(STIssue const& lhs, Issue const& rhs)
operator<(STIssue const& lhs, Asset const& rhs)
{
return lhs.issue() < rhs;
return lhs.value() < 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
5 changes: 1 addition & 4 deletions src/libxrpl/protocol/Asset.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,7 @@ Asset::setJson(Json::Value& jv) const
if (holds<MPTIssue>())
jv[jss::mpt_issuance_id] = to_string(get<MPTIssue>().getMptID());
else
{
jv[jss::currency] = to_string(get<Issue>().currency);
jv[jss::issuer] = to_string(get<Issue>().account);
}
jv = to_json(get<Issue>());
}

std::string
Expand Down
8 changes: 6 additions & 2 deletions src/libxrpl/protocol/Indexes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
*/
//==============================================================================

#include <xrpl/protocol/Asset.h>
#include <xrpl/protocol/Indexes.h>
#include <xrpl/protocol/LedgerFormats.h>
#include <xrpl/protocol/SField.h>
Expand Down Expand Up @@ -393,9 +394,12 @@ 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);
if (!issue1.holds<Issue>() || !issue2.holds<Issue>())
Throw<std::runtime_error>("Asset doesn't hold issue");
auto const& [minI, maxI] =
std::minmax(issue1.get<Issue>(), issue2.get<Issue>());
return amm(indexHash(
LedgerNameSpace::AMM,
minI.account,
Expand Down
85 changes: 64 additions & 21 deletions src/libxrpl/protocol/STIssue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,23 +40,44 @@ STIssue::STIssue(SField const& name) : STBase{name}

STIssue::STIssue(SerialIter& sit, SField const& name) : STBase{name}
{
issue_.currency = sit.get160();
if (!isXRP(issue_.currency))
issue_.account = sit.get160();
else
issue_.account = xrpAccount();

if (isXRP(issue_.currency) != isXRP(issue_.account))
Throw<std::runtime_error>(
"invalid issue: currency and account native mismatch");
}
auto const currencyOrAccount = sit.get160();

STIssue::STIssue(SField const& name, Issue const& issue)
: STBase{name}, issue_{issue}
{
if (isXRP(issue_.currency) != isXRP(issue_.account))
Throw<std::runtime_error>(
"invalid issue: currency and account native mismatch");
if (isXRP(static_cast<Currency>(currencyOrAccount)))
{
asset_ = xrpIssue();
}
// Check if MPT
else
{
// MPT is serialized as:
// - 160 bits MPT issuer account
// - 160 bits black hole account
// - 32 bits sequence
AccountID account = static_cast<AccountID>(sit.get160());
// MPT
if (noAccount() == account)
{
uint192 mptID;
std::uint32_t sequence = sit.get32();
memcpy(mptID.data(), &sequence, sizeof(sequence));
memcpy(
mptID.data() + sizeof(sequence),
account.data(),
sizeof(account));
MPTIssue issue{mptID};
asset_ = issue;
}
else
{
Issue issue;
issue.currency = currencyOrAccount;
issue.account = account;
if (!isConsistent(issue))
Throw<std::runtime_error>(
"invalid issue: currency and account native mismatch");
asset_ = issue;
}
}
}

SerializedTypeID
Expand All @@ -65,17 +86,39 @@ STIssue::getSType() const
return STI_ISSUE;
}

std::string
STIssue::getText() const
{
return asset_.getText();
}

Json::Value STIssue::getJson(JsonOptions) const
{
return to_json(issue_);
Json::Value jv;
asset_.setJson(jv);
return jv;
}

void
STIssue::add(Serializer& s) const
{
s.addBitString(issue_.currency);
if (!isXRP(issue_.currency))
s.addBitString(issue_.account);
if (holds<Issue>())
{
s.addBitString(asset_.get<Issue>().currency);
if (!isXRP(asset_.get<Issue>().currency))
s.addBitString(asset_.get<Issue>().account);
}
else
{
s.addBitString(asset_.get<MPTIssue>().getIssuer());
s.addBitString(noAccount());
std::uint32_t sequence;
memcpy(
&sequence,
asset_.get<MPTIssue>().getMptID().data(),
sizeof(sequence));
s.add32(sequence);
}
}

bool
Expand All @@ -88,7 +131,7 @@ STIssue::isEquivalent(const STBase& t) const
bool
STIssue::isDefault() const
{
return issue_ == xrpIssue();
return holds<Issue>() && asset_.get<Issue>() == xrpIssue();
}

STBase*
Expand Down
4 changes: 2 additions & 2 deletions src/xrpld/app/ledger/OrderBookDB.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -129,8 +129,8 @@ OrderBookDB::update(std::shared_ptr<ReadView const> const& ledger)
}
else if (sle->getType() == ltAMM)
{
auto const issue1 = (*sle)[sfAsset];
auto const issue2 = (*sle)[sfAsset2];
auto const issue1 = (*sle)[sfAsset].get<Issue>();
auto const issue2 = (*sle)[sfAsset2].get<Issue>();
auto addBook = [&](Issue const& in, Issue const& out) {
allBooks[in].insert(out);

Expand Down
Loading

0 comments on commit c0ed04b

Please sign in to comment.