diff --git a/cmake/scripts/codegen/generate_tx_classes.py b/cmake/scripts/codegen/generate_tx_classes.py index 6c7546cc41..1d5d97ec59 100644 --- a/cmake/scripts/codegen/generate_tx_classes.py +++ b/cmake/scripts/codegen/generate_tx_classes.py @@ -105,6 +105,15 @@ def parse_settings(settings_str): if len(re.findall(r"\.\w+", body)) != len(seen): raise ValueError(f"Could not parse every setting in {settings_str!r}") + # A blob with content but no designated initializer is positional, which + # would otherwise be read as "all defaults" and silently generate the + # wrong output. + if body.strip() and not seen: + raise ValueError( + "TxSettings requires designated initializers (.member = value), " + f"got {settings_str!r}" + ) + return settings diff --git a/include/xrpl/protocol/TxSettings.h b/include/xrpl/protocol/TxSettings.h index 984c483334..142a4b3b25 100644 --- a/include/xrpl/protocol/TxSettings.h +++ b/include/xrpl/protocol/TxSettings.h @@ -18,7 +18,7 @@ enum Delegation { Delegable, NotDelegable }; * These are declared per-transaction in transactions.macro (via * TxSettings::privileges) and enforced in InvariantCheck.cpp. */ -// Bitwise flags, 86 files, used in macros files +// Bitwise flags, used in macro files // NOLINTNEXTLINE(cppcoreguidelines-use-enum-class) enum Privilege { NoPriv = 0x0000, // The transaction can not do any of the enumerated operations @@ -71,7 +71,7 @@ struct TxSettings /** * The amendment gating this transaction, or uint256{} if always available. */ - uint256 amendment{}; + uint256 amendment; /** * Operations this transaction is permitted to perform. diff --git a/include/xrpl/protocol/detail/transactions.macro b/include/xrpl/protocol/detail/transactions.macro index 3ca5def3c4..03c31a0131 100644 --- a/include/xrpl/protocol/detail/transactions.macro +++ b/include/xrpl/protocol/detail/transactions.macro @@ -21,7 +21,7 @@ * struct TxSettings * { * Delegation delegable = Delegable; - * uint256 amendment{}; + * uint256 amendment; * Privilege privileges = NoPriv; * }; * @@ -30,6 +30,10 @@ * * ({.delegable = Delegation::NotDelegable, .amendment = featureFoo}) * + * You must use designated initializers, as shown above. Positional + * initialization such as `({Delegation::NotDelegable})` is not supported, + * because the code generator reads these settings by member name. + * * The `privileges` setting is a bitfield defining which operations the * transaction can perform. The values are defined in TxSettings.h and * enforced in InvariantCheck.cpp.