diff --git a/include/xrpl/protocol/LedgerFormats.h b/include/xrpl/protocol/LedgerFormats.h index e3efe8fec2..165d2c0c54 100644 --- a/include/xrpl/protocol/LedgerFormats.h +++ b/include/xrpl/protocol/LedgerFormats.h @@ -55,13 +55,33 @@ enum LedgerEntryType : std::uint16_t #pragma push_macro("LEDGER_ENTRY") #undef LEDGER_ENTRY +#pragma push_macro("LEDGER_ENTRY_FIELD") +#undef LEDGER_ENTRY_FIELD +#pragma push_macro("DEFINE_LEDGER_ENTRY_FIELDS") +#undef DEFINE_LEDGER_ENTRY_FIELDS +#pragma push_macro("LEDGER_ENTRIES_BEGIN") +#undef LEDGER_ENTRIES_BEGIN +#pragma push_macro("LEDGER_ENTRIES_END") +#undef LEDGER_ENTRIES_END +#define LEDGER_ENTRIES_BEGIN +#define LEDGER_ENTRIES_END +#define DEFINE_LEDGER_ENTRY_FIELDS(...) ({__VA_ARGS__}) +#define LEDGER_ENTRY_FIELD(...) {__VA_ARGS__}, #define LEDGER_ENTRY(tag, value, name, rpcName, fields) tag = value, #include #undef LEDGER_ENTRY #pragma pop_macro("LEDGER_ENTRY") +#undef LEDGER_ENTRY_FIELD +#pragma pop_macro("LEDGER_ENTRY_FIELD") +#undef DEFINE_LEDGER_ENTRY_FIELDS +#pragma pop_macro("DEFINE_LEDGER_ENTRY_FIELDS") +#undef LEDGER_ENTRIES_BEGIN +#pragma pop_macro("LEDGER_ENTRIES_BEGIN") +#undef LEDGER_ENTRIES_END +#pragma pop_macro("LEDGER_ENTRIES_END") //--------------------------------------------------------------------------- /** A special type, matching any ledger entry type. diff --git a/include/xrpl/protocol/SField.h b/include/xrpl/protocol/SField.h index 777cfa02ba..ff002f7cbf 100644 --- a/include/xrpl/protocol/SField.h +++ b/include/xrpl/protocol/SField.h @@ -368,11 +368,15 @@ using SF_XCHAIN_BRIDGE = TypedField; #undef UNTYPED_SFIELD #pragma push_macro("TYPED_SFIELD") #undef TYPED_SFIELD +#pragma push_macro("ARRAY_SFIELD") +#undef ARRAY_SFIELD #define UNTYPED_SFIELD(sfName, stiSuffix, fieldValue, ...) \ extern SField const sfName; #define TYPED_SFIELD(sfName, stiSuffix, fieldValue, ...) \ extern SF_##stiSuffix const sfName; +#define ARRAY_SFIELD(sfName, sfItemName, stiSuffix, fieldValue, ...) \ + UNTYPED_SFIELD(sfName, stiSuffix, fieldValue, __VA_ARGS__) extern SField const sfInvalid; extern SField const sfGeneric; @@ -383,6 +387,8 @@ extern SField const sfGeneric; #pragma pop_macro("TYPED_SFIELD") #undef UNTYPED_SFIELD #pragma pop_macro("UNTYPED_SFIELD") +#undef ARRAY_SFIELD +#pragma pop_macro("ARRAY_SFIELD") } // namespace ripple diff --git a/include/xrpl/protocol/TypedLedgerEntries.h b/include/xrpl/protocol/TypedLedgerEntries.h new file mode 100644 index 0000000000..7bda35659f --- /dev/null +++ b/include/xrpl/protocol/TypedLedgerEntries.h @@ -0,0 +1,812 @@ +//------------------------------------------------------------------------------ +/* + This file is part of rippled: https://github.com/ripple/rippled + Copyright (c) 2025 Ripple Labs Inc. + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef TYPED_LEDGER_ENTRIES_H +#define TYPED_LEDGER_ENTRIES_H + +#include +#include +#include +#include +#include + +#include + +namespace ripple { + +// This is a proxy that returns a strongly-typed object instead of an STObject +template +class STArrayProxy +{ +public: + using value_type = ProxyType; + using size_type = std::size_t; + + class iterator + { + public: + using difference_type = std::ptrdiff_t; + using value_type = ProxyType; + using reference = ProxyType; + using iterator_category = std::bidirectional_iterator_tag; + struct pointer + { + ProxyType object_; + + ProxyType const* + operator->() const + { + return &object_; + } + + ProxyType const& + operator*() const + { + return object_; + } + + ProxyType* + operator->() + { + return &object_; + } + + ProxyType& + operator*() + { + return object_; + } + }; + + explicit iterator(STArray::iterator it) : it_(it) + { + } + + reference + operator*() + { + return ProxyType::fromObject(*it_); + } + + pointer + operator->() + { + return pointer{ProxyType::fromObject(*it_)}; + } + + iterator& + operator++() + { + ++it_; + return *this; + } + + iterator + operator++(int) + { + iterator tmp = *this; + ++(*this); + return tmp; + } + + bool + operator==(iterator const& other) const + { + return it_ == other.it_; + } + + bool + operator!=(iterator const& other) const + { + return it_ != other.it_; + } + + private: + STArray::iterator it_; + }; + + explicit STArrayProxy(STArray* array) : array_(array) + { + } + + [[nodiscard]] bool + valid() const + { + return array_ != nullptr; + } + + explicit + operator bool() const + { + return valid(); + } + + STArray& + value() + { + return *array_; + } + + ProxyType + createItem() + { + return ProxyType::create(); + } + + void + push_back(ProxyType const& obj) + { + array_->push_back(obj); + } + + [[nodiscard]] size_type + size() const + { + return array_ ? array_->size() : 0; + } + + [[nodiscard]] bool + empty() const + { + return size() == 0; + } + + [[nodiscard]] ProxyType + at(size_type idx) const + { + if (!array_ || idx >= array_->size()) + { + return ProxyType::fromObject(nullptr); + } + return ProxyType::fromObject((*array_)[idx]); + } + + ProxyType + operator[](size_type idx) const + { + return at(idx); + } + + [[nodiscard]] ProxyType + back() const + { + return ProxyType::fromObject(array_->back()); + } + + [[nodiscard]] iterator + begin() const + { + return array_ ? iterator{array_->begin()} + : iterator{STArray::iterator{}}; + } + + [[nodiscard]] iterator + end() const + { + return array_ ? iterator{array_->end()} : iterator{STArray::iterator{}}; + } + +private: + STArray* array_; +}; + +// We need a way to address each field so that we can map the field names +// to field types +#pragma push_macro("UNTYPED_SFIELD") +#undef UNTYPED_SFIELD +#pragma push_macro("TYPED_SFIELD") +#undef TYPED_SFIELD +#pragma push_macro("ARRAY_SFIELD") +#undef ARRAY_SFIELD + +#define UNTYPED_SFIELD(sfName, stiSuffix, fieldValue, ...) field_##sfName, +#define TYPED_SFIELD(sfName, stiSuffix, fieldValue, ...) field_##sfName, +#define ARRAY_SFIELD(sfName, sfItemName, stiSuffix, fieldValue, ...) \ + UNTYPED_SFIELD(sfName, stiSuffix, fieldValue, __VA_ARGS__) + +enum class SFieldNames { + field_sfInvalid, +#include +}; +#undef TYPED_SFIELD +#pragma pop_macro("TYPED_SFIELD") +#undef UNTYPED_SFIELD +#pragma pop_macro("UNTYPED_SFIELD") +#undef ARRAY_SFIELD +#pragma pop_macro("ARRAY_SFIELD") + +namespace detail { + +// This enum defines what an UNTYPED_SFIELD is holding, +// and we only care about objects and arrays +enum class AggregateFieldTypes { + NONE, + OBJECT, + ARRAY, + LEDGERENTRY, + TRANSACTION, + VALIDATION, + METADATA, + PATHSET, +}; + +// The base case for GetFieldType. We'll define more specialisations for each +// SFieldName so that we can find the field type and the item type if it's +// an array +template +struct GetFieldType +{ + constexpr static AggregateFieldTypes Value = AggregateFieldTypes::NONE; + constexpr static SFieldNames ItemField = SFieldNames::field_sfInvalid; +}; + +// For each field defined in sfields.macro, we will have a template +// specialisation of GetFieldType for it, and each GetFieldType will +// have a static Value member and a static ItemField member +#pragma push_macro("UNTYPED_SFIELD") +#undef UNTYPED_SFIELD +#pragma push_macro("TYPED_SFIELD") +#undef TYPED_SFIELD +#pragma push_macro("ARRAY_SFIELD") +#undef ARRAY_SFIELD + +#define UNTYPED_SFIELD(sfName, stiSuffix, fieldValue, ...) \ + template <> \ + struct GetFieldType \ + { \ + constexpr static AggregateFieldTypes Value = \ + AggregateFieldTypes::stiSuffix; \ + constexpr static SFieldNames ItemField = SFieldNames::field_sfInvalid; \ + }; +#define TYPED_SFIELD(sfName, stiSuffix, fieldValue, ...) +#define ARRAY_SFIELD(sfName, sfItemName, stiSuffix, fieldValue, ...) \ + template <> \ + struct GetFieldType \ + { \ + constexpr static AggregateFieldTypes Value = \ + AggregateFieldTypes::stiSuffix; \ + constexpr static SFieldNames ItemField = \ + SFieldNames::field_##sfItemName; \ + }; + +#include + +#undef TYPED_SFIELD +#pragma pop_macro("TYPED_SFIELD") +#undef UNTYPED_SFIELD +#pragma pop_macro("UNTYPED_SFIELD") +#undef ARRAY_SFIELD +#pragma pop_macro("ARRAY_SFIELD") + +// We reference those `InnerObjects` in the get function when we define the type +// Because of that, We need to push types defined in inner_objects.macro into an +// array so that we can delay evaluating the types. +// This Pair struct stores a field name and a type +template +struct InnerObjectTypePair +{ + static constexpr SFieldNames Field = FieldName; + using InnerObjectType = Type; +}; + +template +concept IsInnerObjectTypePair = requires { + std::same_as; + typename T::InnerObjectType; +} || std::same_as; + +// Those `GetInnerObjectStruct` classes iterate through each item in the array, +// and then return the type that the corresponding field name is equal to the +// name we're looking for. It returns void if there's no corresponding field. +template +struct GetInnerObjectStruct +{ +}; + +template < + SFieldNames FieldName, + IsInnerObjectTypePair Current, + IsInnerObjectTypePair... Pairs> +struct GetInnerObjectStruct> +{ + using Struct = std::conditional_t< + Current::Field == FieldName, + typename Current::InnerObjectType, + typename GetInnerObjectStruct>::Struct>; +}; + +template +struct GetInnerObjectStruct> +{ + using Struct = std::conditional_t< + Current::Field == FieldName, + typename Current::InnerObjectType, + void>; +}; + +template +struct GetInnerObjectStruct> +{ + using Struct = void; +}; + +// This type returns the value directly if the field is a typed field. +template < + SFieldNames FieldName, + SFieldNames ItemFieldName, + SOEStyle SOEStyleValue, + AggregateFieldTypes FieldType, + typename InnerObjectTypesArray> +struct GetFieldValue +{ + template + static auto + get(STObject& object, TFieldType const& field) + { + return object[field]; + } +}; + +// This type returns an optional value when the field is marked as optional +template < + SFieldNames FieldName, + SFieldNames ItemFieldName, + typename InnerObjectTypesArray> +struct GetFieldValue< + FieldName, + ItemFieldName, + soeOPTIONAL, + AggregateFieldTypes::NONE, + InnerObjectTypesArray> +{ + template + static auto + get(STObject& object, TFieldType const& field) + { + return object[~field]; + } +}; + +// This type wraps the STObject value into the corresponding proxy type to +// provide intellisense +template < + SFieldNames FieldName, + SFieldNames ItemFieldName, + SOEStyle SOEStyle, + typename InnerObjectTypesArray> +struct GetFieldValue< + FieldName, + ItemFieldName, + SOEStyle, + AggregateFieldTypes::OBJECT, + InnerObjectTypesArray> +{ + using InnerObjectType = + typename GetInnerObjectStruct::Struct; + // If the type is defined in inner_objects.macro, we return the defined type + // otherwise, we return the untyped STObject + template + static std::conditional_t< + !std::is_void_v, + InnerObjectType, + STObject const&> + get(STObject& object, TFieldType const& field) + { + if constexpr (!std::is_void_v) + { + return InnerObjectType::fromObject( + object.getField(field).template downcast()); + } + else + { + return object.getField(field).template downcast(); + } + } +}; + +// This type returns an std::optional when the field is marked as optional. +template < + SFieldNames FieldName, + SFieldNames ItemFieldName, + typename InnerObjectTypesArray> +struct GetFieldValue< + FieldName, + ItemFieldName, + soeOPTIONAL, + AggregateFieldTypes::OBJECT, + InnerObjectTypesArray> +{ + using InnerObjectType = + typename GetInnerObjectStruct::Struct; + template + static std::conditional_t< + !std::is_void_v, + std::optional, + STObject const*> + get(STObject& object, TFieldType const& field) + { + if constexpr (!std::is_void_v) + { + if (object.isFieldPresent(field)) + { + return InnerObjectType::fromObject( + object.getField(field).template downcast()); + } + return std::nullopt; + } + else + { + if (object.isFieldPresent(field)) + { + return &object.getField(field).template downcast(); + } + return nullptr; + } + } +}; + +// This type wraps the STArray value into the strongly-typed array proxy. +template < + SFieldNames FieldName, + SFieldNames ItemFieldName, + SOEStyle Style, + typename InnerObjectTypesArray> +struct GetFieldValue< + FieldName, + ItemFieldName, + Style, + AggregateFieldTypes::ARRAY, + InnerObjectTypesArray> +{ + using InnerObjectType = + typename GetInnerObjectStruct:: + Struct; + + template + static std::conditional_t< + !std::is_void_v, + STArrayProxy, + STArray&> + get(STObject& object, TFieldType const& field) + { + if constexpr (!std::is_void_v) + { + return STArrayProxy{&object.peekFieldArray(field)}; + } + else + { + return object.peekFieldArray(field); + } + } +}; + +// This type returns an std::optional when the field is marked as optional. +template < + SFieldNames FieldName, + SFieldNames ItemFieldName, + typename InnerObjectTypesArray> +struct GetFieldValue< + FieldName, + ItemFieldName, + soeOPTIONAL, + AggregateFieldTypes::ARRAY, + InnerObjectTypesArray> +{ + using InnerObjectType = + typename GetInnerObjectStruct:: + Struct; + template + static std::conditional_t< + !std::is_void_v, + STArrayProxy, + STArray*> + get(STObject& object, TFieldType const& field) + { + if constexpr (!std::is_void_v) + { + if (object.isFieldPresent(field)) + { + return STArrayProxy{ + &object.peekFieldArray(field)}; + } + return STArrayProxy{nullptr}; + } + else + { + if (object.isFieldPresent(field)) + { + return &object.peekFieldArray(field); + } + return nullptr; + } + } +}; + +// We're defining the inner object type array so that we can use it +// in the get function. +#pragma push_macro("INNER_OBJECT") +#pragma push_macro("FIELDS") +#pragma push_macro("FIELD") +#pragma push_macro("INNER_OBJECT_BEGIN") +#pragma push_macro("INNER_OBJECT_END") + +#define INNER_OBJECT_BEGIN using InnerObjectTypesArray = std::tuple < +#define INNER_OBJECT_END void > ; + +#define FIELDS(...) __VA_ARGS__ +#define FIELD(name, field, soeStyle) + +#define INNER_OBJECT(name, fields) \ + InnerObjectTypePair, + +#include + +#pragma pop_macro("INNER_OBJECT") +#pragma pop_macro("FIELDS") +#pragma pop_macro("FIELD") +#pragma pop_macro("INNER_OBJECT_BEGIN") +#pragma pop_macro("INNER_OBJECT_END") + +// We're defining each inner object type here. + +#pragma push_macro("INNER_OBJECT") +#pragma push_macro("FIELDS") +#pragma push_macro("FIELD") +#pragma push_macro("INNER_OBJECT_BEGIN") +#pragma push_macro("INNER_OBJECT_END") + +#define INNER_OBJECT_BEGIN +#define INNER_OBJECT_END + +#define FIELDS(...) __VA_ARGS__ +#define FIELD(name, field, soeStyle) \ + auto f##field() \ + { \ + return GetFieldValue< \ + SFieldNames::field_##field, \ + detail::GetFieldType::ItemField, \ + soeStyle, \ + detail::GetFieldType::Value, \ + InnerObjectTypesArray>::get(*getObject(), field); \ + } + +#define INNER_OBJECT(name, fields) \ + struct InnerObject_##name \ + { \ + private: \ + std::variant, STObject*> object_; \ + InnerObject_##name(STObject* object) : object_(object) \ + { \ + } \ + InnerObject_##name(std::shared_ptr const& object) \ + : object_(object) \ + { \ + } \ + \ + public: \ + static constexpr bool IsValidType = true; \ + static InnerObject_##name \ + fromObject(STObject& object) \ + { \ + return InnerObject_##name{&object}; \ + } \ + static InnerObject_##name \ + fromObject(std::shared_ptr const& object) \ + { \ + return InnerObject_##name{object}; \ + } \ + static InnerObject_##name \ + create() \ + { \ + return InnerObject_##name{std::make_shared(name)}; \ + } \ + operator STObject const&() const \ + { \ + return *getObject(); \ + } \ + operator STObject&() \ + { \ + return *getObject(); \ + } \ + STObject* \ + getObject() \ + { \ + if (std::holds_alternative>(object_)) \ + { \ + return std::get>(object_).get(); \ + } \ + else \ + { \ + return std::get(object_); \ + } \ + } \ + STObject const* \ + getObject() const \ + { \ + if (std::holds_alternative>(object_)) \ + { \ + return std::get>(object_).get(); \ + } \ + else \ + { \ + return std::get(object_); \ + } \ + } \ + bool \ + isValid() const \ + { \ + return getObject() != nullptr; \ + } \ + fields \ + }; + +#include + +// We're defining each ledger entry here. + +#pragma pop_macro("INNER_OBJECT") +#pragma pop_macro("FIELDS") +#pragma pop_macro("FIELD") +#pragma pop_macro("INNER_OBJECT_BEGIN") +#pragma pop_macro("INNER_OBJECT_END") + +template +struct LedgerEntry +{ +}; + +#pragma push_macro("LEDGER_ENTRY") +#undef LEDGER_ENTRY +#pragma push_macro("LEDGER_ENTRY_DUPLICATE") +#undef LEDGER_ENTRY_DUPLICATE +#pragma push_macro("LEDGER_ENTRY_FIELD") +#undef LEDGER_ENTRY_FIELD +#pragma push_macro("DEFINE_LEDGER_ENTRY_FIELDS") +#undef DEFINE_LEDGER_ENTRY_FIELDS +#pragma push_macro("LEDGER_ENTRIES_BEGIN") +#undef LEDGER_ENTRIES_BEGIN +#pragma push_macro("LEDGER_ENTRIES_END") +#undef LEDGER_ENTRIES_END + +#define LEDGER_ENTRIES_BEGIN +#define LEDGER_ENTRIES_END +#define DEFINE_LEDGER_ENTRY_FIELDS(...) __VA_ARGS__ +#define LEDGER_ENTRY_FIELD(field, soeStyle) \ + using Field_##field##Type = \ + decltype(GetFieldValue< \ + SFieldNames::field_##field, \ + detail::GetFieldType::ItemField, \ + soeStyle, \ + detail::GetFieldType::Value, \ + InnerObjectTypesArray>:: \ + get(std::declval(), field)); \ + Field_##field##Type f##field() \ + { \ + return GetFieldValue< \ + SFieldNames::field_##field, \ + detail::GetFieldType::ItemField, \ + soeStyle, \ + detail::GetFieldType::Value, \ + InnerObjectTypesArray>::get(*getObject(), field); \ + } + +#define LEDGER_ENTRY(tag, value, name, rpcName, fields) \ + template <> \ + struct LedgerEntry \ + { \ + private: \ + using CLS = LedgerEntry; \ + std::variant, STLedgerEntry*> object_; \ + LedgerEntry(STLedgerEntry& object) : object_(&object) \ + { \ + } \ + LedgerEntry(std::shared_ptr const& object) \ + : object_(object) \ + { \ + } \ + \ + public: \ + bool \ + isValid() const \ + { \ + return getObject() != nullptr; \ + } \ + static void \ + ensureType(STLedgerEntry const& object) \ + { \ + if (tag != object.getType()) \ + { \ + Throw("Object type mismatch!"); \ + } \ + } \ + STLedgerEntry* \ + getObject() \ + { \ + if (std::holds_alternative>( \ + object_)) \ + { \ + return std::get>(object_) \ + .get(); \ + } \ + else \ + { \ + return std::get(object_); \ + } \ + } \ + STLedgerEntry const* \ + getObject() const \ + { \ + if (std::holds_alternative>( \ + object_)) \ + { \ + return std::get>(object_) \ + .get(); \ + } \ + else \ + { \ + return std::get(object_); \ + } \ + } \ + static LedgerEntry \ + fromObject(STLedgerEntry& object) \ + { \ + ensureType(object); \ + return LedgerEntry{object}; \ + } \ + static LedgerEntry \ + fromObject(std::shared_ptr const& object) \ + { \ + ensureType(*object); \ + return LedgerEntry{object}; \ + } \ + static LedgerEntry \ + create(uint256 const& key) \ + { \ + return LedgerEntry{std::make_shared(tag, key)}; \ + } \ + fields \ + }; + +#define LEDGER_ENTRY_DUPLICATE(...) + +#include + +#undef LEDGER_ENTRY +#pragma pop_macro("LEDGER_ENTRY") +#undef LEDGER_ENTRY_DUPLICATE +#pragma pop_macro("LEDGER_ENTRY_DUPLICATE") +#undef LEDGER_ENTRY_FIELD +#pragma pop_macro("LEDGER_ENTRY_FIELD") +#undef DEFINE_LEDGER_ENTRY_FIELDS +#pragma pop_macro("DEFINE_LEDGER_ENTRY_FIELDS") +#undef LEDGER_ENTRIES_BEGIN +#pragma pop_macro("LEDGER_ENTRIES_BEGIN") +#undef LEDGER_ENTRIES_END +#pragma pop_macro("LEDGER_ENTRIES_END") + +} // namespace detail + +template +using InnerObjectType = typename detail:: + GetInnerObjectStruct::Struct; + +template +using LedgerObjectType = detail::LedgerEntry; +} // namespace ripple +#endif // TYPED_LEDGER_ENTRIES_H diff --git a/include/xrpl/protocol/detail/inner_objects.macro b/include/xrpl/protocol/detail/inner_objects.macro new file mode 100644 index 0000000000..340fba2f8c --- /dev/null +++ b/include/xrpl/protocol/detail/inner_objects.macro @@ -0,0 +1,175 @@ + +#if !defined(INNER_OBJECT) +#error "undefined macro: INNER_OBJECT" +#endif + +#if !defined(FIELDS) +#error "undefined macro: FIELDS" +#endif + +#if !defined(FIELD) +#error "undefined macro: FIELD" +#endif + +#if !defined(INNER_OBJECT_BEGIN) +#error "undefined macro: INNER_OBJECT_BEGIN" +#endif + +#if !defined(INNER_OBJECT_END) +#error "undefined macro: INNER_OBJECT_END" +#endif + +INNER_OBJECT_BEGIN + +INNER_OBJECT(sfSignerEntry, + FIELDS( + FIELD(sfSignerEntry, sfAccount, soeREQUIRED) + FIELD(sfSignerEntry, sfSignerWeight, soeREQUIRED) + FIELD(sfSignerEntry, sfWalletLocator, soeOPTIONAL) + ) +) + +INNER_OBJECT(sfSigner, + FIELDS( + FIELD(sfSigner, sfAccount, soeREQUIRED) + FIELD(sfSigner, sfSigningPubKey, soeREQUIRED) + FIELD(sfSigner, sfTxnSignature, soeREQUIRED) + ) +) + +INNER_OBJECT(sfMajority, + FIELDS( + FIELD(sfMajority, sfAmendment, soeREQUIRED) + FIELD(sfMajority, sfCloseTime, soeREQUIRED) + ) +) + +INNER_OBJECT(sfDisabledValidator, + FIELDS( + FIELD(sfDisabledValidator, sfPublicKey, soeREQUIRED) + FIELD(sfDisabledValidator, sfFirstLedgerSequence, soeREQUIRED) + ) +) + +INNER_OBJECT(sfNFToken, + FIELDS( + FIELD(sfNFToken, sfNFTokenID, soeREQUIRED) + FIELD(sfNFToken, sfURI, soeOPTIONAL) + ) +) + +INNER_OBJECT(sfVoteEntry, + FIELDS( + FIELD(sfVoteEntry, sfAccount, soeREQUIRED) + FIELD(sfVoteEntry, sfTradingFee, soeDEFAULT) + FIELD(sfVoteEntry, sfVoteWeight, soeREQUIRED) + ) +) + +INNER_OBJECT(sfAuctionSlot, + FIELDS( + FIELD(sfAuctionSlot, sfAccount, soeREQUIRED) + FIELD(sfAuctionSlot, sfExpiration, soeREQUIRED) + FIELD(sfAuctionSlot, sfDiscountedFee, soeDEFAULT) + FIELD(sfAuctionSlot, sfPrice, soeREQUIRED) + FIELD(sfAuctionSlot, sfAuthAccounts, soeOPTIONAL) + ) +) + +INNER_OBJECT(sfXChainClaimAttestationCollectionElement, + FIELDS( + FIELD(sfXChainClaimAttestationCollectionElement, sfAttestationSignerAccount, soeREQUIRED) + FIELD(sfXChainClaimAttestationCollectionElement, sfPublicKey, soeREQUIRED) + FIELD(sfXChainClaimAttestationCollectionElement, sfSignature, soeREQUIRED) + FIELD(sfXChainClaimAttestationCollectionElement, sfAmount, soeREQUIRED) + FIELD(sfXChainClaimAttestationCollectionElement, sfAccount, soeREQUIRED) + FIELD(sfXChainClaimAttestationCollectionElement, sfAttestationRewardAccount, soeREQUIRED) + FIELD(sfXChainClaimAttestationCollectionElement, sfWasLockingChainSend, soeREQUIRED) + FIELD(sfXChainClaimAttestationCollectionElement, sfXChainClaimID, soeREQUIRED) + FIELD(sfXChainClaimAttestationCollectionElement, sfDestination, soeOPTIONAL) + ) +) + +INNER_OBJECT(sfXChainCreateAccountAttestationCollectionElement, + FIELDS( + FIELD(sfXChainCreateAccountAttestationCollectionElement, sfAttestationSignerAccount, soeREQUIRED) + FIELD(sfXChainCreateAccountAttestationCollectionElement, sfPublicKey, soeREQUIRED) + FIELD(sfXChainCreateAccountAttestationCollectionElement, sfSignature, soeREQUIRED) + FIELD(sfXChainCreateAccountAttestationCollectionElement, sfAmount, soeREQUIRED) + FIELD(sfXChainCreateAccountAttestationCollectionElement, sfAccount, soeREQUIRED) + FIELD(sfXChainCreateAccountAttestationCollectionElement, sfAttestationRewardAccount, soeREQUIRED) + FIELD(sfXChainCreateAccountAttestationCollectionElement, sfWasLockingChainSend, soeREQUIRED) + FIELD(sfXChainCreateAccountAttestationCollectionElement, sfXChainAccountCreateCount, soeREQUIRED) + FIELD(sfXChainCreateAccountAttestationCollectionElement, sfDestination, soeREQUIRED) + FIELD(sfXChainCreateAccountAttestationCollectionElement, sfSignatureReward, soeREQUIRED) + ) +) + +INNER_OBJECT(sfXChainClaimProofSig, + FIELDS( + FIELD(sfXChainClaimProofSig, sfAttestationSignerAccount, soeREQUIRED) + FIELD(sfXChainClaimProofSig, sfPublicKey, soeREQUIRED) + FIELD(sfXChainClaimProofSig, sfAmount, soeREQUIRED) + FIELD(sfXChainClaimProofSig, sfAttestationRewardAccount, soeREQUIRED) + FIELD(sfXChainClaimProofSig, sfWasLockingChainSend, soeREQUIRED) + FIELD(sfXChainClaimProofSig, sfDestination, soeOPTIONAL) + ) +) + +INNER_OBJECT(sfXChainCreateAccountProofSig, + FIELDS( + FIELD(sfXChainCreateAccountProofSig, sfAttestationSignerAccount, soeREQUIRED) + FIELD(sfXChainCreateAccountProofSig, sfPublicKey, soeREQUIRED) + FIELD(sfXChainCreateAccountProofSig, sfAmount, soeREQUIRED) + FIELD(sfXChainCreateAccountProofSig, sfSignatureReward, soeREQUIRED) + FIELD(sfXChainCreateAccountProofSig, sfAttestationRewardAccount, soeREQUIRED) + FIELD(sfXChainCreateAccountProofSig, sfWasLockingChainSend, soeREQUIRED) + FIELD(sfXChainCreateAccountProofSig, sfDestination, soeREQUIRED) + ) +) + +INNER_OBJECT(sfAuthAccount, + FIELDS( + FIELD(sfAuthAccount, sfAccount, soeREQUIRED) + ) +) + +INNER_OBJECT(sfPriceData, + FIELDS( + FIELD(sfPriceData, sfBaseAsset, soeREQUIRED) + FIELD(sfPriceData, sfQuoteAsset, soeREQUIRED) + FIELD(sfPriceData, sfAssetPrice, soeOPTIONAL) + FIELD(sfPriceData, sfScale, soeDEFAULT) + ) +) + +INNER_OBJECT(sfCredential, + FIELDS( + FIELD(sfCredential, sfIssuer, soeREQUIRED) + FIELD(sfCredential, sfCredentialType, soeREQUIRED) + ) +) + +INNER_OBJECT(sfPermission, + FIELDS( + FIELD(sfPermission, sfPermissionValue, soeREQUIRED) + ) +) + +INNER_OBJECT(sfBatchSigner, + FIELDS( + FIELD(sfBatchSigner, sfAccount, soeREQUIRED) + FIELD(sfBatchSigner, sfSigningPubKey, soeOPTIONAL) + FIELD(sfBatchSigner, sfTxnSignature, soeOPTIONAL) + FIELD(sfBatchSigner, sfSigners, soeOPTIONAL) + ) +) + +INNER_OBJECT(sfBook, + FIELDS( + FIELD(sfBook, sfBookDirectory, soeREQUIRED) + FIELD(sfBook, sfBookNode, soeREQUIRED) + ) +) + +INNER_OBJECT_END diff --git a/include/xrpl/protocol/detail/ledger_entries.macro b/include/xrpl/protocol/detail/ledger_entries.macro index 46c6e60db3..00497ad195 100644 --- a/include/xrpl/protocol/detail/ledger_entries.macro +++ b/include/xrpl/protocol/detail/ledger_entries.macro @@ -21,6 +21,22 @@ #error "undefined macro: LEDGER_ENTRY" #endif +#if !defined(LEDGER_ENTRY_FIELD) +#error "undefined macro: LEDGER_ENTRY_FIELD" +#endif + +#if !defined(DEFINE_LEDGER_ENTRY_FIELDS) +#error "undefined macro: DEFINE_LEDGER_ENTRY_FIELDS" +#endif + +#if !defined(LEDGER_ENTRIES_BEGIN) +#error "undefined macro: LEDGER_ENTRIES_BEGIN" +#endif + +#if !defined(LEDGER_ENTRIES_END) +#error "undefined macro: LEDGER_ENTRIES_END" +#endif + #ifndef LEDGER_ENTRY_DUPLICATE // The EXPAND macro is needed for Windows // https://stackoverflow.com/questions/5134523/msvc-doesnt-expand-va-args-correctly @@ -32,6 +48,8 @@ #define LEDGER_ENTRY_DUPLICATE(...) EXPAND(LEDGER_ENTRY(__VA_ARGS__)) #endif +LEDGER_ENTRIES_BEGIN + /** * These objects are listed in order of increasing ledger type ID. * There are many gaps between these IDs. @@ -42,50 +60,50 @@ \sa keylet::nftoffer */ -LEDGER_ENTRY(ltNFTOKEN_OFFER, 0x0037, NFTokenOffer, nft_offer, ({ - {sfOwner, soeREQUIRED}, - {sfNFTokenID, soeREQUIRED}, - {sfAmount, soeREQUIRED}, - {sfOwnerNode, soeREQUIRED}, - {sfNFTokenOfferNode, soeREQUIRED}, - {sfDestination, soeOPTIONAL}, - {sfExpiration, soeOPTIONAL}, - {sfPreviousTxnID, soeREQUIRED}, - {sfPreviousTxnLgrSeq, soeREQUIRED}, -})) +LEDGER_ENTRY(ltNFTOKEN_OFFER, 0x0037, NFTokenOffer, nft_offer, DEFINE_LEDGER_ENTRY_FIELDS( + LEDGER_ENTRY_FIELD(sfOwner, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfNFTokenID, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfAmount, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfOwnerNode, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfNFTokenOfferNode, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfDestination, soeOPTIONAL) + LEDGER_ENTRY_FIELD(sfExpiration, soeOPTIONAL) + LEDGER_ENTRY_FIELD(sfPreviousTxnID, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfPreviousTxnLgrSeq, soeREQUIRED) +)) /** A ledger object which describes a check. \sa keylet::check */ -LEDGER_ENTRY(ltCHECK, 0x0043, Check, check, ({ - {sfAccount, soeREQUIRED}, - {sfDestination, soeREQUIRED}, - {sfSendMax, soeREQUIRED}, - {sfSequence, soeREQUIRED}, - {sfOwnerNode, soeREQUIRED}, - {sfDestinationNode, soeREQUIRED}, - {sfExpiration, soeOPTIONAL}, - {sfInvoiceID, soeOPTIONAL}, - {sfSourceTag, soeOPTIONAL}, - {sfDestinationTag, soeOPTIONAL}, - {sfPreviousTxnID, soeREQUIRED}, - {sfPreviousTxnLgrSeq, soeREQUIRED}, -})) +LEDGER_ENTRY(ltCHECK, 0x0043, Check, check, DEFINE_LEDGER_ENTRY_FIELDS( + LEDGER_ENTRY_FIELD(sfAccount, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfDestination, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfSendMax, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfSequence, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfOwnerNode, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfDestinationNode, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfExpiration, soeOPTIONAL) + LEDGER_ENTRY_FIELD(sfInvoiceID, soeOPTIONAL) + LEDGER_ENTRY_FIELD(sfSourceTag, soeOPTIONAL) + LEDGER_ENTRY_FIELD(sfDestinationTag, soeOPTIONAL) + LEDGER_ENTRY_FIELD(sfPreviousTxnID, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfPreviousTxnLgrSeq, soeREQUIRED) +)) /** The ledger object which tracks the DID. \sa keylet::did */ -LEDGER_ENTRY(ltDID, 0x0049, DID, did, ({ - {sfAccount, soeREQUIRED}, - {sfDIDDocument, soeOPTIONAL}, - {sfURI, soeOPTIONAL}, - {sfData, soeOPTIONAL}, - {sfOwnerNode, soeREQUIRED}, - {sfPreviousTxnID, soeREQUIRED}, - {sfPreviousTxnLgrSeq, soeREQUIRED}, -})) +LEDGER_ENTRY(ltDID, 0x0049, DID, did, DEFINE_LEDGER_ENTRY_FIELDS( + LEDGER_ENTRY_FIELD(sfAccount, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfDIDDocument, soeOPTIONAL) + LEDGER_ENTRY_FIELD(sfURI, soeOPTIONAL) + LEDGER_ENTRY_FIELD(sfData, soeOPTIONAL) + LEDGER_ENTRY_FIELD(sfOwnerNode, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfPreviousTxnID, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfPreviousTxnLgrSeq, soeREQUIRED) +)) /** The ledger object which tracks the current negative UNL state. @@ -93,25 +111,25 @@ LEDGER_ENTRY(ltDID, 0x0049, DID, did, ({ \sa keylet::negativeUNL */ -LEDGER_ENTRY(ltNEGATIVE_UNL, 0x004e, NegativeUNL, nunl, ({ - {sfDisabledValidators, soeOPTIONAL}, - {sfValidatorToDisable, soeOPTIONAL}, - {sfValidatorToReEnable, soeOPTIONAL}, - {sfPreviousTxnID, soeOPTIONAL}, - {sfPreviousTxnLgrSeq, soeOPTIONAL}, -})) +LEDGER_ENTRY(ltNEGATIVE_UNL, 0x004e, NegativeUNL, nunl, DEFINE_LEDGER_ENTRY_FIELDS( + LEDGER_ENTRY_FIELD(sfDisabledValidators, soeOPTIONAL) + LEDGER_ENTRY_FIELD(sfValidatorToDisable, soeOPTIONAL) + LEDGER_ENTRY_FIELD(sfValidatorToReEnable, soeOPTIONAL) + LEDGER_ENTRY_FIELD(sfPreviousTxnID, soeOPTIONAL) + LEDGER_ENTRY_FIELD(sfPreviousTxnLgrSeq, soeOPTIONAL) +)) /** A ledger object which contains a list of NFTs \sa keylet::nftpage_min, keylet::nftpage_max, keylet::nftpage */ -LEDGER_ENTRY(ltNFTOKEN_PAGE, 0x0050, NFTokenPage, nft_page, ({ - {sfPreviousPageMin, soeOPTIONAL}, - {sfNextPageMin, soeOPTIONAL}, - {sfNFTokens, soeREQUIRED}, - {sfPreviousTxnID, soeREQUIRED}, - {sfPreviousTxnLgrSeq, soeREQUIRED}, -})) +LEDGER_ENTRY(ltNFTOKEN_PAGE, 0x0050, NFTokenPage, nft_page, DEFINE_LEDGER_ENTRY_FIELDS( + LEDGER_ENTRY_FIELD(sfPreviousPageMin, soeOPTIONAL) + LEDGER_ENTRY_FIELD(sfNextPageMin, soeOPTIONAL) + LEDGER_ENTRY_FIELD(sfNFTokens, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfPreviousTxnID, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfPreviousTxnLgrSeq, soeREQUIRED) +)) /** A ledger object which contains a signer list for an account. @@ -119,77 +137,77 @@ LEDGER_ENTRY(ltNFTOKEN_PAGE, 0x0050, NFTokenPage, nft_page, ({ */ // All fields are soeREQUIRED because there is always a SignerEntries. // If there are no SignerEntries the node is deleted. -LEDGER_ENTRY(ltSIGNER_LIST, 0x0053, SignerList, signer_list, ({ - {sfOwnerNode, soeREQUIRED}, - {sfSignerQuorum, soeREQUIRED}, - {sfSignerEntries, soeREQUIRED}, - {sfSignerListID, soeREQUIRED}, - {sfPreviousTxnID, soeREQUIRED}, - {sfPreviousTxnLgrSeq, soeREQUIRED}, -})) +LEDGER_ENTRY(ltSIGNER_LIST, 0x0053, SignerList, signer_list, DEFINE_LEDGER_ENTRY_FIELDS( + LEDGER_ENTRY_FIELD(sfOwnerNode, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfSignerQuorum, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfSignerEntries, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfSignerListID, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfPreviousTxnID, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfPreviousTxnLgrSeq, soeREQUIRED) +)) /** A ledger object which describes a ticket. \sa keylet::ticket */ -LEDGER_ENTRY(ltTICKET, 0x0054, Ticket, ticket, ({ - {sfAccount, soeREQUIRED}, - {sfOwnerNode, soeREQUIRED}, - {sfTicketSequence, soeREQUIRED}, - {sfPreviousTxnID, soeREQUIRED}, - {sfPreviousTxnLgrSeq, soeREQUIRED}, -})) +LEDGER_ENTRY(ltTICKET, 0x0054, Ticket, ticket, DEFINE_LEDGER_ENTRY_FIELDS( + LEDGER_ENTRY_FIELD(sfAccount, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfOwnerNode, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfTicketSequence, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfPreviousTxnID, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfPreviousTxnLgrSeq, soeREQUIRED) +)) /** A ledger object which describes an account. \sa keylet::account */ -LEDGER_ENTRY(ltACCOUNT_ROOT, 0x0061, AccountRoot, account, ({ - {sfAccount, soeREQUIRED}, - {sfSequence, soeREQUIRED}, - {sfBalance, soeREQUIRED}, - {sfOwnerCount, soeREQUIRED}, - {sfPreviousTxnID, soeREQUIRED}, - {sfPreviousTxnLgrSeq, soeREQUIRED}, - {sfAccountTxnID, soeOPTIONAL}, - {sfRegularKey, soeOPTIONAL}, - {sfEmailHash, soeOPTIONAL}, - {sfWalletLocator, soeOPTIONAL}, - {sfWalletSize, soeOPTIONAL}, - {sfMessageKey, soeOPTIONAL}, - {sfTransferRate, soeOPTIONAL}, - {sfDomain, soeOPTIONAL}, - {sfTickSize, soeOPTIONAL}, - {sfTicketCount, soeOPTIONAL}, - {sfNFTokenMinter, soeOPTIONAL}, - {sfMintedNFTokens, soeDEFAULT}, - {sfBurnedNFTokens, soeDEFAULT}, - {sfFirstNFTokenSequence, soeOPTIONAL}, - {sfAMMID, soeOPTIONAL}, // pseudo-account designator - {sfVaultID, soeOPTIONAL}, // pseudo-account designator -})) +LEDGER_ENTRY(ltACCOUNT_ROOT, 0x0061, AccountRoot, account, DEFINE_LEDGER_ENTRY_FIELDS( + LEDGER_ENTRY_FIELD(sfAccount, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfSequence, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfBalance, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfOwnerCount, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfPreviousTxnID, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfPreviousTxnLgrSeq, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfAccountTxnID, soeOPTIONAL) + LEDGER_ENTRY_FIELD(sfRegularKey, soeOPTIONAL) + LEDGER_ENTRY_FIELD(sfEmailHash, soeOPTIONAL) + LEDGER_ENTRY_FIELD(sfWalletLocator, soeOPTIONAL) + LEDGER_ENTRY_FIELD(sfWalletSize, soeOPTIONAL) + LEDGER_ENTRY_FIELD(sfMessageKey, soeOPTIONAL) + LEDGER_ENTRY_FIELD(sfTransferRate, soeOPTIONAL) + LEDGER_ENTRY_FIELD(sfDomain, soeOPTIONAL) + LEDGER_ENTRY_FIELD(sfTickSize, soeOPTIONAL) + LEDGER_ENTRY_FIELD(sfTicketCount, soeOPTIONAL) + LEDGER_ENTRY_FIELD(sfNFTokenMinter, soeOPTIONAL) + LEDGER_ENTRY_FIELD(sfMintedNFTokens, soeDEFAULT) + LEDGER_ENTRY_FIELD(sfBurnedNFTokens, soeDEFAULT) + LEDGER_ENTRY_FIELD(sfFirstNFTokenSequence, soeOPTIONAL) + LEDGER_ENTRY_FIELD(sfAMMID, soeOPTIONAL) // pseudo-account designator + LEDGER_ENTRY_FIELD(sfVaultID, soeOPTIONAL) // pseudo-account designator +)) /** A ledger object which contains a list of object identifiers. \sa keylet::page, keylet::quality, keylet::book, keylet::next and keylet::ownerDir */ -LEDGER_ENTRY(ltDIR_NODE, 0x0064, DirectoryNode, directory, ({ - {sfOwner, soeOPTIONAL}, // for owner directories - {sfTakerPaysCurrency, soeOPTIONAL}, // order book directories - {sfTakerPaysIssuer, soeOPTIONAL}, // order book directories - {sfTakerGetsCurrency, soeOPTIONAL}, // order book directories - {sfTakerGetsIssuer, soeOPTIONAL}, // order book directories - {sfExchangeRate, soeOPTIONAL}, // order book directories - {sfIndexes, soeREQUIRED}, - {sfRootIndex, soeREQUIRED}, - {sfIndexNext, soeOPTIONAL}, - {sfIndexPrevious, soeOPTIONAL}, - {sfNFTokenID, soeOPTIONAL}, - {sfPreviousTxnID, soeOPTIONAL}, - {sfPreviousTxnLgrSeq, soeOPTIONAL}, - {sfDomainID, soeOPTIONAL} -})) +LEDGER_ENTRY(ltDIR_NODE, 0x0064, DirectoryNode, directory, DEFINE_LEDGER_ENTRY_FIELDS( + LEDGER_ENTRY_FIELD(sfOwner, soeOPTIONAL) // for owner directories + LEDGER_ENTRY_FIELD(sfTakerPaysCurrency, soeOPTIONAL) // order book directories + LEDGER_ENTRY_FIELD(sfTakerPaysIssuer, soeOPTIONAL) // order book directories + LEDGER_ENTRY_FIELD(sfTakerGetsCurrency, soeOPTIONAL) // order book directories + LEDGER_ENTRY_FIELD(sfTakerGetsIssuer, soeOPTIONAL) // order book directories + LEDGER_ENTRY_FIELD(sfExchangeRate, soeOPTIONAL) // order book directories + LEDGER_ENTRY_FIELD(sfIndexes, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfRootIndex, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfIndexNext, soeOPTIONAL) + LEDGER_ENTRY_FIELD(sfIndexPrevious, soeOPTIONAL) + LEDGER_ENTRY_FIELD(sfNFTokenID, soeOPTIONAL) + LEDGER_ENTRY_FIELD(sfPreviousTxnID, soeOPTIONAL) + LEDGER_ENTRY_FIELD(sfPreviousTxnLgrSeq, soeOPTIONAL) + LEDGER_ENTRY_FIELD(sfDomainID, soeOPTIONAL) +)) /** The ledger object which lists details about amendments on the network. @@ -197,12 +215,12 @@ LEDGER_ENTRY(ltDIR_NODE, 0x0064, DirectoryNode, directory, ({ \sa keylet::amendments */ -LEDGER_ENTRY(ltAMENDMENTS, 0x0066, Amendments, amendments, ({ - {sfAmendments, soeOPTIONAL}, // Enabled - {sfMajorities, soeOPTIONAL}, - {sfPreviousTxnID, soeOPTIONAL}, - {sfPreviousTxnLgrSeq, soeOPTIONAL}, -})) +LEDGER_ENTRY(ltAMENDMENTS, 0x0066, Amendments, amendments, DEFINE_LEDGER_ENTRY_FIELDS( + LEDGER_ENTRY_FIELD(sfAmendments, soeOPTIONAL) // Enabled + LEDGER_ENTRY_FIELD(sfMajorities, soeOPTIONAL) + LEDGER_ENTRY_FIELD(sfPreviousTxnID, soeOPTIONAL) + LEDGER_ENTRY_FIELD(sfPreviousTxnLgrSeq, soeOPTIONAL) +)) /** A ledger object that contains a list of ledger hashes. @@ -212,76 +230,76 @@ LEDGER_ENTRY(ltAMENDMENTS, 0x0066, Amendments, amendments, ({ \sa keylet::skip */ -LEDGER_ENTRY(ltLEDGER_HASHES, 0x0068, LedgerHashes, hashes, ({ - {sfFirstLedgerSequence, soeOPTIONAL}, - {sfLastLedgerSequence, soeOPTIONAL}, - {sfHashes, soeREQUIRED}, -})) +LEDGER_ENTRY(ltLEDGER_HASHES, 0x0068, LedgerHashes, hashes, DEFINE_LEDGER_ENTRY_FIELDS( + LEDGER_ENTRY_FIELD(sfFirstLedgerSequence, soeOPTIONAL) + LEDGER_ENTRY_FIELD(sfLastLedgerSequence, soeOPTIONAL) + LEDGER_ENTRY_FIELD(sfHashes, soeREQUIRED) +)) /** The ledger object which lists details about sidechains. \sa keylet::bridge */ -LEDGER_ENTRY(ltBRIDGE, 0x0069, Bridge, bridge, ({ - {sfAccount, soeREQUIRED}, - {sfSignatureReward, soeREQUIRED}, - {sfMinAccountCreateAmount, soeOPTIONAL}, - {sfXChainBridge, soeREQUIRED}, - {sfXChainClaimID, soeREQUIRED}, - {sfXChainAccountCreateCount, soeREQUIRED}, - {sfXChainAccountClaimCount, soeREQUIRED}, - {sfOwnerNode, soeREQUIRED}, - {sfPreviousTxnID, soeREQUIRED}, - {sfPreviousTxnLgrSeq, soeREQUIRED}, -})) +LEDGER_ENTRY(ltBRIDGE, 0x0069, Bridge, bridge, DEFINE_LEDGER_ENTRY_FIELDS( + LEDGER_ENTRY_FIELD(sfAccount, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfSignatureReward, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfMinAccountCreateAmount, soeOPTIONAL) + LEDGER_ENTRY_FIELD(sfXChainBridge, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfXChainClaimID, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfXChainAccountCreateCount, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfXChainAccountClaimCount, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfOwnerNode, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfPreviousTxnID, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfPreviousTxnLgrSeq, soeREQUIRED) +)) /** A ledger object which describes an offer on the DEX. \sa keylet::offer */ -LEDGER_ENTRY(ltOFFER, 0x006f, Offer, offer, ({ - {sfAccount, soeREQUIRED}, - {sfSequence, soeREQUIRED}, - {sfTakerPays, soeREQUIRED}, - {sfTakerGets, soeREQUIRED}, - {sfBookDirectory, soeREQUIRED}, - {sfBookNode, soeREQUIRED}, - {sfOwnerNode, soeREQUIRED}, - {sfPreviousTxnID, soeREQUIRED}, - {sfPreviousTxnLgrSeq, soeREQUIRED}, - {sfExpiration, soeOPTIONAL}, - {sfDomainID, soeOPTIONAL}, - {sfAdditionalBooks, soeOPTIONAL}, -})) +LEDGER_ENTRY(ltOFFER, 0x006f, Offer, offer, DEFINE_LEDGER_ENTRY_FIELDS( + LEDGER_ENTRY_FIELD(sfAccount, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfSequence, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfTakerPays, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfTakerGets, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfBookDirectory, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfBookNode, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfOwnerNode, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfPreviousTxnID, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfPreviousTxnLgrSeq, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfExpiration, soeOPTIONAL) + LEDGER_ENTRY_FIELD(sfDomainID, soeOPTIONAL) + LEDGER_ENTRY_FIELD(sfAdditionalBooks, soeOPTIONAL) +)) /** A ledger object which describes a deposit preauthorization. \sa keylet::depositPreauth */ -LEDGER_ENTRY_DUPLICATE(ltDEPOSIT_PREAUTH, 0x0070, DepositPreauth, deposit_preauth, ({ - {sfAccount, soeREQUIRED}, - {sfAuthorize, soeOPTIONAL}, - {sfOwnerNode, soeREQUIRED}, - {sfPreviousTxnID, soeREQUIRED}, - {sfPreviousTxnLgrSeq, soeREQUIRED}, - {sfAuthorizeCredentials, soeOPTIONAL}, -})) +LEDGER_ENTRY_DUPLICATE(ltDEPOSIT_PREAUTH, 0x0070, DepositPreauth, deposit_preauth, DEFINE_LEDGER_ENTRY_FIELDS( + LEDGER_ENTRY_FIELD(sfAccount, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfAuthorize, soeOPTIONAL) + LEDGER_ENTRY_FIELD(sfOwnerNode, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfPreviousTxnID, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfPreviousTxnLgrSeq, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfAuthorizeCredentials, soeOPTIONAL) +)) /** A claim id for a cross chain transaction. \sa keylet::xChainClaimID */ -LEDGER_ENTRY(ltXCHAIN_OWNED_CLAIM_ID, 0x0071, XChainOwnedClaimID, xchain_owned_claim_id, ({ - {sfAccount, soeREQUIRED}, - {sfXChainBridge, soeREQUIRED}, - {sfXChainClaimID, soeREQUIRED}, - {sfOtherChainSource, soeREQUIRED}, - {sfXChainClaimAttestations, soeREQUIRED}, - {sfSignatureReward, soeREQUIRED}, - {sfOwnerNode, soeREQUIRED}, - {sfPreviousTxnID, soeREQUIRED}, - {sfPreviousTxnLgrSeq, soeREQUIRED}, -})) +LEDGER_ENTRY(ltXCHAIN_OWNED_CLAIM_ID, 0x0071, XChainOwnedClaimID, xchain_owned_claim_id, DEFINE_LEDGER_ENTRY_FIELDS( + LEDGER_ENTRY_FIELD(sfAccount, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfXChainBridge, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfXChainClaimID, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfOtherChainSource, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfXChainClaimAttestations, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfSignatureReward, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfOwnerNode, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfPreviousTxnID, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfPreviousTxnLgrSeq, soeREQUIRED) +)) /** A ledger object which describes a bidirectional trust line. @@ -289,19 +307,19 @@ LEDGER_ENTRY(ltXCHAIN_OWNED_CLAIM_ID, 0x0071, XChainOwnedClaimID, xchain_owned_c \sa keylet::line */ -LEDGER_ENTRY(ltRIPPLE_STATE, 0x0072, RippleState, state, ({ - {sfBalance, soeREQUIRED}, - {sfLowLimit, soeREQUIRED}, - {sfHighLimit, soeREQUIRED}, - {sfPreviousTxnID, soeREQUIRED}, - {sfPreviousTxnLgrSeq, soeREQUIRED}, - {sfLowNode, soeOPTIONAL}, - {sfLowQualityIn, soeOPTIONAL}, - {sfLowQualityOut, soeOPTIONAL}, - {sfHighNode, soeOPTIONAL}, - {sfHighQualityIn, soeOPTIONAL}, - {sfHighQualityOut, soeOPTIONAL}, -})) +LEDGER_ENTRY(ltRIPPLE_STATE, 0x0072, RippleState, state, DEFINE_LEDGER_ENTRY_FIELDS( + LEDGER_ENTRY_FIELD(sfBalance, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfLowLimit, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfHighLimit, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfPreviousTxnID, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfPreviousTxnLgrSeq, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfLowNode, soeOPTIONAL) + LEDGER_ENTRY_FIELD(sfLowQualityIn, soeOPTIONAL) + LEDGER_ENTRY_FIELD(sfLowQualityOut, soeOPTIONAL) + LEDGER_ENTRY_FIELD(sfHighNode, soeOPTIONAL) + LEDGER_ENTRY_FIELD(sfHighQualityIn, soeOPTIONAL) + LEDGER_ENTRY_FIELD(sfHighQualityOut, soeOPTIONAL) +)) /** The ledger object which lists the network's fee settings. @@ -309,201 +327,202 @@ LEDGER_ENTRY(ltRIPPLE_STATE, 0x0072, RippleState, state, ({ \sa keylet::fees */ -LEDGER_ENTRY(ltFEE_SETTINGS, 0x0073, FeeSettings, fee, ({ +LEDGER_ENTRY(ltFEE_SETTINGS, 0x0073, FeeSettings, fee, DEFINE_LEDGER_ENTRY_FIELDS( // Old version uses raw numbers - {sfBaseFee, soeOPTIONAL}, - {sfReferenceFeeUnits, soeOPTIONAL}, - {sfReserveBase, soeOPTIONAL}, - {sfReserveIncrement, soeOPTIONAL}, + LEDGER_ENTRY_FIELD(sfBaseFee, soeOPTIONAL) + LEDGER_ENTRY_FIELD(sfReferenceFeeUnits, soeOPTIONAL) + LEDGER_ENTRY_FIELD(sfReserveBase, soeOPTIONAL) + LEDGER_ENTRY_FIELD(sfReserveIncrement, soeOPTIONAL) // New version uses Amounts - {sfBaseFeeDrops, soeOPTIONAL}, - {sfReserveBaseDrops, soeOPTIONAL}, - {sfReserveIncrementDrops, soeOPTIONAL}, - {sfPreviousTxnID, soeOPTIONAL}, - {sfPreviousTxnLgrSeq, soeOPTIONAL}, -})) + LEDGER_ENTRY_FIELD(sfBaseFeeDrops, soeOPTIONAL) + LEDGER_ENTRY_FIELD(sfReserveBaseDrops, soeOPTIONAL) + LEDGER_ENTRY_FIELD(sfReserveIncrementDrops, soeOPTIONAL) + LEDGER_ENTRY_FIELD(sfPreviousTxnID, soeOPTIONAL) + LEDGER_ENTRY_FIELD(sfPreviousTxnLgrSeq, soeOPTIONAL) +)) /** A claim id for a cross chain create account transaction. \sa keylet::xChainCreateAccountClaimID */ -LEDGER_ENTRY(ltXCHAIN_OWNED_CREATE_ACCOUNT_CLAIM_ID, 0x0074, XChainOwnedCreateAccountClaimID, xchain_owned_create_account_claim_id, ({ - {sfAccount, soeREQUIRED}, - {sfXChainBridge, soeREQUIRED}, - {sfXChainAccountCreateCount, soeREQUIRED}, - {sfXChainCreateAccountAttestations, soeREQUIRED}, - {sfOwnerNode, soeREQUIRED}, - {sfPreviousTxnID, soeREQUIRED}, - {sfPreviousTxnLgrSeq, soeREQUIRED}, -})) +LEDGER_ENTRY(ltXCHAIN_OWNED_CREATE_ACCOUNT_CLAIM_ID, 0x0074, XChainOwnedCreateAccountClaimID, xchain_owned_create_account_claim_id, DEFINE_LEDGER_ENTRY_FIELDS( + LEDGER_ENTRY_FIELD(sfAccount, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfXChainBridge, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfXChainAccountCreateCount, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfXChainCreateAccountAttestations, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfOwnerNode, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfPreviousTxnID, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfPreviousTxnLgrSeq, soeREQUIRED) +)) /** A ledger object describing a single escrow. \sa keylet::escrow */ -LEDGER_ENTRY(ltESCROW, 0x0075, Escrow, escrow, ({ - {sfAccount, soeREQUIRED}, - {sfDestination, soeREQUIRED}, - {sfAmount, soeREQUIRED}, - {sfCondition, soeOPTIONAL}, - {sfCancelAfter, soeOPTIONAL}, - {sfFinishAfter, soeOPTIONAL}, - {sfSourceTag, soeOPTIONAL}, - {sfDestinationTag, soeOPTIONAL}, - {sfOwnerNode, soeREQUIRED}, - {sfPreviousTxnID, soeREQUIRED}, - {sfPreviousTxnLgrSeq, soeREQUIRED}, - {sfDestinationNode, soeOPTIONAL}, - {sfTransferRate, soeOPTIONAL}, - {sfIssuerNode, soeOPTIONAL}, -})) +LEDGER_ENTRY(ltESCROW, 0x0075, Escrow, escrow, DEFINE_LEDGER_ENTRY_FIELDS( + LEDGER_ENTRY_FIELD(sfAccount, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfDestination, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfAmount, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfCondition, soeOPTIONAL) + LEDGER_ENTRY_FIELD(sfCancelAfter, soeOPTIONAL) + LEDGER_ENTRY_FIELD(sfFinishAfter, soeOPTIONAL) + LEDGER_ENTRY_FIELD(sfSourceTag, soeOPTIONAL) + LEDGER_ENTRY_FIELD(sfDestinationTag, soeOPTIONAL) + LEDGER_ENTRY_FIELD(sfOwnerNode, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfPreviousTxnID, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfPreviousTxnLgrSeq, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfDestinationNode, soeOPTIONAL) + LEDGER_ENTRY_FIELD(sfTransferRate, soeOPTIONAL) + LEDGER_ENTRY_FIELD(sfIssuerNode, soeOPTIONAL) +)) /** A ledger object describing a single unidirectional XRP payment channel. \sa keylet::payChan */ -LEDGER_ENTRY(ltPAYCHAN, 0x0078, PayChannel, payment_channel, ({ - {sfAccount, soeREQUIRED}, - {sfDestination, soeREQUIRED}, - {sfAmount, soeREQUIRED}, - {sfBalance, soeREQUIRED}, - {sfPublicKey, soeREQUIRED}, - {sfSettleDelay, soeREQUIRED}, - {sfExpiration, soeOPTIONAL}, - {sfCancelAfter, soeOPTIONAL}, - {sfSourceTag, soeOPTIONAL}, - {sfDestinationTag, soeOPTIONAL}, - {sfOwnerNode, soeREQUIRED}, - {sfPreviousTxnID, soeREQUIRED}, - {sfPreviousTxnLgrSeq, soeREQUIRED}, - {sfDestinationNode, soeOPTIONAL}, -})) +LEDGER_ENTRY(ltPAYCHAN, 0x0078, PayChannel, payment_channel, DEFINE_LEDGER_ENTRY_FIELDS( + LEDGER_ENTRY_FIELD(sfAccount, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfDestination, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfAmount, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfBalance, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfPublicKey, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfSettleDelay, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfExpiration, soeOPTIONAL) + LEDGER_ENTRY_FIELD(sfCancelAfter, soeOPTIONAL) + LEDGER_ENTRY_FIELD(sfSourceTag, soeOPTIONAL) + LEDGER_ENTRY_FIELD(sfDestinationTag, soeOPTIONAL) + LEDGER_ENTRY_FIELD(sfOwnerNode, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfPreviousTxnID, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfPreviousTxnLgrSeq, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfDestinationNode, soeOPTIONAL) +)) /** The ledger object which tracks the AMM. \sa keylet::amm */ -LEDGER_ENTRY(ltAMM, 0x0079, AMM, amm, ({ - {sfAccount, soeREQUIRED}, - {sfTradingFee, soeDEFAULT}, - {sfVoteSlots, soeOPTIONAL}, - {sfAuctionSlot, soeOPTIONAL}, - {sfLPTokenBalance, soeREQUIRED}, - {sfAsset, soeREQUIRED}, - {sfAsset2, soeREQUIRED}, - {sfOwnerNode, soeREQUIRED}, - {sfPreviousTxnID, soeOPTIONAL}, - {sfPreviousTxnLgrSeq, soeOPTIONAL}, -})) +LEDGER_ENTRY(ltAMM, 0x0079, AMM, amm, DEFINE_LEDGER_ENTRY_FIELDS( + LEDGER_ENTRY_FIELD(sfAccount, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfTradingFee, soeDEFAULT) + LEDGER_ENTRY_FIELD(sfVoteSlots, soeOPTIONAL) + LEDGER_ENTRY_FIELD(sfAuctionSlot, soeOPTIONAL) + LEDGER_ENTRY_FIELD(sfLPTokenBalance, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfAsset, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfAsset2, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfOwnerNode, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfPreviousTxnID, soeOPTIONAL) + LEDGER_ENTRY_FIELD(sfPreviousTxnLgrSeq, soeOPTIONAL) +)) /** A ledger object which tracks MPTokenIssuance \sa keylet::mptIssuance */ -LEDGER_ENTRY(ltMPTOKEN_ISSUANCE, 0x007e, MPTokenIssuance, mpt_issuance, ({ - {sfIssuer, soeREQUIRED}, - {sfSequence, soeREQUIRED}, - {sfTransferFee, soeDEFAULT}, - {sfOwnerNode, soeREQUIRED}, - {sfAssetScale, soeDEFAULT}, - {sfMaximumAmount, soeOPTIONAL}, - {sfOutstandingAmount, soeREQUIRED}, - {sfLockedAmount, soeOPTIONAL}, - {sfMPTokenMetadata, soeOPTIONAL}, - {sfPreviousTxnID, soeREQUIRED}, - {sfPreviousTxnLgrSeq, soeREQUIRED}, - {sfDomainID, soeOPTIONAL}, -})) +LEDGER_ENTRY(ltMPTOKEN_ISSUANCE, 0x007e, MPTokenIssuance, mpt_issuance, DEFINE_LEDGER_ENTRY_FIELDS( + LEDGER_ENTRY_FIELD(sfIssuer, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfSequence, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfTransferFee, soeDEFAULT) + LEDGER_ENTRY_FIELD(sfOwnerNode, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfAssetScale, soeDEFAULT) + LEDGER_ENTRY_FIELD(sfMaximumAmount, soeOPTIONAL) + LEDGER_ENTRY_FIELD(sfOutstandingAmount, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfLockedAmount, soeOPTIONAL) + LEDGER_ENTRY_FIELD(sfMPTokenMetadata, soeOPTIONAL) + LEDGER_ENTRY_FIELD(sfPreviousTxnID, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfPreviousTxnLgrSeq, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfDomainID, soeOPTIONAL) +)) /** A ledger object which tracks MPToken \sa keylet::mptoken */ -LEDGER_ENTRY(ltMPTOKEN, 0x007f, MPToken, mptoken, ({ - {sfAccount, soeREQUIRED}, - {sfMPTokenIssuanceID, soeREQUIRED}, - {sfMPTAmount, soeDEFAULT}, - {sfLockedAmount, soeOPTIONAL}, - {sfOwnerNode, soeREQUIRED}, - {sfPreviousTxnID, soeREQUIRED}, - {sfPreviousTxnLgrSeq, soeREQUIRED}, -})) +LEDGER_ENTRY(ltMPTOKEN, 0x007f, MPToken, mptoken, DEFINE_LEDGER_ENTRY_FIELDS( + LEDGER_ENTRY_FIELD(sfAccount, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfMPTokenIssuanceID, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfMPTAmount, soeDEFAULT) + LEDGER_ENTRY_FIELD(sfLockedAmount, soeOPTIONAL) + LEDGER_ENTRY_FIELD(sfOwnerNode, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfPreviousTxnID, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfPreviousTxnLgrSeq, soeREQUIRED) +)) /** A ledger object which tracks Oracle \sa keylet::oracle */ -LEDGER_ENTRY(ltORACLE, 0x0080, Oracle, oracle, ({ - {sfOwner, soeREQUIRED}, - {sfProvider, soeREQUIRED}, - {sfPriceDataSeries, soeREQUIRED}, - {sfAssetClass, soeREQUIRED}, - {sfLastUpdateTime, soeREQUIRED}, - {sfURI, soeOPTIONAL}, - {sfOwnerNode, soeREQUIRED}, - {sfPreviousTxnID, soeREQUIRED}, - {sfPreviousTxnLgrSeq, soeREQUIRED}, -})) +LEDGER_ENTRY(ltORACLE, 0x0080, Oracle, oracle, DEFINE_LEDGER_ENTRY_FIELDS( + LEDGER_ENTRY_FIELD(sfOwner, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfProvider, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfPriceDataSeries, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfAssetClass, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfLastUpdateTime, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfURI, soeOPTIONAL) + LEDGER_ENTRY_FIELD(sfOwnerNode, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfPreviousTxnID, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfPreviousTxnLgrSeq, soeREQUIRED) +)) /** A ledger object which tracks Credential \sa keylet::credential */ -LEDGER_ENTRY(ltCREDENTIAL, 0x0081, Credential, credential, ({ - {sfSubject, soeREQUIRED}, - {sfIssuer, soeREQUIRED}, - {sfCredentialType, soeREQUIRED}, - {sfExpiration, soeOPTIONAL}, - {sfURI, soeOPTIONAL}, - {sfIssuerNode, soeREQUIRED}, - {sfSubjectNode, soeREQUIRED}, - {sfPreviousTxnID, soeREQUIRED}, - {sfPreviousTxnLgrSeq, soeREQUIRED}, -})) +LEDGER_ENTRY(ltCREDENTIAL, 0x0081, Credential, credential, DEFINE_LEDGER_ENTRY_FIELDS( + LEDGER_ENTRY_FIELD(sfSubject, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfIssuer, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfCredentialType, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfExpiration, soeOPTIONAL) + LEDGER_ENTRY_FIELD(sfURI, soeOPTIONAL) + LEDGER_ENTRY_FIELD(sfIssuerNode, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfSubjectNode, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfPreviousTxnID, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfPreviousTxnLgrSeq, soeREQUIRED) +)) /** A ledger object which tracks PermissionedDomain \sa keylet::permissionedDomain */ -LEDGER_ENTRY(ltPERMISSIONED_DOMAIN, 0x0082, PermissionedDomain, permissioned_domain, ({ - {sfOwner, soeREQUIRED}, - {sfSequence, soeREQUIRED}, - {sfAcceptedCredentials, soeREQUIRED}, - {sfOwnerNode, soeREQUIRED}, - {sfPreviousTxnID, soeREQUIRED}, - {sfPreviousTxnLgrSeq, soeREQUIRED}, -})) +LEDGER_ENTRY(ltPERMISSIONED_DOMAIN, 0x0082, PermissionedDomain, permissioned_domain, DEFINE_LEDGER_ENTRY_FIELDS( + LEDGER_ENTRY_FIELD(sfOwner, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfSequence, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfAcceptedCredentials, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfOwnerNode, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfPreviousTxnID, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfPreviousTxnLgrSeq, soeREQUIRED) +)) /** A ledger object representing permissions an account has delegated to another account. \sa keylet::delegate */ -LEDGER_ENTRY(ltDELEGATE, 0x0083, Delegate, delegate, ({ - {sfAccount, soeREQUIRED}, - {sfAuthorize, soeREQUIRED}, - {sfPermissions, soeREQUIRED}, - {sfOwnerNode, soeREQUIRED}, - {sfPreviousTxnID, soeREQUIRED}, - {sfPreviousTxnLgrSeq, soeREQUIRED}, -})) +LEDGER_ENTRY(ltDELEGATE, 0x0083, Delegate, delegate, DEFINE_LEDGER_ENTRY_FIELDS( + LEDGER_ENTRY_FIELD(sfAccount, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfAuthorize, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfPermissions, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfOwnerNode, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfPreviousTxnID, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfPreviousTxnLgrSeq, soeREQUIRED) +)) /** A ledger object representing a single asset vault. \sa keylet::mptoken */ -LEDGER_ENTRY(ltVAULT, 0x0084, Vault, vault, ({ - {sfPreviousTxnID, soeREQUIRED}, - {sfPreviousTxnLgrSeq, soeREQUIRED}, - {sfSequence, soeREQUIRED}, - {sfOwnerNode, soeREQUIRED}, - {sfOwner, soeREQUIRED}, - {sfAccount, soeREQUIRED}, - {sfData, soeOPTIONAL}, - {sfAsset, soeREQUIRED}, - {sfAssetsTotal, soeREQUIRED}, - {sfAssetsAvailable, soeREQUIRED}, - {sfAssetsMaximum, soeDEFAULT}, - {sfLossUnrealized, soeREQUIRED}, - {sfShareMPTID, soeREQUIRED}, - {sfWithdrawalPolicy, soeREQUIRED}, +LEDGER_ENTRY(ltVAULT, 0x0084, Vault, vault, DEFINE_LEDGER_ENTRY_FIELDS( + LEDGER_ENTRY_FIELD(sfPreviousTxnID, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfPreviousTxnLgrSeq, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfSequence, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfOwnerNode, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfOwner, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfAccount, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfData, soeOPTIONAL) + LEDGER_ENTRY_FIELD(sfAsset, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfAssetsTotal, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfAssetsAvailable, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfAssetsMaximum, soeDEFAULT) + LEDGER_ENTRY_FIELD(sfLossUnrealized, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfShareMPTID, soeREQUIRED) + LEDGER_ENTRY_FIELD(sfWithdrawalPolicy, soeREQUIRED) // no SharesTotal ever (use MPTIssuance.sfOutstandingAmount) // no PermissionedDomainID ever (use MPTIssuance.sfDomainID) -})) +)) #undef EXPAND #undef LEDGER_ENTRY_DUPLICATE +LEDGER_ENTRIES_END diff --git a/include/xrpl/protocol/detail/sfields.macro b/include/xrpl/protocol/detail/sfields.macro index 537fcae479..46ebd1afd8 100644 --- a/include/xrpl/protocol/detail/sfields.macro +++ b/include/xrpl/protocol/detail/sfields.macro @@ -23,6 +23,9 @@ #if !defined(TYPED_SFIELD) #error "undefined macro: TYPED_SFIELD" #endif +#if !defined(ARRAY_SFIELD) +#error "undefined macro: ARRAY_SFIELD" +#endif // untyped UNTYPED_SFIELD(sfLedgerEntry, LEDGERENTRY, 257) @@ -366,33 +369,33 @@ UNTYPED_SFIELD(sfBook, OBJECT, 36) // array of objects (common) // ARRAY/1 is reserved for end of array // sfSigningAccounts has never been used. -//UNTYPED_SFIELD(sfSigningAccounts, ARRAY, 2) -UNTYPED_SFIELD(sfSigners, ARRAY, 3, SField::sMD_Default, SField::notSigning) -UNTYPED_SFIELD(sfSignerEntries, ARRAY, 4) -UNTYPED_SFIELD(sfTemplate, ARRAY, 5) -UNTYPED_SFIELD(sfNecessary, ARRAY, 6) -UNTYPED_SFIELD(sfSufficient, ARRAY, 7) -UNTYPED_SFIELD(sfAffectedNodes, ARRAY, 8) -UNTYPED_SFIELD(sfMemos, ARRAY, 9) -UNTYPED_SFIELD(sfNFTokens, ARRAY, 10) -UNTYPED_SFIELD(sfHooks, ARRAY, 11) -UNTYPED_SFIELD(sfVoteSlots, ARRAY, 12) -UNTYPED_SFIELD(sfAdditionalBooks, ARRAY, 13) +//UNTYPED_SFIELD(sfSigningAccounts, sfInvalid, ARRAY, 2) +ARRAY_SFIELD(sfSigners, sfSigner, ARRAY, 3, SField::sMD_Default, SField::notSigning) +ARRAY_SFIELD(sfSignerEntries, sfSignerEntry, ARRAY, 4) +ARRAY_SFIELD(sfTemplate, sfInvalid, ARRAY, 5) +ARRAY_SFIELD(sfNecessary, sfInvalid, ARRAY, 6) +ARRAY_SFIELD(sfSufficient, sfInvalid, ARRAY, 7) +ARRAY_SFIELD(sfAffectedNodes, sfInvalid, ARRAY, 8) +ARRAY_SFIELD(sfMemos, sfInvalid, ARRAY, 9) +ARRAY_SFIELD(sfNFTokens, sfNFToken, ARRAY, 10) +ARRAY_SFIELD(sfHooks, sfInvalid, ARRAY, 11) +ARRAY_SFIELD(sfVoteSlots, sfVoteEntry, ARRAY, 12) +ARRAY_SFIELD(sfAdditionalBooks, sfInvalid, ARRAY, 13) // array of objects (uncommon) -UNTYPED_SFIELD(sfMajorities, ARRAY, 16) -UNTYPED_SFIELD(sfDisabledValidators, ARRAY, 17) -UNTYPED_SFIELD(sfHookExecutions, ARRAY, 18) -UNTYPED_SFIELD(sfHookParameters, ARRAY, 19) -UNTYPED_SFIELD(sfHookGrants, ARRAY, 20) -UNTYPED_SFIELD(sfXChainClaimAttestations, ARRAY, 21) -UNTYPED_SFIELD(sfXChainCreateAccountAttestations, ARRAY, 22) +ARRAY_SFIELD(sfMajorities, sfMajority, ARRAY, 16) +ARRAY_SFIELD(sfDisabledValidators, sfDisabledValidator, ARRAY, 17) +ARRAY_SFIELD(sfHookExecutions, sfInvalid, ARRAY, 18) +ARRAY_SFIELD(sfHookParameters, sfInvalid, ARRAY, 19) +ARRAY_SFIELD(sfHookGrants, sfInvalid, ARRAY, 20) +ARRAY_SFIELD(sfXChainClaimAttestations, sfInvalid, ARRAY, 21) +ARRAY_SFIELD(sfXChainCreateAccountAttestations, sfInvalid, ARRAY, 22) // 23 unused -UNTYPED_SFIELD(sfPriceDataSeries, ARRAY, 24) -UNTYPED_SFIELD(sfAuthAccounts, ARRAY, 25) -UNTYPED_SFIELD(sfAuthorizeCredentials, ARRAY, 26) -UNTYPED_SFIELD(sfUnauthorizeCredentials, ARRAY, 27) -UNTYPED_SFIELD(sfAcceptedCredentials, ARRAY, 28) -UNTYPED_SFIELD(sfPermissions, ARRAY, 29) -UNTYPED_SFIELD(sfRawTransactions, ARRAY, 30) -UNTYPED_SFIELD(sfBatchSigners, ARRAY, 31, SField::sMD_Default, SField::notSigning) +ARRAY_SFIELD(sfPriceDataSeries, sfPriceData, ARRAY, 24) +ARRAY_SFIELD(sfAuthAccounts, sfAuthAccount, ARRAY, 25) +ARRAY_SFIELD(sfAuthorizeCredentials, sfInvalid, ARRAY, 26) +ARRAY_SFIELD(sfUnauthorizeCredentials, sfInvalid, ARRAY, 27) +ARRAY_SFIELD(sfAcceptedCredentials, sfInvalid, ARRAY, 28) +ARRAY_SFIELD(sfPermissions, sfPermission, ARRAY, 29) +ARRAY_SFIELD(sfRawTransactions, sfInvalid, ARRAY, 30) +ARRAY_SFIELD(sfBatchSigners, sfBatchSigner, ARRAY, 31, SField::sMD_Default, SField::notSigning) diff --git a/include/xrpl/protocol/jss.h b/include/xrpl/protocol/jss.h index 67a045fa58..ad232303cf 100644 --- a/include/xrpl/protocol/jss.h +++ b/include/xrpl/protocol/jss.h @@ -717,7 +717,19 @@ JSS(write_load); // out: GetCounts #undef LEDGER_ENTRY #pragma push_macro("LEDGER_ENTRY_DUPLICATE") #undef LEDGER_ENTRY_DUPLICATE +#pragma push_macro("LEDGER_ENTRY_FIELD") +#undef LEDGER_ENTRY_FIELD +#pragma push_macro("DEFINE_LEDGER_ENTRY_FIELDS") +#undef DEFINE_LEDGER_ENTRY_FIELDS +#pragma push_macro("LEDGER_ENTRIES_BEGIN") +#undef LEDGER_ENTRIES_BEGIN +#pragma push_macro("LEDGER_ENTRIES_END") +#undef LEDGER_ENTRIES_END +#define LEDGER_ENTRIES_BEGIN +#define LEDGER_ENTRIES_END +#define DEFINE_LEDGER_ENTRY_FIELDS(...) ({__VA_ARGS__}) +#define LEDGER_ENTRY_FIELD(...) {__VA_ARGS__}, #define LEDGER_ENTRY(tag, value, name, rpcName, fields) \ JSS(name); \ JSS(rpcName); @@ -730,6 +742,14 @@ JSS(write_load); // out: GetCounts #pragma pop_macro("LEDGER_ENTRY") #undef LEDGER_ENTRY_DUPLICATE #pragma pop_macro("LEDGER_ENTRY_DUPLICATE") +#undef LEDGER_ENTRY_FIELD +#pragma pop_macro("LEDGER_ENTRY_FIELD") +#undef DEFINE_LEDGER_ENTRY_FIELDS +#pragma pop_macro("DEFINE_LEDGER_ENTRY_FIELDS") +#undef LEDGER_ENTRIES_BEGIN +#pragma pop_macro("LEDGER_ENTRIES_BEGIN") +#undef LEDGER_ENTRIES_END +#pragma pop_macro("LEDGER_ENTRIES_END") #undef JSS diff --git a/src/libxrpl/protocol/LedgerFormats.cpp b/src/libxrpl/protocol/LedgerFormats.cpp index 94c6d65c88..837dfd255c 100644 --- a/src/libxrpl/protocol/LedgerFormats.cpp +++ b/src/libxrpl/protocol/LedgerFormats.cpp @@ -39,8 +39,20 @@ LedgerFormats::LedgerFormats() #undef UNWRAP #pragma push_macro("LEDGER_ENTRY") #undef LEDGER_ENTRY +#pragma push_macro("LEDGER_ENTRY_FIELD") +#undef LEDGER_ENTRY_FIELD +#pragma push_macro("DEFINE_LEDGER_ENTRY_FIELDS") +#undef DEFINE_LEDGER_ENTRY_FIELDS +#pragma push_macro("LEDGER_ENTRIES_BEGIN") +#undef LEDGER_ENTRIES_BEGIN +#pragma push_macro("LEDGER_ENTRIES_END") +#undef LEDGER_ENTRIES_END +#define LEDGER_ENTRIES_BEGIN +#define LEDGER_ENTRIES_END +#define DEFINE_LEDGER_ENTRY_FIELDS(...) ({__VA_ARGS__}) #define UNWRAP(...) __VA_ARGS__ +#define LEDGER_ENTRY_FIELD(...) {__VA_ARGS__}, #define LEDGER_ENTRY(tag, value, name, rpcName, fields) \ add(jss::name, tag, UNWRAP fields, commonFields); @@ -48,6 +60,14 @@ LedgerFormats::LedgerFormats() #undef LEDGER_ENTRY #pragma pop_macro("LEDGER_ENTRY") +#undef LEDGER_ENTRY_FIELD +#pragma pop_macro("LEDGER_ENTRY_FIELD") +#undef DEFINE_LEDGER_ENTRY_FIELDS +#pragma pop_macro("DEFINE_LEDGER_ENTRY_FIELDS") +#undef LEDGER_ENTRIES_BEGIN +#pragma pop_macro("LEDGER_ENTRIES_BEGIN") +#undef LEDGER_ENTRIES_END +#pragma pop_macro("LEDGER_ENTRIES_END") #undef UNWRAP #pragma pop_macro("UNWRAP") } diff --git a/src/libxrpl/protocol/SField.cpp b/src/libxrpl/protocol/SField.cpp index 1ffce099b8..7492205731 100644 --- a/src/libxrpl/protocol/SField.cpp +++ b/src/libxrpl/protocol/SField.cpp @@ -52,6 +52,8 @@ TypedField::TypedField(private_access_tag_t pat, Args&&... args) #undef UNTYPED_SFIELD #pragma push_macro("TYPED_SFIELD") #undef TYPED_SFIELD +#pragma push_macro("ARRAY_SFIELD") +#undef ARRAY_SFIELD #define UNTYPED_SFIELD(sfName, stiSuffix, fieldValue, ...) \ SField const sfName( \ @@ -67,6 +69,13 @@ TypedField::TypedField(private_access_tag_t pat, Args&&... args) fieldValue, \ std::string_view(#sfName).substr(2).data(), \ ##__VA_ARGS__); +#define ARRAY_SFIELD(sfName, sfItemName, stiSuffix, fieldValue, ...) \ + SField const sfName( \ + access, \ + STI_##stiSuffix, \ + fieldValue, \ + std::string_view(#sfName).substr(2).data(), \ + ##__VA_ARGS__); // SFields which, for historical reasons, do not follow naming conventions. SField const sfInvalid(access, -1); @@ -82,6 +91,8 @@ SField const sfIndex(access, STI_UINT256, 258, "index"); #pragma pop_macro("TYPED_SFIELD") #undef UNTYPED_SFIELD #pragma pop_macro("UNTYPED_SFIELD") +#undef ARRAY_SFIELD +#pragma pop_macro("ARRAY_SFIELD") SField::SField( private_access_tag_t, diff --git a/src/test/protocol/TypedLedgerEntries_test.cpp b/src/test/protocol/TypedLedgerEntries_test.cpp new file mode 100644 index 0000000000..b315402ae7 --- /dev/null +++ b/src/test/protocol/TypedLedgerEntries_test.cpp @@ -0,0 +1,113 @@ +//------------------------------------------------------------------------------ +/* + This file is part of rippled: https://github.com/ripple/rippled + Copyright (c) 2025 Ripple Labs Inc. + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#include +#include +#include + +namespace ripple { + +struct TypedLedgerEntries_test : public beast::unit_test::suite +{ + void + testGet() + { + testcase("testGet"); + + auto object = std::make_shared(ltSIGNER_LIST, uint256{}); + STArray signerEntries; + STObject signerEntry{sfSignerEntry}; + signerEntry[sfAccount] = AccountID{1}; + signerEntry[sfSignerWeight] = 2; + signerEntry[sfWalletLocator] = uint256{3}; + signerEntries.emplace_back(signerEntry); + + (*object)[sfOwnerNode] = 1UL; + (*object)[sfSignerQuorum] = 2U; + (*object)[sfSignerListID] = 3U; + (*object)[sfPreviousTxnLgrSeq] = 4U; + (*object)[sfPreviousTxnID] = uint256{5}; + (*object).setFieldArray(sfSignerEntries, signerEntries); + + auto entry = LedgerObjectType::fromObject(object); + BEAST_EXPECT(entry.fsfOwnerNode() == 1); + BEAST_EXPECT(entry.fsfSignerQuorum() == 2); + BEAST_EXPECT(entry.fsfSignerListID() == 3); + BEAST_EXPECT(entry.fsfPreviousTxnLgrSeq() == 4); + BEAST_EXPECT(entry.fsfPreviousTxnID() == uint256{5}); + BEAST_EXPECT(entry.fsfSignerEntries().size() == 1); + + BEAST_EXPECT( + entry.fsfSignerEntries()[0].fsfAccount().value() == AccountID{1}); + BEAST_EXPECT(entry.fsfSignerEntries()[0].fsfSignerWeight() == 2); + BEAST_EXPECT( + entry.fsfSignerEntries()[0].fsfWalletLocator() == uint256{3}); + } + + void + testSet() + { + testcase("testSet"); + auto new_object = LedgerObjectType::create(uint256{}); + + new_object.fsfOwnerNode() = 1; + new_object.fsfSignerQuorum() = 2; + new_object.fsfSignerListID() = 3; + new_object.fsfPreviousTxnLgrSeq() = 4; + new_object.fsfPreviousTxnID() = uint256{5}; + auto signerEntry = new_object.fsfSignerEntries().createItem(); + signerEntry.fsfAccount() = AccountID{1}; + signerEntry.fsfSignerWeight() = 2; + signerEntry.fsfWalletLocator() = uint256{3}; + new_object.fsfSignerEntries().push_back(signerEntry); + + auto& object = *new_object.getObject(); + + BEAST_EXPECT(object[sfOwnerNode] == new_object.fsfOwnerNode()); + BEAST_EXPECT(object[sfSignerQuorum] == new_object.fsfSignerQuorum()); + BEAST_EXPECT(object[sfSignerListID] == new_object.fsfSignerListID()); + BEAST_EXPECT( + object[sfPreviousTxnLgrSeq] == new_object.fsfPreviousTxnLgrSeq()); + BEAST_EXPECT(object[sfPreviousTxnID] == new_object.fsfPreviousTxnID()); + BEAST_EXPECT( + object.getFieldArray(sfSignerEntries).size() == + new_object.fsfSignerEntries().size()); + + auto entries = object.getFieldArray(sfSignerEntries); + BEAST_EXPECT( + entries[0][sfAccount] == + new_object.fsfSignerEntries()[0].fsfAccount()); + BEAST_EXPECT( + entries[0][sfSignerWeight] == + new_object.fsfSignerEntries()[0].fsfSignerWeight()); + BEAST_EXPECT( + entries[0][sfWalletLocator] == + new_object.fsfSignerEntries()[0].fsfWalletLocator()); + } + + void + run() override + { + testGet(); + testSet(); + } +}; + +BEAST_DEFINE_TESTSUITE(TypedLedgerEntries, protocol, ripple); +} // namespace ripple diff --git a/src/xrpld/rpc/detail/RPCHelpers.cpp b/src/xrpld/rpc/detail/RPCHelpers.cpp index b98f31340a..8dcaa28762 100644 --- a/src/xrpld/rpc/detail/RPCHelpers.cpp +++ b/src/xrpld/rpc/detail/RPCHelpers.cpp @@ -937,7 +937,20 @@ chooseLedgerEntryType(Json::Value const& params) std::tuple>({ #pragma push_macro("LEDGER_ENTRY") #undef LEDGER_ENTRY +#pragma push_macro("LEDGER_ENTRY_FIELD") +#undef LEDGER_ENTRY_FIELD +#pragma push_macro("DEFINE_LEDGER_ENTRY_FIELDS") +#undef DEFINE_LEDGER_ENTRY_FIELDS +#pragma push_macro("LEDGER_ENTRIES_BEGIN") +#undef LEDGER_ENTRIES_BEGIN +#pragma push_macro("LEDGER_ENTRIES_END") +#undef LEDGER_ENTRIES_END +#define LEDGER_ENTRIES_BEGIN +#define LEDGER_ENTRIES_END + +#define DEFINE_LEDGER_ENTRY_FIELDS(...) ({__VA_ARGS__}) +#define LEDGER_ENTRY_FIELD(...) {__VA_ARGS__}, #define LEDGER_ENTRY(tag, value, name, rpcName, fields) \ {jss::name, jss::rpcName, tag}, @@ -945,6 +958,14 @@ chooseLedgerEntryType(Json::Value const& params) #undef LEDGER_ENTRY #pragma pop_macro("LEDGER_ENTRY") +#undef LEDGER_ENTRY_FIELD +#pragma pop_macro("LEDGER_ENTRY_FIELD") +#undef DEFINE_LEDGER_ENTRY_FIELDS +#pragma pop_macro("DEFINE_LEDGER_ENTRY_FIELDS") +#undef LEDGER_ENTRIES_BEGIN +#pragma pop_macro("LEDGER_ENTRIES_BEGIN") +#undef LEDGER_ENTRIES_END +#pragma pop_macro("LEDGER_ENTRIES_END") }); auto const& p = params[jss::type];