Remove the new TenthBips serialized type

- It was a neat idea, but more trouble than it's worth. The conversion
  functions are sufficient for what I need.
- Partially reverts
  - d7357d3eca0b70c36b5665fdf23ee5e7a3cea0d7
  - cbb4dbcbe7023cb8a8d30f0e794acf9d1d9a458a
  - 396b981fc0da0d2d248b8c68bd3fac68c5f0b64c
This commit is contained in:
Ed Hennis
2025-04-30 16:31:06 -04:00
parent ceeb11aee0
commit 2013e7e64d
12 changed files with 47 additions and 145 deletions

View File

@@ -92,8 +92,6 @@ concept HasValue = requires(Integer i) { i.value(); };
STYPE(STI_ISSUE, 24) \
STYPE(STI_XCHAIN_BRIDGE, 25) \
STYPE(STI_CURRENCY, 26) \
STYPE(STI_TENTHBIPS16, 27) \
STYPE(STI_TENTHBIPS32, 28) \
\
/* high-level types */ \
/* cannot be serialized inside other types */ \
@@ -363,13 +361,6 @@ using SF_UINT256 = TypedField<STBitString<256>>;
using SF_UINT384 = TypedField<STBitString<384>>;
using SF_UINT512 = TypedField<STBitString<512>>;
// These TENTHBIPS values are serialized as the underlying type.
// The tag is only applied when deserialized.
//
// Tenth of a basis point values:
using SF_TENTHBIPS16 = TypedField<STInteger<TenthBips16>>;
using SF_TENTHBIPS32 = TypedField<STInteger<TenthBips32>>;
using SF_ACCOUNT = TypedField<STAccount>;
using SF_AMOUNT = TypedField<STAmount>;
using SF_ISSUE = TypedField<STIssue>;

View File

@@ -61,26 +61,6 @@ struct STExchange<STInteger<U>, T>
}
};
template <class U, class T>
struct STExchange<STInteger<TenthBips<U>>, T>
{
explicit STExchange() = default;
using value_type = TenthBips<U>;
static void
get(std::optional<T>& t, STInteger<value_type> const& u)
{
t = u.value();
}
static std::unique_ptr<STInteger<value_type>>
set(SField const& f, T const& t)
{
return std::make_unique<STInteger<value_type>>(f, t);
}
};
template <>
struct STExchange<STBlob, Slice>
{

View File

@@ -82,10 +82,6 @@ using STUInt16 = STInteger<std::uint16_t>;
using STUInt32 = STInteger<std::uint32_t>;
using STUInt64 = STInteger<std::uint64_t>;
// Tenth of a basis point values:
using STTenthBips16 = STInteger<TenthBips16>;
using STTenthBips32 = STInteger<TenthBips32>;
template <typename Integer>
inline STInteger<Integer>::STInteger(Integer v) : value_(v)
{

View File

@@ -61,9 +61,7 @@ TYPED_SFIELD(sfHookEmitCount, UINT16, 18)
TYPED_SFIELD(sfHookExecutionIndex, UINT16, 19)
TYPED_SFIELD(sfHookApiVersion, UINT16, 20)
TYPED_SFIELD(sfLedgerFixType, UINT16, 21)
// 16-bit integers represented as 1/10 basis points (bips)
TYPED_SFIELD(sfManagementFeeRate, TENTHBIPS16, 1)
TYPED_SFIELD(sfManagementFeeRate, UINT16, 22) // 1/10 basis points (bips)
// 32-bit integers (common)
TYPED_SFIELD(sfNetworkID, UINT32, 1)
@@ -126,15 +124,13 @@ TYPED_SFIELD(sfNextPaymentDueDate, UINT32, 56)
TYPED_SFIELD(sfPaymentRemaining, UINT32, 57)
TYPED_SFIELD(sfPaymentTotal, UINT32, 58)
TYPED_SFIELD(sfLoanSequence, UINT32, 59)
// 32-bit integers represented as 1/10 basis points (bips)
TYPED_SFIELD(sfCoverRateMinimum, TENTHBIPS32, 1)
TYPED_SFIELD(sfCoverRateLiquidation, TENTHBIPS32, 2)
TYPED_SFIELD(sfOverpaymentFee, TENTHBIPS32, 3)
TYPED_SFIELD(sfInterestRate, TENTHBIPS32, 4)
TYPED_SFIELD(sfLateInterestRate, TENTHBIPS32, 5)
TYPED_SFIELD(sfCloseInterestRate, TENTHBIPS32, 6)
TYPED_SFIELD(sfOverpaymentInterestRate, TENTHBIPS32, 7)
TYPED_SFIELD(sfCoverRateMinimum, UINT32, 60) // 1/10 basis points (bips)
TYPED_SFIELD(sfCoverRateLiquidation, UINT32, 61) // 1/10 basis points (bips)
TYPED_SFIELD(sfOverpaymentFee, UINT32, 62) // 1/10 basis points (bips)
TYPED_SFIELD(sfInterestRate, UINT32, 63) // 1/10 basis points (bips)
TYPED_SFIELD(sfLateInterestRate, UINT32, 64) // 1/10 basis points (bips)
TYPED_SFIELD(sfCloseInterestRate, UINT32, 65) // 1/10 basis points (bips)
TYPED_SFIELD(sfOverpaymentInterestRate, UINT32, 66) // 1/10 basis points (bips)
// 64-bit integers (common)
TYPED_SFIELD(sfIndexNext, UINT64, 1)

View File

@@ -229,62 +229,4 @@ STUInt64::getJson(JsonOptions) const
return convertToString(value_, 16); // Convert to base 16
}
//------------------------------------------------------------------------------
template <>
STTenthBips16::STInteger(SerialIter& sit, SField const& name)
: STInteger(name, TenthBips16(sit.get16()))
{
}
template <>
SerializedTypeID
STTenthBips16::getSType() const
{
return STI_TENTHBIPS16;
}
template <>
std::string
STTenthBips16::getText() const
{
return std::to_string(value_.value());
}
template <>
Json::Value
STTenthBips16::getJson(JsonOptions) const
{
return value_.value();
}
//------------------------------------------------------------------------------
template <>
STTenthBips32::STInteger(SerialIter& sit, SField const& name)
: STInteger(name, TenthBips32(sit.get32()))
{
}
template <>
SerializedTypeID
STTenthBips32::getSType() const
{
return STI_TENTHBIPS32;
}
template <>
std::string
STTenthBips32::getText() const
{
return std::to_string(value_.value());
}
template <>
Json::Value
STTenthBips32::getJson(JsonOptions) const
{
return value_.value();
}
} // namespace ripple

View File

@@ -446,14 +446,6 @@ parseLeaf(
break;
case STI_TENTHBIPS16:
ret = parseUnsigned<STTenthBips16, std::uint16_t>(
field, json_name, fieldName, name, value, error);
if (!ret)
return ret;
break;
case STI_UINT32:
ret = parseUnsigned<STUInt32, std::uint32_t>(
field, json_name, fieldName, name, value, error);
@@ -462,14 +454,6 @@ parseLeaf(
break;
case STI_TENTHBIPS32:
ret = parseUnsigned<STTenthBips32, std::uint32_t>(
field, json_name, fieldName, name, value, error);
if (!ret)
return ret;
break;
case STI_UINT64:
try
{

View File

@@ -190,12 +190,6 @@ STVar::constructST(SerializedTypeID id, int depth, Args&&... args)
case STI_UINT64:
construct<STUInt64>(std::forward<Args>(args)...);
return;
case STI_TENTHBIPS16:
construct<STTenthBips16>(std::forward<Args>(args)...);
return;
case STI_TENTHBIPS32:
construct<STTenthBips32>(std::forward<Args>(args)...);
return;
case STI_AMOUNT:
construct<STAmount>(std::forward<Args>(args)...);
return;

View File

@@ -197,9 +197,7 @@ struct valueUnitField
using OV = ValueType;
using base = JTxField<SF, SV, OV>;
static_assert(std::is_same_v<SV, typename SField::type::value_type>);
static_assert(
std::is_same_v<OV, typename SField::type::value_type::value_type>);
static_assert(std::is_same_v<OV, typename SField::type::value_type>);
protected:
using base::value_;
@@ -273,8 +271,8 @@ public:
template <
class SField,
class UnitTag = typename SField::type::value_type::unit_type,
class ValueType = typename SField::type::value_type::value_type>
class UnitTag,
class ValueType = typename SField::type::value_type>
using valueUnitWrapper =
JTxFieldWrapper<valueUnitField<SField, UnitTag, ValueType>>;
@@ -687,15 +685,15 @@ coverWithdraw(
auto const loanBrokerID = JTxFieldWrapper<uint256Field>(sfLoanBrokerID);
auto const managementFeeRate =
valueUnitWrapper<SF_TENTHBIPS16>(sfManagementFeeRate);
valueUnitWrapper<SF_UINT16, unit::TenthBipsTag>(sfManagementFeeRate);
auto const debtMaximum = simpleField<SF_NUMBER>(sfDebtMaximum);
auto const coverRateMinimum =
valueUnitWrapper<SF_TENTHBIPS32>(sfCoverRateMinimum);
valueUnitWrapper<SF_UINT32, unit::TenthBipsTag>(sfCoverRateMinimum);
auto const coverRateLiquidation =
valueUnitWrapper<SF_TENTHBIPS32>(sfCoverRateLiquidation);
valueUnitWrapper<SF_UINT32, unit::TenthBipsTag>(sfCoverRateLiquidation);
} // namespace loanBroker
@@ -722,18 +720,20 @@ auto const latePaymentFee = simpleField<SF_NUMBER>(sfLatePaymentFee);
auto const closePaymentFee = simpleField<SF_NUMBER>(sfClosePaymentFee);
auto const overpaymentFee = valueUnitWrapper<SF_TENTHBIPS32>(sfOverpaymentFee);
auto const overpaymentFee =
valueUnitWrapper<SF_UINT32, unit::TenthBipsTag>(sfOverpaymentFee);
auto const interestRate = valueUnitWrapper<SF_TENTHBIPS32>(sfInterestRate);
auto const interestRate =
valueUnitWrapper<SF_UINT32, unit::TenthBipsTag>(sfInterestRate);
auto const lateInterestRate =
valueUnitWrapper<SF_TENTHBIPS32>(sfLateInterestRate);
valueUnitWrapper<SF_UINT32, unit::TenthBipsTag>(sfLateInterestRate);
auto const closeInterestRate =
valueUnitWrapper<SF_TENTHBIPS32>(sfCloseInterestRate);
valueUnitWrapper<SF_UINT32, unit::TenthBipsTag>(sfCloseInterestRate);
auto const overpaymentInterestRate =
valueUnitWrapper<SF_TENTHBIPS32>(sfOverpaymentInterestRate);
valueUnitWrapper<SF_UINT32, unit::TenthBipsTag>(sfOverpaymentInterestRate);
auto const paymentTotal = simpleField<SF_UINT32>(sfPaymentTotal);

View File

@@ -1405,7 +1405,7 @@ class Invariants_test : public beast::unit_test::suite
sle->at(sfOwner) = sle->at(sfAccount);
},
[](SLE::pointer& sle) {
sle->at(sfManagementFeeRate) += TenthBips16(1);
sle->at(sfManagementFeeRate) += 1;
},
[](SLE::pointer& sle) { sle->at(sfCoverRateMinimum) += 1; },
[](SLE::pointer& sle) {

View File

@@ -111,7 +111,8 @@ LoanBrokerCoverWithdraw::preclaim(PreclaimContext const& ctx)
auto const coverAvail = sleBroker->at(sfCoverAvailable);
// Cover Rate is in 1/10 bips units
auto const minimumCover = tenthBipsOfValue(
sleBroker->at(sfDebtTotal), sleBroker->at(sfCoverRateMinimum));
sleBroker->at(sfDebtTotal),
TenthBips32(sleBroker->at(sfCoverRateMinimum)));
if (coverAvail < amount)
return tecINSUFFICIENT_FUNDS;
if ((coverAvail - amount) < minimumCover)

View File

@@ -229,7 +229,8 @@ LoanSet::preclaim(PreclaimContext const& ctx)
}
if (brokerSle->at(sfCoverAvailable) <
tenthBipsOfValue(
debtTotal + principalRequested, brokerSle->at(sfCoverRateMinimum)))
debtTotal + principalRequested,
TenthBips32(brokerSle->at(sfCoverRateMinimum))))
{
JLOG(ctx.j.warn())
<< "Insufficient first-loss capital to cover the loan.";
@@ -270,7 +271,7 @@ LoanSet::doApply()
auto const brokerPseudo = brokerSle->at(sfAccount);
auto const brokerPseudoSle = view.peek(keylet::account(brokerPseudo));
auto const principalRequested = tx[sfPrincipalRequested];
auto const interestRate = tx[~sfInterestRate].value_or(TenthBips32(0));
TenthBips32 const interestRate{tx[~sfInterestRate].value_or(0)};
auto const originationFee = tx[~sfLoanOriginationFee];
auto const loanAssetsAvailable =
principalRequested - originationFee.value_or(Number{});
@@ -332,14 +333,14 @@ LoanSet::doApply()
return ter;
}
auto const managementFeeRate = brokerSle->at(sfManagementFeeRate);
TenthBips32 const managementFeeRate{brokerSle->at(sfManagementFeeRate)};
// The total amount if interest the loan is expected to generate
auto const loanInterest =
tenthBipsOfValue(principalRequested, interestRate);
// The portion of the loan interest that will go to the vault (total
// interest minus the management fee)
auto const loanInterestToVault = loanInterest -
tenthBipsOfValue(loanInterest, managementFeeRate.value());
auto const loanInterestToVault =
loanInterest - tenthBipsOfValue(loanInterest, managementFeeRate);
auto const startDate = tx[sfStartDate];
auto const paymentInterval =
tx[~sfPaymentInterval].value_or(defaultPaymentInterval);

View File

@@ -229,6 +229,13 @@ protected:
static bool
validNumericRange(std::optional<T> value, T max, T min = {});
template <class T, class Unit>
static bool
validNumericRange(
std::optional<T> value,
unit::ValueUnit<Unit, T> max,
unit::ValueUnit<Unit, T> min = {});
private:
std::pair<TER, XRPAmount>
reset(XRPAmount fee);
@@ -322,6 +329,16 @@ Transactor::validNumericRange(std::optional<T> value, T max, T min)
return value >= min && value <= max;
}
template <class T, class Unit>
bool
Transactor::validNumericRange(
std::optional<T> value,
unit::ValueUnit<Unit, T> max,
unit::ValueUnit<Unit, T> min)
{
return validNumericRange(value, max.value(), min.value());
}
} // namespace ripple
#endif