Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
169 changes: 153 additions & 16 deletions include/xrpl/protocol/TER.h
Original file line number Diff line number Diff line change
Expand Up @@ -604,7 +604,7 @@ class CanCvtToNotTEC<TEScodes> : public std::true_type
{
};

using NotTEC = TERSubset<CanCvtToNotTEC>;
using NotTECRaw = TERSubset<CanCvtToNotTEC>;

//------------------------------------------------------------------------------

Expand Down Expand Up @@ -639,48 +639,188 @@ class CanCvtToTER<TECcodes> : public std::true_type
{
};
template <>
class CanCvtToTER<NotTEC> : public std::true_type
class CanCvtToTER<NotTECRaw> : public std::true_type
{
};

// TER allows all of the subsets.
using TER = TERSubset<CanCvtToTER>;
// TERRaw allows all of the subsets (the plain numeric code, no reason string).
using TERRaw = TERSubset<CanCvtToTER>;

//------------------------------------------------------------------------------
// Forward declaration required by TER constructors below (TER.cpp provides the
// definition). The full public declaration is repeated after the struct.
std::string
transHuman(TERRaw code);

//------------------------------------------------------------------------------
// TERBase<RawType, Trait>: shared implementation for TER and NotTEC.
//
// RawType – the underlying plain-integer subset (TERRaw or NotTECRaw).
// Trait – the trait class restricting which TE*codes values are accepted.
//
// When no reason is supplied the standard description from transHuman() is used
// automatically, so existing bare return statements compile unchanged:
// return tesSUCCESS; // in a TER-returning function
// return temMALFORMED; // in a NotTEC-returning preflight
//
// To attach a more specific reason at a particular return site write:
// return {tecNO_DST, "destination account has been deleted"};
// return {temMALFORMED, "SignerEntries must be present for a non-zero quorum"};
//
template <typename RawType, template <typename> class Trait>
struct TERBase
{
RawType code;
std::string reason;

// Default-construct to tesSUCCESS.
TERBase() : code(tesSUCCESS), reason(transHuman(TERRaw{code}))
{
}

TERBase(TERBase const&) = default;
TERBase(TERBase&&) = default;
TERBase&
operator=(TERBase const&) = default;
TERBase&
operator=(TERBase&&) = default;

// --- construction from RawType ---

// Without explicit reason: populate from transHuman.
TERBase(RawType c) // NOLINT(google-explicit-constructor)
: code(c), reason(transHuman(TERRaw{code}))
{
}

// With explicit reason.
TERBase(RawType c, std::string r) : code(c), reason(std::move(r))
{
}

// --- construction from any TE*codes enum satisfying Trait ---

// Without explicit reason: populate from transHuman.
template <typename T>
TERBase(T c) // NOLINT(google-explicit-constructor)
requires(Trait<std::remove_cv_t<std::remove_reference_t<T>>>::value)
: code(c), reason(transHuman(TERRaw{code}))
{
}

// With explicit reason.
template <typename T>
TERBase(T c, std::string r)
requires(Trait<std::remove_cv_t<std::remove_reference_t<T>>>::value)
: code(c), reason(std::move(r))
{
}

// --- cross-construction from a compatible TERBase specialization ---
// Carries the reason string across (e.g. NotTEC → TER preserves a
// custom reason set during preflight).
template <typename OtherRaw, template <typename> class OtherTrait>
TERBase(TERBase<OtherRaw, OtherTrait> const& other) // NOLINT(google-explicit-constructor)
requires(Trait<OtherRaw>::value)
: code(other.code), reason(other.reason)
{
}

// Build from a raw integer (used by transCode).
static TERBase
fromInt(int from)
{
return TERBase(RawType::fromInt(from));
}

// Implicit conversion to RawType for backward compatibility.
operator RawType() const // NOLINT(google-explicit-constructor)
{
return code;
}

// True when the code is anything other than tesSUCCESS.
explicit
operator bool() const
{
return static_cast<bool>(code);
}

// Allow assignment to json::Objects without casting.
operator json::Value() const // NOLINT(google-explicit-constructor)
{
return json::Value{TERtoInt(code)};
}

friend std::ostream&
operator<<(std::ostream& os, TERBase const& rhs)
{
return os << TERtoInt(rhs.code);
}
};

// TER – full result code for apply-phase transactors (all TE*codes).
using TER = TERBase<TERRaw, CanCvtToTER>;

// NotTEC – result code for preflight functions (tel*, tem*, tef*, ter*, tes*;
// excludes tec* to prevent fee charging without a valid signature).
using NotTEC = TERBase<NotTECRaw, CanCvtToNotTEC>;

// Expose underlying integers for the comparison operator templates.
inline TERUnderlyingType
TERtoInt(TER const& v)
{
return TERtoInt(v.code);
}

inline TERUnderlyingType
TERtoInt(NotTEC const& v)
{
return TERtoInt(v.code);
}

// Allow TERRaw (and therefore transHuman/transToken/transResultInfo) to accept
// a NotTEC directly, enabling one-step implicit conversion via TERtoInt(NotTEC).
template <>
class CanCvtToTER<NotTEC> : public std::true_type
{
};

//------------------------------------------------------------------------------

inline bool
isTelLocal(TER x) noexcept
isTelLocal(TER const& x) noexcept
{
return (x >= telLOCAL_ERROR && x < temMALFORMED);
}

inline bool
isTemMalformed(TER x) noexcept
isTemMalformed(TER const& x) noexcept
{
return (x >= temMALFORMED && x < tefFAILURE);
}

inline bool
isTefFailure(TER x) noexcept
isTefFailure(TER const& x) noexcept
{
return (x >= tefFAILURE && x < terRETRY);
}

inline bool
isTerRetry(TER x) noexcept
isTerRetry(TER const& x) noexcept
{
return (x >= terRETRY && x < tesSUCCESS);
}

inline bool
isTesSuccess(TER x) noexcept
isTesSuccess(TER const& x) noexcept
{
// Makes use of TERSubset::operator bool()
// Makes use of TER::operator bool()
return !x;
}

inline bool
isTecClaim(TER x) noexcept
isTecClaim(TER const& x) noexcept
{
return (x >= tecCLAIM);
}
Expand All @@ -689,13 +829,10 @@ std::unordered_map<TERUnderlyingType, std::pair<char const* const, char const* c
transResults();

bool
transResultInfo(TER code, std::string& token, std::string& text);

std::string
transToken(TER code);
transResultInfo(TERRaw code, std::string& token, std::string& text);

std::string
transHuman(TER code);
transToken(TERRaw code);

std::optional<TER>
transCode(std::string const& token);
Expand Down
1 change: 1 addition & 0 deletions include/xrpl/protocol/jss.h
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,7 @@ JSS(enabled); // out: AmendmentTable
JSS(engine_result); // out: NetworkOPs, TransactionSign, Submit
JSS(engine_result_code); // out: NetworkOPs, TransactionSign, Submit
JSS(engine_result_message); // out: NetworkOPs, TransactionSign, Submit
JSS(engine_result_reason); // out: NetworkOPs, TransactionSign, Submit
JSS(entire_set); // out: get_aggregate_price
JSS(ephemeral_key); // out: ValidatorInfo
// in/out: Manifest
Expand Down
2 changes: 1 addition & 1 deletion include/xrpl/tx/Transactor.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ struct PreclaimContext
beast::Journal j = beast::Journal{beast::Journal::getNullSink()})
: registry(registry)
, view(view)
, preflightResult(preflightResult)
, preflightResult(std::move(preflightResult))
, flags(flags)
, tx(tx)
, parentBatchId(parentBatchId)
Expand Down
2 changes: 1 addition & 1 deletion include/xrpl/tx/applySteps.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ struct ApplyResult
std::optional<TxMeta> metadata;

ApplyResult(TER t, bool a, std::optional<TxMeta> m = std::nullopt)
: ter(t), applied(a), metadata(std::move(m))
: ter(std::move(t)), applied(a), metadata(std::move(m))
{
}
};
Expand Down
2 changes: 1 addition & 1 deletion include/xrpl/tx/paths/detail/Steps.h
Original file line number Diff line number Diff line change
Expand Up @@ -505,7 +505,7 @@
public:
TER ter;

FlowException(TER t, std::string const& msg) : std::runtime_error(msg), ter(t)
FlowException(TER t, std::string const& msg) : std::runtime_error(msg), ter(std::move(t))

Check warning on line 508 in include/xrpl/tx/paths/detail/Steps.h

View check run for this annotation

Codecov / codecov/patch

include/xrpl/tx/paths/detail/Steps.h#L508

Added line #L508 was not covered by tests
{
}

Expand Down
6 changes: 3 additions & 3 deletions src/libxrpl/protocol/TER.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ transResults()
}

bool
transResultInfo(TER code, std::string& token, std::string& text)
transResultInfo(TERRaw code, std::string& token, std::string& text)
{
auto& results = transResults();

Expand All @@ -248,7 +248,7 @@ transResultInfo(TER code, std::string& token, std::string& text)
}

std::string
transToken(TER code)
transToken(TERRaw code)
{
std::string token;
std::string text;
Expand All @@ -257,7 +257,7 @@ transToken(TER code)
}

std::string
transHuman(TER code)
transHuman(TERRaw code)
{
std::string token;
std::string text;
Expand Down
Loading
Loading