mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-20 02:55:50 +00:00
[WIP] Turns out that adding a new serialized type is harder than it looks
This commit is contained in:
@@ -49,6 +49,8 @@ template <int>
|
|||||||
class STBitString;
|
class STBitString;
|
||||||
template <class>
|
template <class>
|
||||||
class STInteger;
|
class STInteger;
|
||||||
|
template <class>
|
||||||
|
class STTypedInteger;
|
||||||
class STNumber;
|
class STNumber;
|
||||||
class STXChainBridge;
|
class STXChainBridge;
|
||||||
class STVector256;
|
class STVector256;
|
||||||
@@ -89,6 +91,8 @@ class STCurrency;
|
|||||||
STYPE(STI_ISSUE, 24) \
|
STYPE(STI_ISSUE, 24) \
|
||||||
STYPE(STI_XCHAIN_BRIDGE, 25) \
|
STYPE(STI_XCHAIN_BRIDGE, 25) \
|
||||||
STYPE(STI_CURRENCY, 26) \
|
STYPE(STI_CURRENCY, 26) \
|
||||||
|
STYPE(STI_TENTHBIPS16, 27) \
|
||||||
|
STYPE(STI_TENTHBIPS32, 28) \
|
||||||
\
|
\
|
||||||
/* high-level types */ \
|
/* high-level types */ \
|
||||||
/* cannot be serialized inside other types */ \
|
/* cannot be serialized inside other types */ \
|
||||||
@@ -358,15 +362,12 @@ using SF_UINT256 = TypedField<STBitString<256>>;
|
|||||||
using SF_UINT384 = TypedField<STBitString<384>>;
|
using SF_UINT384 = TypedField<STBitString<384>>;
|
||||||
using SF_UINT512 = TypedField<STBitString<512>>;
|
using SF_UINT512 = TypedField<STBitString<512>>;
|
||||||
|
|
||||||
// These BIPS and TENTHBIPS values are serialized as the underlying type.
|
// These TENTHBIPS values are serialized as the underlying type.
|
||||||
// The tag is only applied when deserialized.
|
// The tag is only applied when deserialized.
|
||||||
//
|
//
|
||||||
// Basis points (bips) values:
|
|
||||||
using SF_BIPS16 = TypedField<STInteger<Bips16>>;
|
|
||||||
using SF_BIPS32 = TypedField<STInteger<Bips32>>;
|
|
||||||
// Tenth of a basis point values:
|
// Tenth of a basis point values:
|
||||||
using SF_TENTHBIPS16 = TypedField<STInteger<TenthBips16>>;
|
using SF_TENTHBIPS16 = TypedField<STTypedInteger<TenthBips16>>;
|
||||||
using SF_TENTHBIPS32 = TypedField<STInteger<TenthBips32>>;
|
using SF_TENTHBIPS32 = TypedField<STTypedInteger<TenthBips32>>;
|
||||||
|
|
||||||
using SF_ACCOUNT = TypedField<STAccount>;
|
using SF_ACCOUNT = TypedField<STAccount>;
|
||||||
using SF_AMOUNT = TypedField<STAmount>;
|
using SF_AMOUNT = TypedField<STAmount>;
|
||||||
@@ -384,23 +385,17 @@ using SF_XCHAIN_BRIDGE = TypedField<STXChainBridge>;
|
|||||||
#undef UNTYPED_SFIELD
|
#undef UNTYPED_SFIELD
|
||||||
#pragma push_macro("TYPED_SFIELD")
|
#pragma push_macro("TYPED_SFIELD")
|
||||||
#undef TYPED_SFIELD
|
#undef TYPED_SFIELD
|
||||||
#pragma push_macro("INTERPRETED_SFIELD")
|
|
||||||
#undef INTERPRETED_SFIELD
|
|
||||||
|
|
||||||
#define UNTYPED_SFIELD(sfName, stiSuffix, fieldValue, ...) \
|
#define UNTYPED_SFIELD(sfName, stiSuffix, fieldValue, ...) \
|
||||||
extern SField const sfName;
|
extern SField const sfName;
|
||||||
#define TYPED_SFIELD(sfName, stiSuffix, fieldValue, ...) \
|
#define TYPED_SFIELD(sfName, stiSuffix, fieldValue, ...) \
|
||||||
extern SF_##stiSuffix const sfName;
|
extern SF_##stiSuffix const sfName;
|
||||||
#define INTERPRETED_SFIELD(sfName, stiSuffix, fieldValue, stiInterpreted, ...) \
|
|
||||||
extern SF_##stiInterpreted const sfName;
|
|
||||||
|
|
||||||
extern SField const sfInvalid;
|
extern SField const sfInvalid;
|
||||||
extern SField const sfGeneric;
|
extern SField const sfGeneric;
|
||||||
|
|
||||||
#include <xrpl/protocol/detail/sfields.macro>
|
#include <xrpl/protocol/detail/sfields.macro>
|
||||||
|
|
||||||
#undef INTERPRETED_SFIELD
|
|
||||||
#pragma pop_macro("INTERPRETED_SFIELD")
|
|
||||||
#undef TYPED_SFIELD
|
#undef TYPED_SFIELD
|
||||||
#pragma pop_macro("TYPED_SFIELD")
|
#pragma pop_macro("TYPED_SFIELD")
|
||||||
#undef UNTYPED_SFIELD
|
#undef UNTYPED_SFIELD
|
||||||
|
|||||||
@@ -61,6 +61,26 @@ struct STExchange<STInteger<U>, T>
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <class U, class T>
|
||||||
|
struct STExchange<STTypedInteger<U>, T>
|
||||||
|
{
|
||||||
|
explicit STExchange() = default;
|
||||||
|
|
||||||
|
using value_type = U;
|
||||||
|
|
||||||
|
static void
|
||||||
|
get(std::optional<T>& t, STTypedInteger<U> const& u)
|
||||||
|
{
|
||||||
|
t = u.value();
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::unique_ptr<STInteger<U>>
|
||||||
|
set(SField const& f, T const& t)
|
||||||
|
{
|
||||||
|
return std::make_unique<STTypedInteger<U>>(f, t);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct STExchange<STBlob, Slice>
|
struct STExchange<STBlob, Slice>
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -82,12 +82,42 @@ using STUInt16 = STInteger<std::uint16_t>;
|
|||||||
using STUInt32 = STInteger<std::uint32_t>;
|
using STUInt32 = STInteger<std::uint32_t>;
|
||||||
using STUInt64 = STInteger<std::uint64_t>;
|
using STUInt64 = STInteger<std::uint64_t>;
|
||||||
|
|
||||||
// Basis points (bips) values:
|
template <class TypedInteger>
|
||||||
using SFBips16 = STInteger<Bips16>;
|
class STTypedInteger : public STInteger<typename TypedInteger::value_type>,
|
||||||
using SFBips32 = STInteger<Bips32>;
|
public CountedObject<STTypedInteger<TypedInteger>>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using value_type = TypedInteger;
|
||||||
|
using base_value_type = TypedInteger::value_type;
|
||||||
|
using base = STInteger<base_value_type>;
|
||||||
|
|
||||||
|
public:
|
||||||
|
using base::add;
|
||||||
|
using base::getJson;
|
||||||
|
using base::getSType;
|
||||||
|
using base::getText;
|
||||||
|
using base::isDefault;
|
||||||
|
using base::isEquivalent;
|
||||||
|
using base::STInteger;
|
||||||
|
|
||||||
|
SerializedTypeID
|
||||||
|
getSType() const override;
|
||||||
|
|
||||||
|
STTypedInteger&
|
||||||
|
operator=(value_type const& v);
|
||||||
|
|
||||||
|
value_type
|
||||||
|
value() const noexcept;
|
||||||
|
|
||||||
|
void
|
||||||
|
setValue(TypedInteger v);
|
||||||
|
|
||||||
|
operator TypedInteger() const;
|
||||||
|
};
|
||||||
|
|
||||||
// Tenth of a basis point values:
|
// Tenth of a basis point values:
|
||||||
using SFTenthBips16 = STInteger<TenthBips16>;
|
using STTenthBips16 = STTypedInteger<TenthBips16>;
|
||||||
using SFTenthBips32 = STInteger<TenthBips32>;
|
using STTenthBips32 = STTypedInteger<TenthBips32>;
|
||||||
|
|
||||||
template <typename Integer>
|
template <typename Integer>
|
||||||
inline STInteger<Integer>::STInteger(Integer v) : value_(v)
|
inline STInteger<Integer>::STInteger(Integer v) : value_(v)
|
||||||
@@ -169,6 +199,34 @@ inline STInteger<Integer>::operator Integer() const
|
|||||||
return value_;
|
return value_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename TypedInteger>
|
||||||
|
inline STTypedInteger<TypedInteger>&
|
||||||
|
STTypedInteger<TypedInteger>::operator=(value_type const& v)
|
||||||
|
{
|
||||||
|
base::setValue(v.value());
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename TypedInteger>
|
||||||
|
inline typename STTypedInteger<TypedInteger>::value_type
|
||||||
|
STTypedInteger<TypedInteger>::value() const noexcept
|
||||||
|
{
|
||||||
|
return value_type(base::value());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename TypedInteger>
|
||||||
|
inline void
|
||||||
|
STTypedInteger<TypedInteger>::setValue(TypedInteger v)
|
||||||
|
{
|
||||||
|
base::setValue(v.value());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename TypedInteger>
|
||||||
|
inline STTypedInteger<TypedInteger>::operator TypedInteger() const
|
||||||
|
{
|
||||||
|
return TypedInteger(base::value());
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace ripple
|
} // namespace ripple
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -301,6 +301,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Returns the number of drops */
|
/** Returns the number of drops */
|
||||||
|
// TODO: Move this to a new class, maybe with the old "TaggedFee" name
|
||||||
constexpr value_type
|
constexpr value_type
|
||||||
fee() const
|
fee() const
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -61,7 +61,9 @@ TYPED_SFIELD(sfHookEmitCount, UINT16, 18)
|
|||||||
TYPED_SFIELD(sfHookExecutionIndex, UINT16, 19)
|
TYPED_SFIELD(sfHookExecutionIndex, UINT16, 19)
|
||||||
TYPED_SFIELD(sfHookApiVersion, UINT16, 20)
|
TYPED_SFIELD(sfHookApiVersion, UINT16, 20)
|
||||||
TYPED_SFIELD(sfLedgerFixType, UINT16, 21)
|
TYPED_SFIELD(sfLedgerFixType, UINT16, 21)
|
||||||
INTERPRETED_SFIELD(sfManagementFeeRate, UINT16, 22, TENTHBIPS16)
|
|
||||||
|
// 16-bit integers represented as 1/10 basis points (bips)
|
||||||
|
TYPED_SFIELD(sfManagementFeeRate, TENTHBIPS16, 1)
|
||||||
|
|
||||||
// 32-bit integers (common)
|
// 32-bit integers (common)
|
||||||
TYPED_SFIELD(sfNetworkID, UINT32, 1)
|
TYPED_SFIELD(sfNetworkID, UINT32, 1)
|
||||||
@@ -123,12 +125,15 @@ TYPED_SFIELD(sfPreviousPaymentDate, UINT32, 55)
|
|||||||
TYPED_SFIELD(sfNextPaymentDueDate, UINT32, 56)
|
TYPED_SFIELD(sfNextPaymentDueDate, UINT32, 56)
|
||||||
TYPED_SFIELD(sfPaymentRemaining, UINT32, 57)
|
TYPED_SFIELD(sfPaymentRemaining, UINT32, 57)
|
||||||
TYPED_SFIELD(sfPaymentTotal, UINT32, 58)
|
TYPED_SFIELD(sfPaymentTotal, UINT32, 58)
|
||||||
INTERPRETED_SFIELD(sfCoverRateMinimum, UINT32, 59, TENTHBIPS32)
|
|
||||||
INTERPRETED_SFIELD(sfCoverRateLiquidation, UINT32, 60, TENTHBIPS32)
|
|
||||||
INTERPRETED_SFIELD(sfInterestRate, UINT32, 61, TENTHBIPS32)
|
// 32-bit integers represented as 1/10 basis points (bips)
|
||||||
INTERPRETED_SFIELD(sfLateInterestRate, UINT32, 62, TENTHBIPS32)
|
TYPED_SFIELD(sfCoverRateMinimum, TENTHBIPS32, 1)
|
||||||
INTERPRETED_SFIELD(sfCloseInterestRate, UINT32, 63, TENTHBIPS32)
|
TYPED_SFIELD(sfCoverRateLiquidation, TENTHBIPS32, 2)
|
||||||
INTERPRETED_SFIELD(sfOverpaymentInterestRate, UINT32, 64, TENTHBIPS32)
|
TYPED_SFIELD(sfInterestRate, TENTHBIPS32, 3)
|
||||||
|
TYPED_SFIELD(sfLateInterestRate, TENTHBIPS32, 4)
|
||||||
|
TYPED_SFIELD(sfCloseInterestRate, TENTHBIPS32, 5)
|
||||||
|
TYPED_SFIELD(sfOverpaymentInterestRate, TENTHBIPS32, 6)
|
||||||
|
|
||||||
// 64-bit integers (common)
|
// 64-bit integers (common)
|
||||||
TYPED_SFIELD(sfIndexNext, UINT64, 1)
|
TYPED_SFIELD(sfIndexNext, UINT64, 1)
|
||||||
|
|||||||
@@ -54,8 +54,6 @@ TypedField<T>::TypedField(private_access_tag_t pat, Args&&... args)
|
|||||||
#undef UNTYPED_SFIELD
|
#undef UNTYPED_SFIELD
|
||||||
#pragma push_macro("TYPED_SFIELD")
|
#pragma push_macro("TYPED_SFIELD")
|
||||||
#undef TYPED_SFIELD
|
#undef TYPED_SFIELD
|
||||||
#pragma push_macro("INTERPRETED_SFIELD")
|
|
||||||
#undef INTERPRETED_SFIELD
|
|
||||||
|
|
||||||
#define UNTYPED_SFIELD(sfName, stiSuffix, fieldValue, ...) \
|
#define UNTYPED_SFIELD(sfName, stiSuffix, fieldValue, ...) \
|
||||||
SField const sfName( \
|
SField const sfName( \
|
||||||
@@ -71,13 +69,6 @@ TypedField<T>::TypedField(private_access_tag_t pat, Args&&... args)
|
|||||||
fieldValue, \
|
fieldValue, \
|
||||||
std::string_view(#sfName).substr(2).data(), \
|
std::string_view(#sfName).substr(2).data(), \
|
||||||
##__VA_ARGS__);
|
##__VA_ARGS__);
|
||||||
#define INTERPRETED_SFIELD(sfName, stiSuffix, fieldValue, stiInterpreted, ...) \
|
|
||||||
SF_##stiInterpreted 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.
|
// SFields which, for historical reasons, do not follow naming conventions.
|
||||||
SField const sfInvalid(access, -1);
|
SField const sfInvalid(access, -1);
|
||||||
@@ -89,8 +80,6 @@ SField const sfIndex(access, STI_UINT256, 258, "index");
|
|||||||
|
|
||||||
#include <xrpl/protocol/detail/sfields.macro>
|
#include <xrpl/protocol/detail/sfields.macro>
|
||||||
|
|
||||||
#undef INTERPRETED_SFIELD
|
|
||||||
#pragma pop_macro("INTERPRETED_SFIELD")
|
|
||||||
#undef TYPED_SFIELD
|
#undef TYPED_SFIELD
|
||||||
#pragma pop_macro("TYPED_SFIELD")
|
#pragma pop_macro("TYPED_SFIELD")
|
||||||
#undef UNTYPED_SFIELD
|
#undef UNTYPED_SFIELD
|
||||||
|
|||||||
@@ -229,4 +229,18 @@ STUInt64::getJson(JsonOptions) const
|
|||||||
return convertToString(value_, 16); // Convert to base 16
|
return convertToString(value_, 16); // Convert to base 16
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
SerializedTypeID
|
||||||
|
STTenthBips16::getSType() const override
|
||||||
|
{
|
||||||
|
return STI_TENTHBIPS16;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
SerializedTypeID
|
||||||
|
STTenthBips32::getSType() const override
|
||||||
|
{
|
||||||
|
return STI_TENTHBIPS32;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace ripple
|
} // namespace ripple
|
||||||
|
|||||||
@@ -190,6 +190,12 @@ STVar::constructST(SerializedTypeID id, int depth, Args&&... args)
|
|||||||
case STI_UINT64:
|
case STI_UINT64:
|
||||||
construct<STUInt64>(std::forward<Args>(args)...);
|
construct<STUInt64>(std::forward<Args>(args)...);
|
||||||
return;
|
return;
|
||||||
|
case STI_TENTHBIPS16:
|
||||||
|
construct<STTenthBips16>(std::forward<Args>(args)...);
|
||||||
|
return;
|
||||||
|
case STI_TENTHBIPS32:
|
||||||
|
construct<STTenthBips32>(std::forward<Args>(args)...);
|
||||||
|
return;
|
||||||
case STI_AMOUNT:
|
case STI_AMOUNT:
|
||||||
construct<STAmount>(std::forward<Args>(args)...);
|
construct<STAmount>(std::forward<Args>(args)...);
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -174,20 +174,15 @@ struct valueUnitField
|
|||||||
using OV = ValueType;
|
using OV = ValueType;
|
||||||
using base = JTxField<SF, SV, OV>;
|
using base = JTxField<SF, SV, OV>;
|
||||||
|
|
||||||
|
static_assert(std::is_same_v<SV, typename SField::type::value_type>);
|
||||||
static_assert(
|
static_assert(
|
||||||
std::is_same_v<SV, typename SField::type::value_type::value_type>);
|
std::is_same_v<OV, typename SField::type::value_type::value_type>);
|
||||||
static_assert(std::is_same_v<
|
|
||||||
OV,
|
|
||||||
typename SField::type::value_type::value_type::value_type>);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
using base::value_;
|
using base::value_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit valueUnitField(SF const& sfield, SV const& value)
|
using base::JTxField;
|
||||||
: JTxField(sfield, value)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
OV
|
OV
|
||||||
value() const override
|
value() const override
|
||||||
@@ -675,7 +670,7 @@ auto const coverRateMinimum =
|
|||||||
valueUnitWrapper<SF_TENTHBIPS32>(sfCoverRateMinimum);
|
valueUnitWrapper<SF_TENTHBIPS32>(sfCoverRateMinimum);
|
||||||
|
|
||||||
auto const coverRateLiquidation =
|
auto const coverRateLiquidation =
|
||||||
simpleField<SF_TENTHBIPS32>(sfCoverRateLiquidation);
|
valueUnitWrapper<SF_TENTHBIPS32>(sfCoverRateLiquidation);
|
||||||
|
|
||||||
} // namespace loanBroker
|
} // namespace loanBroker
|
||||||
|
|
||||||
|
|||||||
@@ -193,8 +193,8 @@ LoanBrokerSet::doApply()
|
|||||||
return tecINSUFFICIENT_RESERVE;
|
return tecINSUFFICIENT_RESERVE;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
auto maybePseudo = createPseudoAccount(
|
auto maybePseudo =
|
||||||
view, broker->key(), PseudoAccountOwnerType::LoanBroker);
|
createPseudoAccount(view, broker->key(), sfLoanBrokerID);
|
||||||
if (!maybePseudo)
|
if (!maybePseudo)
|
||||||
return maybePseudo.error();
|
return maybePseudo.error();
|
||||||
auto& pseudo = *maybePseudo;
|
auto& pseudo = *maybePseudo;
|
||||||
|
|||||||
Reference in New Issue
Block a user