refactor: Collapse transactions.macro settings into a TxSettings struct (#8001)

Co-authored-by: Timur Yalymov <36795566+tyalymov@users.noreply.github.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Vito Tumas <5780819+Tapanito@users.noreply.github.com>
Co-authored-by: Ayaz Salikhov <mathbunnyru@users.noreply.github.com>
This commit is contained in:
Mayukha Vadari
2026-08-20 19:25:27 +00:00
committed by GitHub
parent 3ab5288ef2
commit 85512541ad
95 changed files with 520 additions and 446 deletions

View File

@@ -10,6 +10,7 @@
#include <xrpl/protocol/STTx.h>
#include <xrpl/protocol/TxFlags.h> // IWYU pragma: keep
#include <xrpl/protocol/TxFormats.h>
#include <xrpl/protocol/TxSettings.h>
#include <algorithm>
#include <cstdint>
@@ -40,16 +41,24 @@ Permission::GranularPermissionEntry::GranularPermissionEntry(
Permission::Permission()
{
{
#pragma push_macro("UNWRAP")
#undef UNWRAP
#pragma push_macro("TRANSACTION")
#undef TRANSACTION
#define TRANSACTION(tag, value, name, delegable, amendment, ...) \
txDelegationMap_[static_cast<TxType>(value)] = {amendment, delegable};
#define UNWRAP(...) __VA_ARGS__
#define TRANSACTION(tag, value, name, settings, ...) \
{ \
TxSettings const s = UNWRAP settings; \
txDelegationMap_[static_cast<TxType>(value)] = {s.amendment, s.delegable}; \
}
#include <xrpl/protocol/detail/transactions.macro>
#undef TRANSACTION
#pragma pop_macro("TRANSACTION")
#undef UNWRAP
#pragma pop_macro("UNWRAP")
}
granularPermissionsByName_ = {
@@ -242,7 +251,7 @@ Permission::isDelegable(std::uint32_t permissionValue, Rules const& rules) const
// Tx-level permissions require the transaction type itself to be delegable, and
// the corresponding amendment enabled.
return txIt != txDelegationMap_.end() && txIt->second.delegable != NotDelegable &&
return txIt != txDelegationMap_.end() && txIt->second.delegable != Delegation::NotDelegable &&
amendmentEnabled(txIt->second);
}

View File

@@ -45,7 +45,7 @@ TxFormats::TxFormats()
#undef TRANSACTION
#define UNWRAP(...) __VA_ARGS__
#define TRANSACTION(tag, value, name, delegable, amendment, privileges, fields) \
#define TRANSACTION(tag, value, name, settings, fields) \
add(jss::name, tag, UNWRAP fields, getCommonFields());
#include <xrpl/protocol/detail/transactions.macro>

View File

@@ -288,7 +288,8 @@ TransfersNotFrozen::validateFrozenState(
// individually-frozen or deep-frozen AMM trust lines.
// Post-fixCleanup3_4_0: AMMClawbacks are allowed to override all freeze types.
bool const isAMMLine = change.line->isFlag(lsfAMMNode);
if ((fixOverrideFreeze || !isAMMLine || globalFreeze) && hasPrivilege(tx, OverrideFreeze))
if ((fixOverrideFreeze || !isAMMLine || globalFreeze) &&
hasPrivilege(tx, Privilege::OverrideFreeze))
{
JLOG(j.debug()) << "Invariant check allowing funds to be moved "
<< (change.balanceChangeSign > 0 ? "to" : "from")

View File

@@ -25,6 +25,7 @@
#include <xrpl/protocol/SystemParameters.h>
#include <xrpl/protocol/TER.h>
#include <xrpl/protocol/TxFormats.h>
#include <xrpl/protocol/TxSettings.h>
#include <xrpl/protocol/UintTypes.h>
#include <xrpl/protocol/XRPAmount.h>
#include <xrpl/tx/invariants/InvariantCheckPrivilege.h>
@@ -40,12 +41,15 @@
namespace xrpl {
#pragma push_macro("UNWRAP")
#undef UNWRAP
#pragma push_macro("TRANSACTION")
#undef TRANSACTION
#define TRANSACTION(tag, value, name, delegable, amendment, privileges, ...) \
case tag: { \
return (privileges) & priv; \
#define UNWRAP(...) __VA_ARGS__
#define TRANSACTION(tag, value, name, settings, ...) \
case tag: { \
return ((TxSettings UNWRAP settings).privileges & priv) != Privilege::NoPriv; \
}
bool
@@ -63,6 +67,8 @@ hasPrivilege(STTx const& tx, Privilege priv)
#undef TRANSACTION
#pragma pop_macro("TRANSACTION")
#undef UNWRAP
#pragma pop_macro("UNWRAP")
// Returns the human-readable name of a ledger entry's type, falling back to
// the numeric type if the format is somehow unknown.
@@ -436,7 +442,7 @@ AccountRootsNotDeleted::finalize(
// transaction when the total AMM LP Tokens balance goes to 0.
// A successful AccountDelete or AMMDelete MUST delete exactly
// one account root.
if (hasPrivilege(tx, MustDeleteAcct) && isTesSuccess(result))
if (hasPrivilege(tx, Privilege::MustDeleteAcct) && isTesSuccess(result))
{
if (accountsDeleted_ == 1)
return true;
@@ -457,7 +463,7 @@ AccountRootsNotDeleted::finalize(
// A successful AMMWithdraw/AMMClawback MAY delete one account root
// when the total AMM LP Tokens balance goes to 0. Not every AMM withdraw
// deletes the AMM account, accountsDeleted_ is set if it is deleted.
if (hasPrivilege(tx, MayDeleteAcct) && isTesSuccess(result) && accountsDeleted_ == 1)
if (hasPrivilege(tx, Privilege::MayDeleteAcct) && isTesSuccess(result) && accountsDeleted_ == 1)
return true;
if (accountsDeleted_ == 0)
@@ -760,14 +766,15 @@ ValidNewAccountRoot::finalize(
}
// From this point on we know exactly one account was created.
if (hasPrivilege(tx, CreateAcct | CreatePseudoAcct) && isTesSuccess(result))
if (hasPrivilege(tx, Privilege::CreateAcct | Privilege::CreatePseudoAcct) &&
isTesSuccess(result))
{
bool const pseudoAccount =
(pseudoAccount_ &&
(view.rules().enabled(featureSingleAssetVault) ||
view.rules().enabled(featureLendingProtocol)));
if (pseudoAccount && !hasPrivilege(tx, CreatePseudoAcct))
if (pseudoAccount && !hasPrivilege(tx, Privilege::CreatePseudoAcct))
{
JLOG(j.fatal()) << "Invariant failed: pseudo-account created by a "
"wrong transaction type";

View File

@@ -211,7 +211,7 @@ ValidMPTIssuance::finalize(
}
auto const txnType = tx.getTxnType();
if (hasPrivilege(tx, CreateMptIssuance))
if (hasPrivilege(tx, Privilege::CreateMptIssuance))
{
if (mptIssuancesCreated_ == 0)
{
@@ -232,7 +232,7 @@ ValidMPTIssuance::finalize(
return mptIssuancesCreated_ == 1 && mptIssuancesDeleted_ == 0;
}
if (hasPrivilege(tx, DestroyMptIssuance))
if (hasPrivilege(tx, Privilege::DestroyMptIssuance))
{
if (mptIssuancesDeleted_ == 0)
{
@@ -259,7 +259,8 @@ ValidMPTIssuance::finalize(
// non-amendment-gated side effects.
bool const enforceEscrowFinish = (txnType == ttESCROW_FINISH) &&
(rules.enabled(featureSingleAssetVault) || lendingProtocolEnabled);
if (hasPrivilege(tx, MustAuthorizeMpt | MayAuthorizeMpt) || enforceEscrowFinish)
if (hasPrivilege(tx, Privilege::MustAuthorizeMpt | Privilege::MayAuthorizeMpt) ||
enforceEscrowFinish)
{
bool const submittedByIssuer = tx.isFieldPresent(sfHolder);
@@ -275,7 +276,7 @@ ValidMPTIssuance::finalize(
"succeeded but deleted issuances";
return false;
}
if (mptV2Enabled && hasPrivilege(tx, MayAuthorizeMpt) &&
if (mptV2Enabled && hasPrivilege(tx, Privilege::MayAuthorizeMpt) &&
(txnType == ttAMM_WITHDRAW || txnType == ttAMM_CLAWBACK))
{
if (submittedByIssuer && txnType == ttAMM_WITHDRAW && mptokensCreated_ > 0)
@@ -311,7 +312,7 @@ ValidMPTIssuance::finalize(
return false;
}
else if (
!submittedByIssuer && hasPrivilege(tx, MustAuthorizeMpt) &&
!submittedByIssuer && hasPrivilege(tx, Privilege::MustAuthorizeMpt) &&
(mptokensCreated_ + mptokensDeleted_ != 1))
{
// if the holder submitted this tx, then a mptoken must be
@@ -324,7 +325,7 @@ ValidMPTIssuance::finalize(
return true;
}
if (hasPrivilege(tx, MayCreateMpt))
if (hasPrivilege(tx, Privilege::MayCreateMpt))
{
bool const submittedByIssuer = tx.isFieldPresent(sfHolder);
@@ -379,7 +380,7 @@ ValidMPTIssuance::finalize(
return true;
}
if (hasPrivilege(tx, MayDeleteMpt) &&
if (hasPrivilege(tx, Privilege::MayDeleteMpt) &&
((txnType == ttAMM_DELETE && mptokensDeleted_ <= 2) || mptokensDeleted_ == 1) &&
mptokensCreated_ == 0 && mptIssuancesCreated_ == 0 && mptIssuancesDeleted_ == 0)
return true;
@@ -856,7 +857,7 @@ ValidMPTTransfer::finalize(
ReadView const& view,
beast::Journal const& j)
{
if (hasPrivilege(tx, OverrideFreeze))
if (hasPrivilege(tx, Privilege::OverrideFreeze))
return true;
// XLS-0066: a broker must be able to default an already-late loan

View File

@@ -206,7 +206,7 @@ NFTokenCountTracking::finalize(
ReadView const& view,
beast::Journal const& j) const
{
if (!hasPrivilege(tx, ChangeNftCounts))
if (!hasPrivilege(tx, Privilege::ChangeNftCounts))
{
if (beforeMintedTotal_ != afterMintedTotal_)
{

View File

@@ -346,7 +346,7 @@ ValidVault::finalize(
if (afterVault_.empty() && beforeVault_.empty())
{
if (hasPrivilege(tx, MustModifyVault))
if (hasPrivilege(tx, Privilege::MustModifyVault))
{
JLOG(j.fatal()) << //
"Invariant failed: vault operation succeeded without modifying "
@@ -357,7 +357,8 @@ ValidVault::finalize(
return true; // Not a vault operation
}
if (!(hasPrivilege(tx, MustModifyVault) || hasPrivilege(tx, MayModifyVault)))
if (!(hasPrivilege(tx, Privilege::MustModifyVault) ||
hasPrivilege(tx, Privilege::MayModifyVault)))
{
JLOG(j.fatal()) << //
"Invariant failed: vault updated by a wrong transaction type";

View File

@@ -47,6 +47,7 @@
#include <xrpl/protocol/SecretKey.h>
#include <xrpl/protocol/TER.h>
#include <xrpl/protocol/TxFlags.h>
#include <xrpl/protocol/TxSettings.h>
#include <xrpl/protocol/XRPAmount.h>
#include <xrpl/protocol/jss.h>
@@ -2718,19 +2719,24 @@ class Delegate_test : public beast::unit_test::Suite
std::size_t delegableCount = 0;
#pragma push_macro("UNWRAP")
#undef UNWRAP
#pragma push_macro("TRANSACTION")
#undef TRANSACTION
#define TRANSACTION(tag, value, name, txDelegable, ...) \
if (txDelegable == xrpl::Delegable) \
{ \
delegableCount++; \
#define UNWRAP(...) __VA_ARGS__
#define TRANSACTION(tag, value, name, settings, ...) \
if ((xrpl::TxSettings UNWRAP settings).delegable == xrpl::Delegation::Delegable) \
{ \
delegableCount++; \
}
#include <xrpl/protocol/detail/transactions.macro>
#undef TRANSACTION
#pragma pop_macro("TRANSACTION")
#undef UNWRAP
#pragma pop_macro("UNWRAP")
// ====================================================================
// IMPORTANT NOTICE: