diff --git a/include/xrpl/basics/base_uint.h b/include/xrpl/basics/base_uint.h index 2bb74791444..0518ee37ea5 100644 --- a/include/xrpl/basics/base_uint.h +++ b/include/xrpl/basics/base_uint.h @@ -634,6 +634,7 @@ operator<<(std::ostream& out, base_uint<Bits, Tag> const& u) #ifndef __INTELLISENSE__ static_assert(sizeof(uint128) == 128 / 8, "There should be no padding bytes"); static_assert(sizeof(uint160) == 160 / 8, "There should be no padding bytes"); +static_assert(sizeof(uint192) == 192 / 8, "There should be no padding bytes"); static_assert(sizeof(uint256) == 256 / 8, "There should be no padding bytes"); #endif diff --git a/include/xrpl/protocol/Indexes.h b/include/xrpl/protocol/Indexes.h index 0f6e78d9cee..64328ce5f52 100644 --- a/include/xrpl/protocol/Indexes.h +++ b/include/xrpl/protocol/Indexes.h @@ -290,10 +290,7 @@ Keylet mptIssuance(AccountID const& issuer, std::uint32_t seq) noexcept; Keylet -mptIssuance(uint192 const& mpt) noexcept; - -Keylet -mptIssuance(ripple::MPT const& mpt) noexcept; +mptIssuance(MPTID const& mpt) noexcept; inline Keylet mptIssuance(uint256 const& issuance) @@ -302,10 +299,7 @@ mptIssuance(uint256 const& issuance) } Keylet -mptoken(MPT const& issuanceID, AccountID const& holder) noexcept; - -Keylet -mptoken(uint192 const& issuanceID, AccountID const& holder) noexcept; +mptoken(MPTID const& issuanceID, AccountID const& holder) noexcept; inline Keylet mptoken(uint256 const& mptokenKey) @@ -336,7 +330,7 @@ getTicketIndex(AccountID const& account, std::uint32_t uSequence); uint256 getTicketIndex(AccountID const& account, SeqProxy ticketSeq); -uint192 +MPTID getMptID(AccountID const& account, std::uint32_t sequence); } // namespace ripple diff --git a/include/xrpl/protocol/MPTIssue.h b/include/xrpl/protocol/MPTIssue.h index 6c01baccf08..7bc34adcf53 100644 --- a/include/xrpl/protocol/MPTIssue.h +++ b/include/xrpl/protocol/MPTIssue.h @@ -28,25 +28,17 @@ namespace ripple { class MPTIssue { private: - MPT mpt_; + MPTID mptID_; public: MPTIssue() = default; - MPTIssue(MPT const& mpt); + MPTIssue(MPTID const& id); - MPTIssue(uint192 const& id); - - AccountID const& + AccountID getIssuer() const; - MPT const& - mpt() const; - - MPT& - mpt(); - - uint192 + MPTID const& getMptID() const; friend constexpr bool @@ -59,27 +51,17 @@ class MPTIssue constexpr bool operator==(MPTIssue const& lhs, MPTIssue const& rhs) { - return lhs.mpt_ == rhs.mpt_; + return lhs.mptID_ == rhs.mptID_; } constexpr bool operator!=(MPTIssue const& lhs, MPTIssue const& rhs) { - return !(lhs.mpt_ == rhs.mpt_); -} - -MPT -getMPT(uint192 const&); - -inline MPT -badMPT() -{ - static MPT mpt{0, AccountID{0}}; - return mpt; + return !(lhs.mptID_ == rhs.mptID_); } inline bool -isXRP(uint192 const&) +isXRP(MPTID const&) { return false; } diff --git a/include/xrpl/protocol/SField.h b/include/xrpl/protocol/SField.h index 4d977060dba..ae7d38627ec 100644 --- a/include/xrpl/protocol/SField.h +++ b/include/xrpl/protocol/SField.h @@ -43,6 +43,7 @@ Some fields have a different meaning for their // Forwards class STAccount; class STEitherAmount; +class STAmount; class STIssue; class STBlob; template <int> @@ -56,44 +57,49 @@ class STCurrency; #pragma push_macro("XMACRO") #undef XMACRO -#define XMACRO(STYPE) \ - /* special types */ \ - STYPE(STI_UNKNOWN, -2) \ - STYPE(STI_NOTPRESENT, 0) \ - STYPE(STI_UINT16, 1) \ - \ - /* types (common) */ \ - STYPE(STI_UINT32, 2) \ - STYPE(STI_UINT64, 3) \ - STYPE(STI_UINT128, 4) \ - STYPE(STI_UINT256, 5) \ - STYPE(STI_AMOUNT, 6) \ - STYPE(STI_EITHER_AMOUNT, 6) \ - STYPE(STI_VL, 7) \ - STYPE(STI_ACCOUNT, 8) \ - \ - /* 9-13 are reserved */ \ - STYPE(STI_OBJECT, 14) \ - STYPE(STI_ARRAY, 15) \ - \ - /* types (uncommon) */ \ - STYPE(STI_UINT8, 16) \ - STYPE(STI_UINT160, 17) \ - STYPE(STI_PATHSET, 18) \ - STYPE(STI_VECTOR256, 19) \ - STYPE(STI_UINT96, 20) \ - STYPE(STI_UINT192, 21) \ - STYPE(STI_UINT384, 22) \ - STYPE(STI_UINT512, 23) \ - STYPE(STI_ISSUE, 24) \ - STYPE(STI_XCHAIN_BRIDGE, 25) \ - STYPE(STI_CURRENCY, 26) \ - \ - /* high-level types */ \ - /* cannot be serialized inside other types */ \ - STYPE(STI_TRANSACTION, 10001) \ - STYPE(STI_LEDGERENTRY, 10002) \ - STYPE(STI_VALIDATION, 10003) \ +#define XMACRO(STYPE) \ + /* special types */ \ + STYPE(STI_UNKNOWN, -2) \ + STYPE(STI_NOTPRESENT, 0) \ + STYPE(STI_UINT16, 1) \ + \ + /* types (common) */ \ + STYPE(STI_UINT32, 2) \ + STYPE(STI_UINT64, 3) \ + STYPE(STI_UINT128, 4) \ + STYPE(STI_UINT256, 5) \ + /* Need two enumerators with the same value */ \ + /* so that SF_AMOUNT and SF_EITHER_AMOUNT */ \ + /* map to the same serialization id. */ \ + /* This is an artifact of */ \ + /* CONSTRUCT_TYPED_SFIELD */ \ + STYPE(STI_AMOUNT, 6) \ + STYPE(STI_EITHER_AMOUNT, 6) \ + STYPE(STI_VL, 7) \ + STYPE(STI_ACCOUNT, 8) \ + \ + /* 9-13 are reserved */ \ + STYPE(STI_OBJECT, 14) \ + STYPE(STI_ARRAY, 15) \ + \ + /* types (uncommon) */ \ + STYPE(STI_UINT8, 16) \ + STYPE(STI_UINT160, 17) \ + STYPE(STI_PATHSET, 18) \ + STYPE(STI_VECTOR256, 19) \ + STYPE(STI_UINT96, 20) \ + STYPE(STI_UINT192, 21) \ + STYPE(STI_UINT384, 22) \ + STYPE(STI_UINT512, 23) \ + STYPE(STI_ISSUE, 24) \ + STYPE(STI_XCHAIN_BRIDGE, 25) \ + STYPE(STI_CURRENCY, 26) \ + \ + /* high-level types */ \ + /* cannot be serialized inside other types */ \ + STYPE(STI_TRANSACTION, 10001) \ + STYPE(STI_LEDGERENTRY, 10002) \ + STYPE(STI_VALIDATION, 10003) \ STYPE(STI_METADATA, 10004) #pragma push_macro("TO_ENUM") @@ -302,8 +308,6 @@ class SField static std::map<int, SField const*> knownCodeToField; }; -enum class SFieldMPT { None, Yes, No }; - /** A field with a type known at compile time. */ template <class T> struct TypedField : SField @@ -325,38 +329,49 @@ struct OptionaledField } }; -template <class T> -inline OptionaledField<T> -operator~(TypedField<T> const& f) -{ - return OptionaledField<T>(f); -} - -// Amount fields - -/** A field with a type known at compile time. */ -template <SFieldMPT> -struct TypedFieldAmount : public TypedField<STEitherAmount> +/** A field representing a variant with a type known at compile time. + * First template parameter is the variant type, the second + * template parameter is one of its alternative types. A variant field + * enables STObject::operator[]() overload to return the specified + * alternative type. For instance, STEitherAmount is a variant of STAmount + * and STMPTAmount. Some Amount fields, like SFee, don't support MPT + * and are declared as TypedVariantField<STEitherAmount, STAmount>. + * Conversely, sfAmount field supports MPT and is declared as + * TypedVariantField<STEitherAmount>. Then tx[sfFee] always returns STAmount, + * while tx[sfAmount] returns STEitherAmount and the caller has to get + * the specific type that STEitherAmount holds. + */ +template <class T, class H = T> +struct TypedVariantField : TypedField<T> { template <class... Args> - explicit TypedFieldAmount(private_access_tag_t pat, Args&&... args); + explicit TypedVariantField( + SField::private_access_tag_t pat, + Args&&... args); }; -/** Indicate std::optional field semantics. */ -template <SFieldMPT M> -struct OptionaledFieldAmount : public OptionaledField<STEitherAmount> +/** Indicate std::optional variant field semantics. */ +template <class T, class H = T> +struct OptionaledVariantField : OptionaledField<T> { - explicit OptionaledFieldAmount(TypedFieldAmount<M> const& f_) - : OptionaledField<STEitherAmount>(f_) + explicit OptionaledVariantField(TypedVariantField<T, H> const& f_) + : OptionaledField<T>(f_) { } }; -template <SFieldMPT M> -inline OptionaledFieldAmount<M> -operator~(TypedFieldAmount<M> const& f) +template <class T> +inline OptionaledField<T> +operator~(TypedField<T> const& f) +{ + return OptionaledField<T>(f); +} + +template <class T, class H = T> +inline OptionaledVariantField<T, H> +operator~(TypedVariantField<T, H> const& f) { - return OptionaledFieldAmount<M>(f); + return OptionaledVariantField<T, H>(f); } //------------------------------------------------------------------------------ @@ -376,8 +391,8 @@ using SF_UINT384 = TypedField<STBitString<384>>; using SF_UINT512 = TypedField<STBitString<512>>; using SF_ACCOUNT = TypedField<STAccount>; -using SF_AMOUNT = TypedFieldAmount<SFieldMPT::No>; -using SF_EITHER_AMOUNT = TypedFieldAmount<SFieldMPT::Yes>; +using SF_AMOUNT = TypedVariantField<STEitherAmount, STAmount>; +using SF_EITHER_AMOUNT = TypedVariantField<STEitherAmount>; using SF_ISSUE = TypedField<STIssue>; using SF_CURRENCY = TypedField<STCurrency>; using SF_VL = TypedField<STBlob>; diff --git a/include/xrpl/protocol/SOTemplate.h b/include/xrpl/protocol/SOTemplate.h index 56a0d471150..f6c231d1310 100644 --- a/include/xrpl/protocol/SOTemplate.h +++ b/include/xrpl/protocol/SOTemplate.h @@ -73,13 +73,15 @@ class SOElement { init(fieldName); } - SOElement(TypedFieldAmount<SFieldMPT::No> const& fieldName, SOEStyle style) + SOElement( + TypedVariantField<STEitherAmount, STAmount> const& fieldName, + SOEStyle style) : sField_(fieldName), style_(style), supportMpt_(soeMPTNotSupported) { init(fieldName); } SOElement( - TypedFieldAmount<SFieldMPT::Yes> const& fieldName, + TypedVariantField<STEitherAmount> const& fieldName, SOEStyle style, SOETxMPTAmount supportMpt = soeMPTNotSupported) : sField_(fieldName), style_(style), supportMpt_(supportMpt) diff --git a/include/xrpl/protocol/STAmount.h b/include/xrpl/protocol/STAmount.h index 63738966b95..6cd5cc7a557 100644 --- a/include/xrpl/protocol/STAmount.h +++ b/include/xrpl/protocol/STAmount.h @@ -32,10 +32,6 @@ namespace ripple { -struct int64_tag_t -{ -}; - // Internal form: // 1: If amount is zero, then value is zero and offset is -100 // 2: Otherwise: @@ -102,8 +98,6 @@ class STAmount final bool native, bool negative); - STAmount(std::int64_t mantissa, int64_tag_t); - explicit STAmount(std::uint64_t mantissa = 0, bool negative = false); STAmount( diff --git a/include/xrpl/protocol/STEitherAmount.h b/include/xrpl/protocol/STEitherAmount.h index c2c8172cb9b..d4b5756451f 100644 --- a/include/xrpl/protocol/STEitherAmount.h +++ b/include/xrpl/protocol/STEitherAmount.h @@ -29,11 +29,6 @@ template <typename TAmnt> concept ValidAmountType = std::is_same_v<TAmnt, STAmount> || std::is_same_v<TAmnt, STMPTAmount>; -// Currency or MPT issuance ID -template <typename T> -concept ValidAssetType = - std::is_same_v<T, Currency> || std::is_same_v<T, uint192>; - template <typename T> concept EitherAmountType = std::is_same_v<T, STEitherAmount> || std::is_same_v<T, std::optional<STEitherAmount>>; @@ -100,7 +95,7 @@ class STEitherAmount : public STBase, public CountedObject<STEitherAmount> std::variant<STAmount, STMPTAmount>& getValue(); - AccountID const& + AccountID getIssuer() const; bool diff --git a/include/xrpl/protocol/STMPTAmount.h b/include/xrpl/protocol/STMPTAmount.h index 02ea3837d33..8e467b6453b 100644 --- a/include/xrpl/protocol/STMPTAmount.h +++ b/include/xrpl/protocol/STMPTAmount.h @@ -66,13 +66,13 @@ class STMPTAmount final : public MPTAmount bool isDefault() const; - AccountID const& + AccountID getIssuer() const; MPTIssue const& issue() const; - uint192 + MPTID const& getCurrency() const; void diff --git a/include/xrpl/protocol/STObject.h b/include/xrpl/protocol/STObject.h index 26cdf5a55ea..4d2b061f88a 100644 --- a/include/xrpl/protocol/STObject.h +++ b/include/xrpl/protocol/STObject.h @@ -54,15 +54,12 @@ throwFieldNotFound(SField const& field) class STObject : public STBase, public CountedObject<STObject> { - template <typename T, SFieldMPT M> - using ValueType = std::conditional<M == SFieldMPT::No, STAmount, T>::type; - // Proxy value for a STBase derived class - template <class T, SFieldMPT = SFieldMPT::None> + template <class T, class H = T> class Proxy; - template <class T, SFieldMPT = SFieldMPT::None> + template <class T, class H = T> class ValueProxy; - template <class T, SFieldMPT = SFieldMPT::None> + template <class T, class H = T> class OptionalProxy; struct Transform @@ -240,11 +237,10 @@ class STObject : public STBase, public CountedObject<STObject> Blob getFieldVL(SField const& field) const; STEitherAmount const& - getFieldEitherAmount(SField const& field) const; - STEitherAmount const& getFieldAmount(SField const& field) const; STAmount const& - getFieldAmount(TypedFieldAmount<SFieldMPT::No> const& field) const; + getFieldAmount( + TypedVariantField<STEitherAmount, STAmount> const& field) const; STPathSet const& getFieldPathSet(SField const& field) const; const STVector256& @@ -265,11 +261,11 @@ class STObject : public STBase, public CountedObject<STObject> typename T::value_type operator[](TypedField<T> const& f) const; - /** Overload for amount fields + /** Overload for amount field */ - template <SFieldMPT M> - typename ValueType<STEitherAmount, M>::value_type - operator[](TypedFieldAmount<M> const& f) const; + template <class T, class H = T> + H::value_type + operator[](TypedVariantField<T, H> const& f) const; /** Get the value of a field as a std::optional @@ -283,12 +279,11 @@ class STObject : public STBase, public CountedObject<STObject> std::optional<std::decay_t<typename T::value_type>> operator[](OptionaledField<T> const& of) const; - /** Overload for amount fields + /** Overload for a variant field */ - template <SFieldMPT M> - std::optional< - std::decay_t<typename ValueType<STEitherAmount, M>::value_type>> - operator[](OptionaledFieldAmount<M> const& of) const; + template <class T, class H> + std::optional<std::decay_t<typename H::value_type>> + operator[](OptionaledVariantField<T, H> const& of) const; /** Get a modifiable field value. @param A TypedField built from an SField value representing the desired @@ -301,11 +296,11 @@ class STObject : public STBase, public CountedObject<STObject> ValueProxy<T> operator[](TypedField<T> const& f); - /** Overload for amount fields + /** Overload for a variant field */ - template <SFieldMPT M> - ValueProxy<STEitherAmount, M> - operator[](TypedFieldAmount<M> const& f); + template <class T, class H = T> + ValueProxy<T, H> + operator[](TypedVariantField<T, H> const& f); /** Return a modifiable field value as std::optional @@ -320,11 +315,11 @@ class STObject : public STBase, public CountedObject<STObject> OptionalProxy<T> operator[](OptionaledField<T> const& of); - /** Overload for amount fields + /** Overload for a variant field */ - template <SFieldMPT M> - OptionalProxy<STEitherAmount, M> - operator[](OptionaledFieldAmount<M> const& of); + template <class T, class H = T> + OptionalProxy<T, H> + operator[](OptionaledVariantField<T, H> const& of); /** Get the value of a field. @param A TypedField built from an SField value representing the desired @@ -337,11 +332,11 @@ class STObject : public STBase, public CountedObject<STObject> typename T::value_type at(TypedField<T> const& f) const; - /** Overload for amount fields + /** Overload for a variant field */ - template <SFieldMPT M> - typename ValueType<STEitherAmount, M>::value_type - at(TypedFieldAmount<M> const& f) const; + template <class T, class H = T> + H::value_type + at(TypedVariantField<T, H> const& f) const; /** Get the value of a field as std::optional @@ -355,12 +350,11 @@ class STObject : public STBase, public CountedObject<STObject> std::optional<std::decay_t<typename T::value_type>> at(OptionaledField<T> const& of) const; - /** Overload for amount fields + /** Overload for a variant field */ - template <SFieldMPT M> - std::optional< - std::decay_t<typename ValueType<STEitherAmount, M>::value_type>> - at(OptionaledFieldAmount<M> const& of) const; + template <class T, class H = T> + std::optional<std::decay_t<typename H::value_type>> + at(OptionaledVariantField<T, H> const& of) const; /** Get a modifiable field value. @param A TypedField built from an SField value representing the desired @@ -373,11 +367,11 @@ class STObject : public STBase, public CountedObject<STObject> ValueProxy<T> at(TypedField<T> const& f); - /** Overload for amount fields that don't support MPT + /** Overload for a variant field */ - template <SFieldMPT M> - ValueProxy<STEitherAmount, M> - at(TypedFieldAmount<M> const& f); + template <class T, class H = T> + ValueProxy<T, H> + at(TypedVariantField<T, H> const& f); /** Return a modifiable field value as std::optional @@ -392,11 +386,11 @@ class STObject : public STBase, public CountedObject<STObject> OptionalProxy<T> at(OptionaledField<T> const& of); - /** Overload for amount fields that don't support MPT + /** Overload for a variant field */ - template <SFieldMPT M> - OptionalProxy<STEitherAmount, M> - at(OptionaledFieldAmount<M> const& of); + template <class T, class H = T> + OptionalProxy<T, H> + at(OptionaledVariantField<T, H> const& of); /** Set a field. if the field already exists, it is replaced. @@ -541,11 +535,11 @@ class STObject : public STBase, public CountedObject<STObject> //------------------------------------------------------------------------------ -template <class T, SFieldMPT M> +template <class T, class H> class STObject::Proxy { protected: - using value_type = ValueType<T, M>::value_type; + using value_type = H::value_type; STObject* st_; SOEStyle style_; @@ -566,11 +560,11 @@ class STObject::Proxy assign(U&& u); }; -template <class T, SFieldMPT M> -class STObject::ValueProxy : private Proxy<T, M> +template <class T, class H> +class STObject::ValueProxy : private Proxy<T, H> { private: - using value_type = ValueType<T, M>::value_type; + using value_type = H::value_type; public: ValueProxy(ValueProxy const&) = default; @@ -589,11 +583,11 @@ class STObject::ValueProxy : private Proxy<T, M> ValueProxy(STObject* st, TypedField<T> const* f); }; -template <class T, SFieldMPT M> -class STObject::OptionalProxy : private Proxy<T, M> +template <class T, class H> +class STObject::OptionalProxy : private Proxy<T, H> { private: - using value_type = ValueType<T, M>::value_type; + using value_type = H::value_type; using optional_type = std::optional<typename std::decay<value_type>::type>; @@ -725,8 +719,8 @@ class STObject::FieldErr : public std::runtime_error using std::runtime_error::runtime_error; }; -template <class T, SFieldMPT M> -STObject::Proxy<T, M>::Proxy(STObject* st, TypedField<T> const* f) +template <class T, class H> +STObject::Proxy<T, H>::Proxy(STObject* st, TypedField<T> const* f) : st_(st), f_(f) { if (st_->mType) @@ -743,32 +737,18 @@ STObject::Proxy<T, M>::Proxy(STObject* st, TypedField<T> const* f) } } -template <class T, SFieldMPT M> +template <class T, class H> auto -STObject::Proxy<T, M>::value() const -> value_type +STObject::Proxy<T, H>::value() const -> value_type { auto const t = find(); if (t) - return t->value(); - if (style_ == soeINVALID) { - Throw<STObject::FieldErr>("Value requested from invalid STObject."); - } - if (style_ != soeDEFAULT) - { - Throw<STObject::FieldErr>( - "Missing field '" + this->f_->getName() + "'"); + if constexpr (std::is_same_v<T, H>) + return t->value(); + else + return get<H>(t->value()); } - return value_type{}; -} - -template <> -inline auto -STObject::Proxy<STEitherAmount, SFieldMPT::No>::value() const -> STAmount -{ - auto const t = find(); - if (t) - return get<STAmount>(t->value()); if (style_ == soeINVALID) { Throw<STObject::FieldErr>("Value requested from invalid STObject."); @@ -778,20 +758,20 @@ STObject::Proxy<STEitherAmount, SFieldMPT::No>::value() const -> STAmount Throw<STObject::FieldErr>( "Missing field '" + this->f_->getName() + "'"); } - return STAmount{}; + return value_type{}; } -template <class T, SFieldMPT M> +template <class T, class H> inline T const* -STObject::Proxy<T, M>::find() const +STObject::Proxy<T, H>::find() const { return dynamic_cast<T const*>(st_->peekAtPField(*f_)); } -template <class T, SFieldMPT M> +template <class T, class H> template <class U> void -STObject::Proxy<T, M>::assign(U&& u) +STObject::Proxy<T, H>::assign(U&& u) { if (style_ == soeDEFAULT && u == value_type{}) { @@ -809,68 +789,68 @@ STObject::Proxy<T, M>::assign(U&& u) //------------------------------------------------------------------------------ -template <class T, SFieldMPT M> +template <class T, class H> template <class U> -std::enable_if_t<std::is_assignable_v<T, U>, STObject::ValueProxy<T, M>&> -STObject::ValueProxy<T, M>::operator=(U&& u) +std::enable_if_t<std::is_assignable_v<T, U>, STObject::ValueProxy<T, H>&> +STObject::ValueProxy<T, H>::operator=(U&& u) { this->assign(std::forward<U>(u)); return *this; } -template <class T, SFieldMPT M> -STObject::ValueProxy<T, M>::operator value_type() const +template <class T, class H> +STObject::ValueProxy<T, H>::operator value_type() const { return this->value(); } -template <class T, SFieldMPT M> -STObject::ValueProxy<T, M>::ValueProxy(STObject* st, TypedField<T> const* f) - : Proxy<T, M>(st, f) +template <class T, class H> +STObject::ValueProxy<T, H>::ValueProxy(STObject* st, TypedField<T> const* f) + : Proxy<T, H>(st, f) { } //------------------------------------------------------------------------------ -template <class T, SFieldMPT M> -STObject::OptionalProxy<T, M>::operator bool() const noexcept +template <class T, class H> +STObject::OptionalProxy<T, H>::operator bool() const noexcept { return engaged(); } -template <class T, SFieldMPT M> +template <class T, class H> auto -STObject::OptionalProxy<T, M>::operator*() const -> value_type +STObject::OptionalProxy<T, H>::operator*() const -> value_type { return this->value(); } -template <class T, SFieldMPT M> -STObject::OptionalProxy<T, M>::operator typename STObject::OptionalProxy<T, M>:: +template <class T, class H> +STObject::OptionalProxy<T, H>::operator typename STObject::OptionalProxy<T, H>:: optional_type() const { return optional_value(); } -template <class T, SFieldMPT M> -typename STObject::OptionalProxy<T, M>::optional_type -STObject::OptionalProxy<T, M>::operator~() const +template <class T, class H> +typename STObject::OptionalProxy<T, H>::optional_type +STObject::OptionalProxy<T, H>::operator~() const { return optional_value(); } -template <class T, SFieldMPT M> +template <class T, class H> auto -STObject::OptionalProxy<T, M>::operator=(std::nullopt_t const&) +STObject::OptionalProxy<T, H>::operator=(std::nullopt_t const&) -> OptionalProxy& { disengage(); return *this; } -template <class T, SFieldMPT M> +template <class T, class H> auto -STObject::OptionalProxy<T, M>::operator=(optional_type&& v) -> OptionalProxy& +STObject::OptionalProxy<T, H>::operator=(optional_type&& v) -> OptionalProxy& { if (v) this->assign(std::move(*v)); @@ -879,9 +859,9 @@ STObject::OptionalProxy<T, M>::operator=(optional_type&& v) -> OptionalProxy& return *this; } -template <class T, SFieldMPT M> +template <class T, class H> auto -STObject::OptionalProxy<T, M>::operator=(optional_type const& v) +STObject::OptionalProxy<T, H>::operator=(optional_type const& v) -> OptionalProxy& { if (v) @@ -891,33 +871,33 @@ STObject::OptionalProxy<T, M>::operator=(optional_type const& v) return *this; } -template <class T, SFieldMPT M> +template <class T, class H> template <class U> -std::enable_if_t<std::is_assignable_v<T, U>, STObject::OptionalProxy<T, M>&> -STObject::OptionalProxy<T, M>::operator=(U&& u) +std::enable_if_t<std::is_assignable_v<T, U>, STObject::OptionalProxy<T, H>&> +STObject::OptionalProxy<T, H>::operator=(U&& u) { this->assign(std::forward<U>(u)); return *this; } -template <class T, SFieldMPT M> -STObject::OptionalProxy<T, M>::OptionalProxy( +template <class T, class H> +STObject::OptionalProxy<T, H>::OptionalProxy( STObject* st, TypedField<T> const* f) - : Proxy<T, M>(st, f) + : Proxy<T, H>(st, f) { } -template <class T, SFieldMPT M> +template <class T, class H> bool -STObject::OptionalProxy<T, M>::engaged() const noexcept +STObject::OptionalProxy<T, H>::engaged() const noexcept { return this->style_ == soeDEFAULT || this->find() != nullptr; } -template <class T, SFieldMPT M> +template <class T, class H> void -STObject::OptionalProxy<T, M>::disengage() +STObject::OptionalProxy<T, H>::disengage() { if (this->style_ == soeREQUIRED || this->style_ == soeDEFAULT) Throw<STObject::FieldErr>( @@ -928,18 +908,18 @@ STObject::OptionalProxy<T, M>::disengage() this->st_->makeFieldAbsent(*this->f_); } -template <class T, SFieldMPT M> +template <class T, class H> auto -STObject::OptionalProxy<T, M>::optional_value() const -> optional_type +STObject::OptionalProxy<T, H>::optional_value() const -> optional_type { if (!engaged()) return std::nullopt; return this->value(); } -template <class T, SFieldMPT M> -typename STObject::OptionalProxy<T, M>::value_type -STObject::OptionalProxy<T, M>::value_or(value_type val) const +template <class T, class H> +typename STObject::OptionalProxy<T, H>::value_type +STObject::OptionalProxy<T, H>::value_or(value_type val) const { return engaged() ? this->value() : val; } @@ -1051,9 +1031,9 @@ STObject::operator[](TypedField<T> const& f) const return at(f); } -template <SFieldMPT M> -typename STObject::ValueType<STEitherAmount, M>::value_type -STObject::operator[](TypedFieldAmount<M> const& f) const +template <class T, class H> +inline H::value_type +STObject::operator[](TypedVariantField<T, H> const& f) const { return at(f); } @@ -1065,10 +1045,9 @@ STObject::operator[](OptionaledField<T> const& of) const return at(of); } -template <SFieldMPT M> -std::optional< - std::decay_t<typename STObject::ValueType<STEitherAmount, M>::value_type>> -STObject::operator[](OptionaledFieldAmount<M> const& of) const +template <class T, class H> +inline std::optional<std::decay_t<typename H::value_type>> +STObject::operator[](OptionaledVariantField<T, H> const& of) const { return at(of); } @@ -1080,10 +1059,9 @@ STObject::operator[](TypedField<T> const& f) -> ValueProxy<T> return at(f); } -template <SFieldMPT M> +template <class T, class H> inline auto -STObject::operator[](TypedFieldAmount<M> const& f) - -> ValueProxy<STEitherAmount, M> +STObject::operator[](TypedVariantField<T, H> const& f) -> ValueProxy<T, H> { return at(f); } @@ -1095,10 +1073,10 @@ STObject::operator[](OptionaledField<T> const& of) -> OptionalProxy<T> return at(of); } -template <SFieldMPT M> +template <class T, class H> inline auto -STObject::operator[](OptionaledFieldAmount<M> const& of) - -> OptionalProxy<STEitherAmount, M> +STObject::operator[](OptionaledVariantField<T, H> const& of) + -> OptionalProxy<T, H> { return at(of); } @@ -1137,14 +1115,14 @@ STObject::at(TypedField<T> const& f) const return atImpl(f); } -template <SFieldMPT M> -typename STObject::ValueType<STEitherAmount, M>::value_type -STObject::at(TypedFieldAmount<M> const& f) const +template <class T, class H> +inline H::value_type +STObject::at(TypedVariantField<T, H> const& f) const { - if constexpr (M == SFieldMPT::Yes) + if constexpr (std::is_same_v<T, H>) return atImpl(f); else - return get<STAmount>(atImpl(f)); + return get<H>(atImpl(f)); } template <class T> @@ -1174,15 +1152,14 @@ STObject::at(OptionaledField<T> const& of) const return atImpl(of); } -template <SFieldMPT M> -std::optional< - std::decay_t<typename STObject::ValueType<STEitherAmount, M>::value_type>> -STObject::at(OptionaledFieldAmount<M> const& of) const +template <class T, class H> +inline std::optional<std::decay_t<typename H::value_type>> +STObject::at(OptionaledVariantField<T, H> const& of) const { - if constexpr (M == SFieldMPT::Yes) + if constexpr (std::is_same_v<T, H>) return atImpl(of); else - return get<STAmount>(atImpl(of)); + return get<H>(atImpl(of)); } template <class T> @@ -1192,11 +1169,11 @@ STObject::at(TypedField<T> const& f) -> ValueProxy<T> return ValueProxy<T>(this, &f); } -template <SFieldMPT M> +template <class T, class H> inline auto -STObject::at(TypedFieldAmount<M> const& f) -> ValueProxy<STEitherAmount, M> +STObject::at(TypedVariantField<T, H> const& f) -> ValueProxy<T, H> { - return ValueProxy<STEitherAmount, M>(this, &f); + return ValueProxy<T, H>(this, &f); } template <class T> @@ -1206,12 +1183,11 @@ STObject::at(OptionaledField<T> const& of) -> OptionalProxy<T> return OptionalProxy<T>(this, of.f); } -template <SFieldMPT M> +template <class T, class H> inline auto -STObject::at(OptionaledFieldAmount<M> const& of) - -> OptionalProxy<STEitherAmount, M> +STObject::at(OptionaledVariantField<T, H> const& of) -> OptionalProxy<T, H> { - return OptionalProxy<STEitherAmount, M>(this, of.f); + return OptionalProxy<T, H>(this, of.f); } template <class Tag> diff --git a/include/xrpl/protocol/UintTypes.h b/include/xrpl/protocol/UintTypes.h index 8ccca8743ae..cf34366262f 100644 --- a/include/xrpl/protocol/UintTypes.h +++ b/include/xrpl/protocol/UintTypes.h @@ -58,8 +58,12 @@ using Currency = base_uint<160, detail::CurrencyTag>; /** NodeID is a 160-bit hash representing one node. */ using NodeID = base_uint<160, detail::NodeIDTag>; -/** MPT is a 192-bit hash representing MPTID. */ -using MPT = std::pair<std::uint32_t, AccountID>; +/** MPT is a 192-bit hash representing MPTID. + * Currently MPTID is the only 192-bit field. + * If other 192-bit fields with different semantics + * are added then MPTID must change to a unique tag. + */ +using MPTID = base_uint<192>; /** XRP currency. */ Currency const& @@ -70,7 +74,7 @@ Currency const& noCurrency(); /** A placeholder for empty MPTID. */ -MPT const& +MPTID const& noMPT(); /** We deliberately disallow the currency that looks like "XRP" because too diff --git a/src/libxrpl/protocol/Indexes.cpp b/src/libxrpl/protocol/Indexes.cpp index b402111972c..8014d8d4dcd 100644 --- a/src/libxrpl/protocol/Indexes.cpp +++ b/src/libxrpl/protocol/Indexes.cpp @@ -137,10 +137,10 @@ getTicketIndex(AccountID const& account, SeqProxy ticketSeq) return getTicketIndex(account, ticketSeq.value()); } -uint192 +MPTID getMptID(AccountID const& account, std::uint32_t sequence) { - uint192 u; + MPTID u; sequence = boost::endian::native_to_big(sequence); memcpy(u.data(), &sequence, sizeof(sequence)); memcpy(u.data() + sizeof(sequence), account.data(), sizeof(account)); @@ -470,31 +470,18 @@ mptIssuance(AccountID const& issuer, std::uint32_t seq) noexcept } Keylet -mptIssuance(ripple::MPT const& mpt) noexcept -{ - return mptIssuance(mpt.second, mpt.first); -} - -Keylet -mptIssuance(uint192 const& mpt) noexcept +mptIssuance(MPTID const& id) noexcept { return { - ltMPTOKEN_ISSUANCE, indexHash(LedgerNameSpace::MPTOKEN_ISSUANCE, mpt)}; + ltMPTOKEN_ISSUANCE, indexHash(LedgerNameSpace::MPTOKEN_ISSUANCE, id)}; } Keylet -mptoken(uint192 const& issuanceID, AccountID const& holder) noexcept +mptoken(MPTID const& issuanceID, AccountID const& holder) noexcept { return mptoken(mptIssuance(issuanceID).key, holder); } -Keylet -mptoken(MPT const& mptID, AccountID const& holder) noexcept -{ - return mptoken( - mptIssuance(getMptID(mptID.second, mptID.first)).key, holder); -} - Keylet mptoken(uint256 const& issuanceKey, AccountID const& holder) noexcept { diff --git a/src/libxrpl/protocol/MPTIssue.cpp b/src/libxrpl/protocol/MPTIssue.cpp index 4737f46a938..629f00be2d2 100644 --- a/src/libxrpl/protocol/MPTIssue.cpp +++ b/src/libxrpl/protocol/MPTIssue.cpp @@ -23,49 +23,27 @@ namespace ripple { -MPTIssue::MPTIssue(MPT const& mpt) : mpt_(mpt) +MPTIssue::MPTIssue(MPTID const& id) : mptID_(id) { } -MPTIssue::MPTIssue(uint192 const& id) -{ - mpt_ = getMPT(id); -} - -AccountID const& +AccountID MPTIssue::getIssuer() const { - return mpt_.second; -} - -MPT const& -MPTIssue::mpt() const -{ - return mpt_; -} + AccountID account; -MPT& -MPTIssue::mpt() -{ - return mpt_; + // copy from id skipping the sequence + memcpy( + account.data(), + mptID_.data() + sizeof(std::uint32_t), + sizeof(AccountID)); + return account; } -uint192 +MPTID const& MPTIssue::getMptID() const { - return ripple::getMptID(mpt_.second, mpt_.first); -} - -MPT -getMPT(uint192 const& id) -{ - std::uint32_t sequence; - AccountID account; - - memcpy(&sequence, id.data(), sizeof(sequence)); - sequence = boost::endian::big_to_native(sequence); - memcpy(account.data(), id.data() + sizeof(sequence), sizeof(AccountID)); - return std::make_pair(sequence, account); + return mptID_; } Json::Value diff --git a/src/libxrpl/protocol/SField.cpp b/src/libxrpl/protocol/SField.cpp index 38c2148c980..19b55607435 100644 --- a/src/libxrpl/protocol/SField.cpp +++ b/src/libxrpl/protocol/SField.cpp @@ -45,10 +45,12 @@ TypedField<T>::TypedField(private_access_tag_t pat, Args&&... args) { } -template <SFieldMPT M> +template <class T, class H> template <class... Args> -TypedFieldAmount<M>::TypedFieldAmount(private_access_tag_t pat, Args&&... args) - : TypedField<STEitherAmount>(pat, std::forward<Args>(args)...) +TypedVariantField<T, H>::TypedVariantField( + SField::private_access_tag_t pat, + Args&&... args) + : TypedField<T>(pat, std::forward<Args>(args)...) { } diff --git a/src/libxrpl/protocol/STAmount.cpp b/src/libxrpl/protocol/STAmount.cpp index c2eee78d462..99eb4b829c5 100644 --- a/src/libxrpl/protocol/STAmount.cpp +++ b/src/libxrpl/protocol/STAmount.cpp @@ -187,12 +187,6 @@ STAmount::STAmount( canonicalize(); } -STAmount::STAmount(std::int64_t mantissa, int64_tag_t) - : mOffset(0), mIsNative(true) -{ - set(mantissa); -} - //------------------------------------------------------------------------------ STAmount::STAmount(std::uint64_t mantissa, bool negative) @@ -351,7 +345,12 @@ operator+(STAmount const& v1, STAmount const& v2) } if (v1.native()) - return {getSNValue(v1) + getSNValue(v2), int64_tag_t{}}; + { + auto const res = getSNValue(v1) + getSNValue(v2); + auto const negative = res < 0; + return STAmount{ + static_cast<std::uint64_t>(negative ? -res : res), negative}; + } if (getSTNumberSwitchover()) { diff --git a/src/libxrpl/protocol/STEitherAmount.cpp b/src/libxrpl/protocol/STEitherAmount.cpp index 74eebcff487..2fc4d3f00de 100644 --- a/src/libxrpl/protocol/STEitherAmount.cpp +++ b/src/libxrpl/protocol/STEitherAmount.cpp @@ -183,7 +183,7 @@ STEitherAmount::getValue() return amount_; } -AccountID const& +AccountID STEitherAmount::getIssuer() const { if (isIssue()) @@ -297,7 +297,7 @@ amountFromJson(SField const& name, Json::Value const& v) if (isMPT) { // sequence (32 bits) + account (160 bits) - uint192 u; + MPTID u; if (!u.parseHex(currencyOrMPTID.asString())) Throw<std::runtime_error>("invalid MPTokenIssuanceID"); issue = u; diff --git a/src/libxrpl/protocol/STMPTAmount.cpp b/src/libxrpl/protocol/STMPTAmount.cpp index 554e3d7c713..c4e40e3ce36 100644 --- a/src/libxrpl/protocol/STMPTAmount.cpp +++ b/src/libxrpl/protocol/STMPTAmount.cpp @@ -111,16 +111,16 @@ STMPTAmount::add(Serializer& s) const bool STMPTAmount::isDefault() const { - return value_ == 0 && issue_ == badMPT(); + return value_ == 0 && issue_ == noMPT(); } -AccountID const& +AccountID STMPTAmount::getIssuer() const { return issue_.getIssuer(); } -uint192 +MPTID const& STMPTAmount::getCurrency() const { return issue_.getMptID(); diff --git a/src/libxrpl/protocol/STObject.cpp b/src/libxrpl/protocol/STObject.cpp index ec23b16793d..ccd34d16d33 100644 --- a/src/libxrpl/protocol/STObject.cpp +++ b/src/libxrpl/protocol/STObject.cpp @@ -630,13 +630,6 @@ STObject::getFieldVL(SField const& field) const return Blob(b.data(), b.data() + b.size()); } -STEitherAmount const& -STObject::getFieldEitherAmount(SField const& field) const -{ - static STEitherAmount const empty{}; - return getFieldByConstRef<STEitherAmount>(field, empty); -} - STEitherAmount const& STObject::getFieldAmount(SField const& field) const { @@ -645,7 +638,8 @@ STObject::getFieldAmount(SField const& field) const } STAmount const& -STObject::getFieldAmount(TypedFieldAmount<SFieldMPT::No> const& field) const +STObject::getFieldAmount( + TypedVariantField<STEitherAmount, STAmount> const& field) const { static STEitherAmount const empty{}; return get<STAmount>(getFieldByConstRef<STEitherAmount>(field, empty)); diff --git a/src/libxrpl/protocol/UintTypes.cpp b/src/libxrpl/protocol/UintTypes.cpp index 9487e5dcbf7..e50e52c1c30 100644 --- a/src/libxrpl/protocol/UintTypes.cpp +++ b/src/libxrpl/protocol/UintTypes.cpp @@ -18,6 +18,7 @@ //============================================================================== #include <xrpl/beast/utility/Zero.h> +#include <xrpl/protocol/Indexes.h> #include <xrpl/protocol/Serializer.h> #include <xrpl/protocol/SystemParameters.h> #include <xrpl/protocol/UintTypes.h> @@ -125,11 +126,11 @@ noCurrency() return currency; } -MPT const& +MPTID const& noMPT() { - static MPT const mpt{0, noAccount()}; - return mpt; + static MPTID const id = getMptID(noAccount(), 0); + return id; } Currency const& diff --git a/src/test/app/MPToken_test.cpp b/src/test/app/MPToken_test.cpp index e23352cafa0..757e9e9db60 100644 --- a/src/test/app/MPToken_test.cpp +++ b/src/test/app/MPToken_test.cpp @@ -824,8 +824,7 @@ class MPToken_test : public beast::unit_test::suite { Env env{*this, features}; env.fund(XRP(1'000), alice, bob); - STMPTAmount mpt{ - MPTIssue{std::make_pair(1, alice.id())}, UINT64_C(100)}; + STMPTAmount mpt{MPTIssue{getMptID(alice.id(), 1)}, UINT64_C(100)}; Json::Value jv; jv[jss::secret] = alice.name(); jv[jss::tx_json] = pay(alice, bob, mpt); @@ -904,8 +903,7 @@ class MPToken_test : public beast::unit_test::suite env.fund(XRP(1'000), alice); env.fund(XRP(1'000), bob); - STMPTAmount mpt{ - MPTIssue{std::make_pair(1, alice.id())}, UINT64_C(100)}; + STMPTAmount mpt{MPTIssue{getMptID(alice.id(), 1)}, UINT64_C(100)}; env(pay(alice, bob, mpt), ter(temDISABLED)); } @@ -919,8 +917,7 @@ class MPToken_test : public beast::unit_test::suite env.fund(XRP(1'000), alice); env.fund(XRP(1'000), carol); - STMPTAmount mpt{ - MPTIssue{std::make_pair(1, alice.id())}, UINT64_C(100)}; + STMPTAmount mpt{MPTIssue{getMptID(alice.id(), 1)}, UINT64_C(100)}; Json::Value jv; jv[jss::secret] = alice.name(); @@ -1007,7 +1004,7 @@ class MPToken_test : public beast::unit_test::suite Account const alice("alice"); auto const USD = alice["USD"]; Account const carol("carol"); - MPTIssue issue(std::make_pair(1, alice.id())); + MPTIssue issue(getMptID(alice.id(), 1)); STMPTAmount mpt{issue, UINT64_C(100)}; auto const jvb = bridge(alice, USD, alice, USD); for (auto const& feature : {features, features - featureMPTokensV1}) @@ -1331,7 +1328,7 @@ class MPToken_test : public beast::unit_test::suite auto const USD = alice["USD"]; auto const mpt = ripple::test::jtx::MPT( - alice.name(), std::make_pair(env.seq(alice), alice.id())); + alice.name(), getMptID(alice.id(), env.seq(alice))); env(claw(alice, bob["USD"](5), bob), ter(temMALFORMED)); env.close(); @@ -1354,7 +1351,7 @@ class MPToken_test : public beast::unit_test::suite auto const USD = alice["USD"]; auto const mpt = ripple::test::jtx::MPT( - alice.name(), std::make_pair(env.seq(alice), alice.id())); + alice.name(), getMptID(alice.id(), env.seq(alice))); // clawing back IOU from a MPT holder fails env(claw(alice, bob["USD"](5), bob), ter(temMALFORMED)); @@ -1413,7 +1410,7 @@ class MPToken_test : public beast::unit_test::suite MPTTester mptAlice(env, alice, {.holders = {&bob}}); auto const fakeMpt = ripple::test::jtx::MPT( - alice.name(), std::make_pair(env.seq(alice), alice.id())); + alice.name(), getMptID(alice.id(), env.seq(alice))); // issuer tries to clawback MPT where issuance doesn't exist env(claw(alice, fakeMpt(5), bob), ter(tecOBJECT_NOT_FOUND)); @@ -1452,7 +1449,7 @@ class MPToken_test : public beast::unit_test::suite env.close(); auto const mpt = ripple::test::jtx::MPT( - alice.name(), std::make_pair(env.seq(alice), alice.id())); + alice.name(), getMptID(alice.id(), env.seq(alice))); Json::Value jv = claw(alice, mpt(1), bob); jv[jss::Amount][jss::value] = to_string(maxMPTokenAmount + 1); diff --git a/src/test/jtx/amount.h b/src/test/jtx/amount.h index 70a0bf51f34..fb5cef102ef 100644 --- a/src/test/jtx/amount.h +++ b/src/test/jtx/amount.h @@ -377,14 +377,14 @@ class MPT { public: std::string name; - ripple::MPT mptID; + ripple::MPTID mptID; - MPT(std::string const& n, ripple::MPT const& mptID_) + MPT(std::string const& n, ripple::MPTID const& mptID_) : name(n), mptID(mptID_) { } - ripple::MPT const& + ripple::MPTID const& mpt() const { return mptID; @@ -395,7 +395,7 @@ class MPT This allows passing an MPT value where an Issue is expected. */ - operator ripple::MPT() const + operator ripple::MPTID() const { return mpt(); } diff --git a/src/test/jtx/impl/mpt.cpp b/src/test/jtx/impl/mpt.cpp index 909154fb720..88f206796bf 100644 --- a/src/test/jtx/impl/mpt.cpp +++ b/src/test/jtx/impl/mpt.cpp @@ -94,8 +94,7 @@ MPTTester::create(const MPTCreate& arg) { if (issuanceKey_) Throw<std::runtime_error>("MPT can't be reused"); - mpt_ = std::make_pair(env_.seq(issuer_), issuer_.id()); - id_ = getMptID(issuer_.id(), mpt_->first); + id_ = getMptID(issuer_.id(), env_.seq(issuer_)); issuanceKey_ = keylet::mptIssuance(*id_).key; Json::Value jv; jv[sfAccount.jsonName] = issuer_.human(); @@ -119,7 +118,6 @@ MPTTester::create(const MPTCreate& arg) id_.reset(); issuanceKey_.reset(); - mpt_.reset(); } else if (arg.flags) env_.require(mptflags(*this, *arg.flags)); @@ -306,7 +304,7 @@ MPTTester::pay( std::int64_t amount, std::optional<TER> err) { - assert(mpt_); + assert(id_); auto const srcAmt = getAmount(src); auto const destAmt = getAmount(dest); auto const outstnAmt = getAmount(issuer_); @@ -331,7 +329,7 @@ MPTTester::pay( else { auto const actual = static_cast<std::int64_t>( - amount * Number{transferRate(*env_.current(), *mpt_).value, -9}); + amount * Number{transferRate(*env_.current(), *id_).value, -9}); // Sender pays the transfer fee if any env_.require(mptpay(*this, src, srcAmt - actual)); env_.require(mptpay(*this, dest, destAmt + amount)); @@ -347,7 +345,7 @@ MPTTester::claw( std::int64_t amount, std::optional<TER> err) { - assert(mpt_); + assert(id_); auto const issuerAmt = getAmount(issuer); auto const holderAmt = getAmount(holder); if (err) @@ -368,8 +366,8 @@ MPTTester::claw( STMPTAmount MPTTester::mpt(std::int64_t amount) const { - assert(mpt_); - return ripple::test::jtx::MPT(issuer_.name(), *mpt_)(amount); + assert(id_); + return ripple::test::jtx::MPT(issuer_.name(), *id_)(amount); } std::int64_t diff --git a/src/test/jtx/mpt.h b/src/test/jtx/mpt.h index e3ebb69d658..e96b73f039a 100644 --- a/src/test/jtx/mpt.h +++ b/src/test/jtx/mpt.h @@ -111,7 +111,7 @@ struct MPTCreate struct MPTDestroy { AccountP issuer = nullptr; - std::optional<uint192> id = std::nullopt; + std::optional<MPTID> id = std::nullopt; std::optional<std::uint32_t> ownerCount = std::nullopt; std::optional<std::uint32_t> holderCount = std::nullopt; std::optional<std::uint32_t> flags = std::nullopt; @@ -122,7 +122,7 @@ struct MPTAuthorize { AccountP account = nullptr; AccountP holder = nullptr; - std::optional<uint192> id = std::nullopt; + std::optional<MPTID> id = std::nullopt; std::optional<std::uint32_t> ownerCount = std::nullopt; std::optional<std::uint32_t> holderCount = std::nullopt; std::optional<std::uint32_t> flags = std::nullopt; @@ -133,7 +133,7 @@ struct MPTSet { AccountP account = nullptr; AccountP holder = nullptr; - std::optional<uint192> id = std::nullopt; + std::optional<MPTID> id = std::nullopt; std::optional<std::uint32_t> ownerCount = std::nullopt; std::optional<std::uint32_t> holderCount = std::nullopt; std::optional<std::uint32_t> flags = std::nullopt; @@ -145,9 +145,8 @@ class MPTTester Env& env_; Account const& issuer_; std::unordered_map<std::string, AccountP> const holders_; - std::optional<uint192> id_; + std::optional<MPTID> id_; std::optional<uint256> issuanceKey_; - std::optional<ripple::MPT> mpt_; bool close_; public: @@ -206,7 +205,7 @@ class MPTTester return *issuanceKey_; } - uint192 const& + MPTID const& issuanceID() const { assert(id_); diff --git a/src/xrpld/app/tx/detail/Clawback.cpp b/src/xrpld/app/tx/detail/Clawback.cpp index fa8f2a3843f..a6ca307bb3d 100644 --- a/src/xrpld/app/tx/detail/Clawback.cpp +++ b/src/xrpld/app/tx/detail/Clawback.cpp @@ -172,7 +172,7 @@ preclaimHelper<STMPTAmount>(PreclaimContext const& ctx) if (sleHolder->isFieldPresent(sfAMMID)) return tecAMM_ACCOUNT; - auto const issuanceKey = keylet::mptIssuance(clawAmount.issue().mpt()); + auto const issuanceKey = keylet::mptIssuance(clawAmount.issue().getMptID()); auto const sleIssuance = ctx.view.read(issuanceKey); if (!sleIssuance) return tecOBJECT_NOT_FOUND; diff --git a/src/xrpld/app/tx/detail/Payment.cpp b/src/xrpld/app/tx/detail/Payment.cpp index 6cc88a8107a..98ef572b548 100644 --- a/src/xrpld/app/tx/detail/Payment.cpp +++ b/src/xrpld/app/tx/detail/Payment.cpp @@ -268,7 +268,7 @@ preflightHelper<STMPTAmount>(PreflightContext const& ctx) << "bad dst amount: " << saDstAmount.getFullText(); return temBAD_AMOUNT; } - if (badMPT() == uDstCurrency) + if (noMPT() == uDstCurrency) { JLOG(j.trace()) << "Malformed transaction: " << "Bad asset."; diff --git a/src/xrpld/ledger/View.h b/src/xrpld/ledger/View.h index 3ee99713dcc..b413a775bea 100644 --- a/src/xrpld/ledger/View.h +++ b/src/xrpld/ledger/View.h @@ -235,7 +235,7 @@ forEachItemAfter( transferRate(ReadView const& view, AccountID const& issuer); [[nodiscard]] Rate -transferRate(ReadView const& view, MPT const& id); +transferRate(ReadView const& view, MPTID const& id); /** Returns `true` if the directory is empty @param key The key of the directory diff --git a/src/xrpld/ledger/detail/View.cpp b/src/xrpld/ledger/detail/View.cpp index f5303c3bb7e..22a8249758e 100644 --- a/src/xrpld/ledger/detail/View.cpp +++ b/src/xrpld/ledger/detail/View.cpp @@ -180,7 +180,7 @@ isGlobalFrozen(ReadView const& view, AccountID const& issuer) bool isGlobalFrozen(ReadView const& view, MPTIssue const& mpt) { - if (auto const sle = view.read(keylet::mptIssuance(mpt.mpt()))) + if (auto const sle = view.read(keylet::mptIssuance(mpt.getMptID()))) return sle->getFlags() & lsfMPTLocked; return false; } @@ -211,7 +211,7 @@ isIndividualFrozen( AccountID const& account, MPTIssue const& mpt) { - if (auto const sle = view.read(keylet::mptoken(mpt.mpt(), account))) + if (auto const sle = view.read(keylet::mptoken(mpt.getMptID(), account))) return sle->getFlags() & lsfMPTLocked; return false; } @@ -316,7 +316,7 @@ accountHolds( { STMPTAmount amount; - auto const sleMpt = view.read(keylet::mptoken(issue.mpt(), account)); + auto const sleMpt = view.read(keylet::mptoken(issue.getMptID(), account)); if (!sleMpt) amount.clear(issue); else if (zeroIfFrozen == fhZERO_IF_FROZEN && isFrozen(view, account, issue)) @@ -564,7 +564,7 @@ transferRate(ReadView const& view, AccountID const& issuer) } Rate -transferRate(ReadView const& view, MPT const& id) +transferRate(ReadView const& view, MPTID const& id) { auto const sle = view.read(keylet::mptIssuance(id)); @@ -1363,11 +1363,13 @@ rippleSend( } // Sending 3rd party MPTs: transit. - if (auto const sle = view.read(keylet::mptIssuance(saAmount.issue().mpt()))) + if (auto const sle = + view.read(keylet::mptIssuance(saAmount.issue().getMptID()))) { saActual = (waiveFee == WaiveTransferFee::Yes) ? saAmount - : multiply(saAmount, transferRate(view, saAmount.issue().mpt())); + : multiply( + saAmount, transferRate(view, saAmount.issue().getMptID())); JLOG(j.debug()) << "rippleSend> " << to_string(uSenderID) << " - > " << to_string(uReceiverID) @@ -1693,7 +1695,7 @@ requireAuth(ReadView const& view, Issue const& issue, AccountID const& account) TER requireAuth(ReadView const& view, MPTIssue const& mpt, AccountID const& account) { - auto const mptID = keylet::mptIssuance(mpt.mpt()); + auto const mptID = keylet::mptIssuance(mpt.getMptID()); if (auto const sle = view.read(mptID); sle && sle->getFieldU32(sfFlags) & lsfMPTRequireAuth) { @@ -1713,7 +1715,7 @@ canTransfer( AccountID const& from, AccountID const& to) { - auto const mptID = keylet::mptIssuance(mpt.mpt()); + auto const mptID = keylet::mptIssuance(mpt.getMptID()); if (auto const sle = view.read(mptID); sle && !(sle->getFieldU32(sfFlags) & lsfMPTCanTransfer)) { @@ -1856,7 +1858,7 @@ rippleCredit( STMPTAmount saAmount, beast::Journal j) { - auto const mptID = keylet::mptIssuance(saAmount.issue().mpt()); + auto const mptID = keylet::mptIssuance(saAmount.issue().getMptID()); auto const issuer = saAmount.getIssuer(); if (uSenderID == issuer) { diff --git a/src/xrpld/rpc/MPTokenIssuanceID.h b/src/xrpld/rpc/MPTokenIssuanceID.h index f7f45fded3b..4f94e61fa86 100644 --- a/src/xrpld/rpc/MPTokenIssuanceID.h +++ b/src/xrpld/rpc/MPTokenIssuanceID.h @@ -37,7 +37,7 @@ canHaveMPTokenIssuanceID( std::shared_ptr<STTx const> const& serializedTx, TxMeta const& transactionMeta); -std::optional<uint192> +std::optional<MPTID> getIDFromCreatedIssuance(TxMeta const& transactionMeta); void diff --git a/src/xrpld/rpc/detail/MPTokenIssuanceID.cpp b/src/xrpld/rpc/detail/MPTokenIssuanceID.cpp index 8de1e8f3344..c2aa3eea02a 100644 --- a/src/xrpld/rpc/detail/MPTokenIssuanceID.cpp +++ b/src/xrpld/rpc/detail/MPTokenIssuanceID.cpp @@ -47,7 +47,7 @@ canHaveMPTokenIssuanceID( return true; } -std::optional<uint192> +std::optional<MPTID> getIDFromCreatedIssuance(TxMeta const& transactionMeta) { for (STObject const& node : transactionMeta.getNodes()) @@ -74,7 +74,7 @@ insertMPTokenIssuanceID( if (!canHaveMPTokenIssuanceID(transaction, transactionMeta)) return; - std::optional<uint192> result = getIDFromCreatedIssuance(transactionMeta); + std::optional<MPTID> result = getIDFromCreatedIssuance(transactionMeta); if (result.has_value()) response[jss::mpt_issuance_id] = to_string(result.value()); } diff --git a/src/xrpld/rpc/handlers/LedgerEntry.cpp b/src/xrpld/rpc/handlers/LedgerEntry.cpp index 30b1113cd05..b8f5ffe104a 100644 --- a/src/xrpld/rpc/handlers/LedgerEntry.cpp +++ b/src/xrpld/rpc/handlers/LedgerEntry.cpp @@ -651,7 +651,7 @@ doLedgerEntry(RPC::JsonContext& context) context.params[jss::mpt_issuance]; if (unparsedMPTIssuanceID.isString()) { - uint192 mptIssuanceID; + MPTID mptIssuanceID; if (!mptIssuanceID.parseHex(unparsedMPTIssuanceID.asString())) { uNodeIndex = beast::zero; @@ -691,7 +691,7 @@ doLedgerEntry(RPC::JsonContext& context) context.params[jss::mptoken][jss::mpt_issuance_id] .asString(); - uint192 mptIssuanceID; + MPTID mptIssuanceID; if (!mptIssuanceID.parseHex(mptIssuanceIdStr)) Throw<std::runtime_error>( "Cannot parse mpt_issuance_id");