diff --git a/include/xrpl/basics/base_uint.h b/include/xrpl/basics/base_uint.h index 5cd1c5aa26..b1a4622cc4 100644 --- a/include/xrpl/basics/base_uint.h +++ b/include/xrpl/basics/base_uint.h @@ -636,12 +636,10 @@ template inline std::string to_short_string(base_uint const& a) { - // LCOV_EXCL_START - if constexpr (base_uint::bytes <= 4) - return to_string(a); - else - // LCOV_EXCL_STOP - return strHex(a.cbegin(), a.cbegin() + 4) + "..."; + static_assert( + base_uint::bytes > 4, + "For 4 bytes or less, use a native type"); + return strHex(a.cbegin(), a.cbegin() + 4) + "..."; } template diff --git a/include/xrpl/protocol/TxFlags.h b/include/xrpl/protocol/TxFlags.h index 4eb311bcb5..ebbccd591c 100644 --- a/include/xrpl/protocol/TxFlags.h +++ b/include/xrpl/protocol/TxFlags.h @@ -143,8 +143,8 @@ constexpr std::uint32_t const tfTransferable = 0x00000008; constexpr std::uint32_t const tfMutable = 0x00000010; // MPTokenIssuanceCreate flags: -// NOTE - there is intentionally no flag here for lsfMPTLocked, which -// this transaction cannot mutate. +// Note: tf/lsfMPTLocked is intentionally omitted, since this transaction +// is not allowed to modify it. constexpr std::uint32_t const tfMPTCanLock = lsfMPTCanLock; constexpr std::uint32_t const tfMPTRequireAuth = lsfMPTRequireAuth; constexpr std::uint32_t const tfMPTCanEscrow = lsfMPTCanEscrow; diff --git a/include/xrpl/protocol/Units.h b/include/xrpl/protocol/Units.h index 9459f5cb82..6b2ae67059 100644 --- a/include/xrpl/protocol/Units.h +++ b/include/xrpl/protocol/Units.h @@ -77,6 +77,16 @@ concept Compatible = Valid && std::is_arithmetic_v && std::is_arithmetic_v && std::is_convertible_v; +template +concept Integral = std::is_integral_v; + +template +concept IntegralValue = Integral; + +template +concept CastableValue = IntegralValue && IntegralValue && + std::is_same_v; + template class ValueUnit : private boost::totally_ordered>, private boost::additive>, @@ -218,8 +228,8 @@ public: return *this; } - template - std::enable_if_t, ValueUnit&> + template + ValueUnit& operator%=(value_type const& rhs) { value_ %= rhs; @@ -358,49 +368,27 @@ to_string(ValueUnit const& amount) return std::to_string(amount.value()); } -template -constexpr bool can_muldiv_source_v = +template +concept muldivSource = Valid && std::is_convertible_v; -template -constexpr bool can_muldiv_dest_v = - can_muldiv_source_v && // Dest is also a source +template +concept muldivDest = muldivSource && // Dest is also a source std::is_convertible_v && sizeof(typename Dest::value_type) >= sizeof(std::uint64_t); -template -constexpr bool can_muldiv_sources_v = - can_muldiv_source_v && can_muldiv_source_v && +template +concept muldivSources = muldivSource && muldivSource && std::is_same_v; -template -constexpr bool can_muldiv_v = - can_muldiv_sources_v && can_muldiv_dest_v; +template +concept muldivable = muldivSources && muldivDest; // Source and Dest can be the same by default -template -constexpr bool can_muldiv_commute_v = can_muldiv_v && +template +concept muldivCommutable = muldivable && !std::is_same_v; -template -using enable_muldiv_source_t = - typename std::enable_if_t>; - -template -using enable_muldiv_dest_t = typename std::enable_if_t>; - -template -using enable_muldiv_sources_t = - typename std::enable_if_t>; - -template -using enable_muldiv_t = - typename std::enable_if_t>; - -template -using enable_muldiv_commute_t = - typename std::enable_if_t>; - template ValueUnit scalar(T value) @@ -408,11 +396,7 @@ scalar(T value) return ValueUnit{value}; } -template < - class Source1, - class Source2, - class Dest, - class = enable_muldiv_t> +template Dest> std::optional mulDivU(Source1 value, Dest mul, Source2 div) { @@ -426,7 +410,7 @@ mulDivU(Source1 value, Dest mul, Source2 div) XRPL_ASSERT( mul.value() >= 0, "ripple::unit::mulDivU : minimum mul input"); XRPL_ASSERT( - div.value() >= 0, "ripple::unit::mulDivU : minimum div input"); + div.value() > 0, "ripple::unit::mulDivU : minimum div input"); return std::nullopt; } @@ -477,11 +461,7 @@ using TenthBips = unit::ValueUnit; using TenthBips16 = TenthBips; using TenthBips32 = TenthBips; -template < - class Source1, - class Source2, - class Dest, - class = unit::enable_muldiv_t> +template Dest> std::optional mulDiv(Source1 value, Dest mul, Source2 div) { @@ -491,8 +471,7 @@ mulDiv(Source1 value, Dest mul, Source2 div) template < class Source1, class Source2, - class Dest, - class = unit::enable_muldiv_commute_t> + unit::muldivCommutable Dest> std::optional mulDiv(Dest value, Source1 mul, Source2 div) { @@ -500,7 +479,7 @@ mulDiv(Dest value, Source1 mul, Source2 div) return unit::mulDivU(mul, value, div); } -template > +template std::optional mulDiv(std::uint64_t value, Dest mul, std::uint64_t div) { @@ -509,7 +488,7 @@ mulDiv(std::uint64_t value, Dest mul, std::uint64_t div) return unit::mulDivU(unit::scalar(value), mul, unit::scalar(div)); } -template > +template std::optional mulDiv(Dest value, std::uint64_t mul, std::uint64_t div) { @@ -517,10 +496,7 @@ mulDiv(Dest value, std::uint64_t mul, std::uint64_t div) return mulDiv(mul, value, div); } -template < - class Source1, - class Source2, - class = unit::enable_muldiv_sources_t> +template Source2> std::optional mulDiv(Source1 value, std::uint64_t mul, Source2 div) { @@ -534,10 +510,7 @@ mulDiv(Source1 value, std::uint64_t mul, Source2 div) return unitresult->value(); } -template < - class Source1, - class Source2, - class = unit::enable_muldiv_sources_t> +template Source2> std::optional mulDiv(std::uint64_t value, Source1 mul, Source2 div) { @@ -545,44 +518,32 @@ mulDiv(std::uint64_t value, Source1 mul, Source2 div) return mulDiv(mul, value, div); } -template -constexpr std::enable_if_t< - std::is_same_v && - std::is_integral_v && - std::is_integral_v, - Dest> +template Src> +constexpr Dest safe_cast(Src s) noexcept { // Dest may not have an explicit value constructor return Dest{safe_cast(s.value())}; } -template -constexpr std::enable_if_t< - std::is_integral_v && std::is_integral_v, - Dest> +template +constexpr Dest safe_cast(Src s) noexcept { // Dest may not have an explicit value constructor return Dest{safe_cast(s)}; } -template -constexpr std::enable_if_t< - std::is_same_v && - std::is_integral_v && - std::is_integral_v, - Dest> +template Src> +constexpr Dest unsafe_cast(Src s) noexcept { // Dest may not have an explicit value constructor return Dest{unsafe_cast(s.value())}; } -template -constexpr std::enable_if_t< - std::is_integral_v && std::is_integral_v, - Dest> +template +constexpr Dest unsafe_cast(Src s) noexcept { // Dest may not have an explicit value constructor diff --git a/include/xrpl/protocol/detail/sfields.macro b/include/xrpl/protocol/detail/sfields.macro index 12371b6839..10fe015dac 100644 --- a/include/xrpl/protocol/detail/sfields.macro +++ b/include/xrpl/protocol/detail/sfields.macro @@ -175,7 +175,7 @@ TYPED_SFIELD(sfEmitParentTxnID, UINT256, 11) TYPED_SFIELD(sfEmitNonce, UINT256, 12) TYPED_SFIELD(sfEmitHookHash, UINT256, 13) TYPED_SFIELD(sfAMMID, UINT256, 14, - SField::sMD_PseudoAccount |SField::sMD_Default) + SField::sMD_PseudoAccount | SField::sMD_Default) // 256-bit (uncommon) TYPED_SFIELD(sfBookDirectory, UINT256, 16) diff --git a/src/test/jtx/amount.h b/src/test/jtx/amount.h index fbe78bf3ec..a793f3a287 100644 --- a/src/test/jtx/amount.h +++ b/src/test/jtx/amount.h @@ -34,7 +34,6 @@ #include namespace ripple { - namespace detail { struct epsilon_multiple diff --git a/src/xrpld/app/tx/detail/InvariantCheck.cpp b/src/xrpld/app/tx/detail/InvariantCheck.cpp index 7af93a5e3e..40062104bb 100644 --- a/src/xrpld/app/tx/detail/InvariantCheck.cpp +++ b/src/xrpld/app/tx/detail/InvariantCheck.cpp @@ -41,7 +41,7 @@ namespace ripple { assert(enforce) There are several asserts (or XRPL_ASSERTs) in this file that check a variable -named `enforce` when an invariant fails. At first glace, those asserts may look +named `enforce` when an invariant fails. At first glance, those asserts may look incorrect, but they are not. Those asserts take advantage of two facts: @@ -49,11 +49,11 @@ Those asserts take advantage of two facts: 2. Invariants should *never* fail, except in tests that specifically modify the open ledger to break them. -To make it sort of a second-layer of invariant enforcement aimed at -_developers_. It's designed to fire if a developer writes code that violates an -invariant, and runs it in unit tests or a develop build that _does not have the -relevant amendments enabled_. It's intentionally a pain in the neck so that bad -code gets caught and fixed as early as possible. +This makes `assert(enforce)` sort of a second-layer of invariant enforcement +aimed at _developers_. It's designed to fire if a developer writes code that +violates an invariant, and runs it in unit tests or a develop build that _does +not have the relevant amendments enabled_. It's intentionally a pain in the neck +so that bad code gets caught and fixed as early as possible. */ enum Privilege {