Add Dynamic MPT (XLS-0094) workload - #89
Conversation
DynamicMPTSet handler submitted as MPTokenIssuanceSet using the opt-in mutable_flags model from xrpl-py pre-3.3-release-group. Valid paths cover flag-enable, metadata, and transfer-fee mutations on a mutable cohort (accounts 53-55); faulty paths cover fake issuance, non-issuer, immutable-cohort (56-58) mutation, oversize metadata, and generative fuzz. Includes setup cohorts, state tracking of mutable_flags/can_transfer, ws_listener routing, registry/ticket wiring, driver script, and unit tests.
vvysokikh1
left a comment
There was a problem hiding this comment.
CLAUDE.md needs updating in the same change — setup chain, MPT cohorts section, synthetic-names list.
| "/mpt/set/dynamic/random", | ||
| mpt_issuance_set_dynamic, | ||
| lambda w: (w.accounts, w.mpt_issuances, w.client), | ||
| None, |
There was a problem hiding this comment.
Nothing updates tracked state when a set-enable lands. Flip CanTrade on-ledger and MPTokenIssuance.can_trade stays False — these issuances sit in the mpt_dex no-trade fault pool, so that curated tecNO_PERMISSION vector silently becomes a real trade. Add an updater on the real "MPTokenIssuanceSet" row (same trick as _on_payment_maybe_sponsored_account on "Payment") that ORs the set bits into the tracked flags.
|
|
||
| [dependency-groups] | ||
| dev = [ | ||
| "pytest>=9.1.1", |
There was a problem hiding this comment.
Nothing runs these tests — CI doesn't call pytest and neither does the pre-push list. Wire it into checks.yml and CLAUDE.md, or they'll rot.
| return [m for m in mpt_issuances if m.mutable_flags and m.issuer in accounts] | ||
|
|
||
|
|
||
| def _immutable_issuances( |
There was a problem hiding this comment.
This matches every zero-mutable_flags issuance, including all the regular step-4 cohorts — so the dedicated 56–58 cohort only buys guaranteed existence. Drop it, or keep it and say why in the setup comment.
| _IMMUTABLE_MPT_RANGE = range(56, 59) # accounts[56..58] | ||
| # Opt-in create-time MutableFlags for the mutable cohort: declare every | ||
| # capability enable-able + metadata/transfer-fee mutable. | ||
| _DYNAMIC_MUTABLE_FLAGS = ( |
There was a problem hiding this comment.
All three issuances declare CAN_ENABLE_REQUIRE_AUTH, and enables are one-way (no clear bits in the pinned xrpl-py). Holders get these tokens in step 5 with no issuer-side auth, so the first RequireAuth flip locks them out permanently — over a long run all three converge to that and the cohort goes dark.
Split it: one blockable cohort that declares CAN_ENABLE_REQUIRE_AUTH (holders getting locked out is the point), one safe cohort without it (RequireAuth there = deterministic tecNO_PERMISSION, and its holders can never be blocked). Keeps valid traffic alive for the whole run.
| transfer_fee=params.mpt_transfer_fee(), | ||
| ) | ||
| else: | ||
| # set-enable latch; re-enabling an already-set capability is a no-op tesSUCCESS. |
There was a problem hiding this comment.
Six one-way latches × three issuances — everything's latched early in a run, then this arm is a permanent no-op tesSUCCESS. Weight the metadata/fee arms higher.
| # core wheel this installs and is built separately in the Antithesis image; see | ||
| # scripts/setup-confidential-crypto.sh. | ||
| [tool.uv.sources] | ||
| xrpl-py = { git = "https://github.com/XRPLF/xrpl-py.git", branch = "pre-3.3-release-group" } |
There was a problem hiding this comment.
XLS-0094 models now also hang off this moving branch pin, which already broke the build once (flag rename). Pin a rev — fine as a follow-up.
|
|
||
| # tmfMPTSet* set-enable bits: which capability a mutation turns on. Each requires | ||
| # the matching TMF_MPT_CAN_ENABLE_* declared in the create-time MutableFlags. | ||
| _SET_ENABLE_FLAGS = [ |
There was a problem hiding this comment.
xrpl-py has seven set bits, this list has six — TMF_MPT_SET_CAN_HOLD_CONFIDENTIAL_BALANCE is missing (and the matching CAN_ENABLE at create). Deliberate? If so, comment why. If not, an issuance turning confidential-capable mid-run is worth having.
Adds a
DynamicMPTSetworkload exercising XLS-0094 (mutable MPT issuances), submitted on-ledger asMPTokenIssuanceSet.Model — opt-in mutability
An MPT issuance is immutable by default; mutability is granted only when a create-time
MutableFlags(tmfMPT*) bit declares a capability/field as mutable. A mutatingMPTokenIssuanceSetthen either:MutableFlagsset-enable bit (each requires the matchingCAN_ENABLE_*declared at create),MPTokenMetadata(requiresCAN_MUTATE_METADATA), orTransferFee(requiresCAN_MUTATE_TRANSFER_FEEand an already-enabledCanTransfer).All three ride typed xrpl-py fields; only the oversize-metadata malformation needs
submit_raw.Setup cohorts
_DYNAMIC_MUTABLE_FLAGSdeclaring every capability enable-able + metadata/transfer-fee mutable — feeds the valid paths.MutableFlags, so every later flag-enable / metadata / transfer-fee mutation fails withtecNO_PERMISSION— feeds a curated failure vector.Both are seeded through the
_run_phasesetup infrastructure.Faulty vectors
fuzz(generative),fake_issuance(tecOBJECT_NOT_FOUND),non_issuer(tecNO_PERMISSION),immutable_mutation(tecNO_PERMISSION), andoversize_metadata(temMALFORMED, viasubmit_rawsince xrpl-py rejects the length at construction).State tracking
MPTokenIssuancegains amutable_flagsfield;_on_mpt_createpopulates it from the create tx'sMutableFlags.ws_listenerroutes validatedMPTokenIssuanceSettxns carryingMutableFlags/MPTokenMetadata/TransferFeeinto the syntheticDynamicMPTSetbucket.Packaging
xrpl-pypinned to thepre-3.3-release-groupbranch (carries the XLS-0094 mutable-flag models the workload needs).Verification
check-imports,check-endpoints,check-fuzz-coverage,check-modifier-coverage,check-assembler-roundtrip— all pass.DynamicMPTSetis auto-classified by every Modifier via_TX_NAMES.tests/test_mpt_dynamic.py— 13 tests pass.Testing note
The workload image relies on the target
xrpldbeing built with XLS-0094 enabled. Run againststaging/3.3.xfromxrpld-private(per team guidance — notrippled/develop).Co-authored by Augment Code
Pull Request opened by Augment Code with guidance from the PR author