-
Notifications
You must be signed in to change notification settings - Fork 8
Add Dynamic MPT (XLS-0094) workload #89
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| #!/usr/bin/env bash | ||
|
|
||
| curl --silent http://workload:8000/mpt/set/dynamic/random |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -34,9 +34,15 @@ warn_unused_ignores = true | |
| # complementary flow/annotation checker, so third-party types resolve as Any here. | ||
| ignore_missing_imports = true | ||
|
|
||
| # Confidential MPT (XLS-0096), sponsor (XLS-68), and the rest of the models come from | ||
| # xrpl-py's pre-3.3-release-group branch (converges the pre-release WIP branches; not yet | ||
| # released). Proof generation (xrpl/ext/confidential) is EXCLUDED from the core wheel this | ||
| # installs and is built separately in the Antithesis image; see scripts/setup-confidential-crypto.sh. | ||
| # Confidential MPT (XLS-0096), Dynamic MPT (XLS-0094), sponsor (XLS-68), and the rest of | ||
| # the models come from xrpl-py's pre-3.3-release-group branch (converges the pre-release WIP | ||
| # branches; not yet released). Proof generation (xrpl/ext/confidential) is EXCLUDED from the | ||
| # 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" } | ||
|
|
||
| [dependency-groups] | ||
| dev = [ | ||
| "pytest>=9.1.1", | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 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. |
||
| ] | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -37,6 +37,7 @@ | |
| MPTokenAuthorize, | ||
| MPTokenIssuanceCreate, | ||
| MPTokenIssuanceCreateFlag, | ||
| MPTokenIssuanceCreateMutableFlag, | ||
| MPTokenIssuanceSet, | ||
| MPTokenIssuanceSetFlag, | ||
| NFTokenCreateOffer, | ||
|
|
@@ -99,6 +100,26 @@ | |
| _HOLDER_RANGE = range(62, 72) # accounts[62..71] | ||
| _VAULT_RANGE = range(10, 17) # accounts[10..16] | ||
|
|
||
| # Dynamic MPT (XLS-0094): opt-in mutable cohort created with create-time | ||
| # MutableFlags declaring every capability as enable-able + metadata/fee mutable, | ||
| # on indices unused elsewhere. | ||
| _DYNAMIC_MPT_RANGE = range(53, 56) # accounts[53..55] | ||
| # Immutable cohort: created with NO MutableFlags, so every later flag-enable / | ||
| # metadata / transfer-fee mutation must fail with tecNO_PERMISSION. | ||
| _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 = ( | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. All three issuances declare Split it: one blockable cohort that declares |
||
| MPTokenIssuanceCreateMutableFlag.TMF_MPT_CAN_ENABLE_CAN_LOCK | ||
| | MPTokenIssuanceCreateMutableFlag.TMF_MPT_CAN_ENABLE_REQUIRE_AUTH | ||
| | MPTokenIssuanceCreateMutableFlag.TMF_MPT_CAN_ENABLE_CAN_ESCROW | ||
| | MPTokenIssuanceCreateMutableFlag.TMF_MPT_CAN_ENABLE_CAN_TRADE | ||
| | MPTokenIssuanceCreateMutableFlag.TMF_MPT_CAN_ENABLE_CAN_TRANSFER | ||
| | MPTokenIssuanceCreateMutableFlag.TMF_MPT_CAN_ENABLE_CAN_CLAWBACK | ||
| | MPTokenIssuanceCreateMutableFlag.TMF_MPT_CAN_MUTATE_METADATA | ||
| | MPTokenIssuanceCreateMutableFlag.TMF_MPT_CAN_MUTATE_TRANSFER_FEE | ||
| ) | ||
|
|
||
| # Confidential MPT (XLS-0096): issuers + holders on indices unused elsewhere. | ||
| _CONF_ISSUER_RANGE = range(7, 9) # accounts[7..8] | ||
| _CONF_HOLDER_RANGE = range(72, 77) # accounts[72..76] | ||
|
|
@@ -967,6 +988,8 @@ async def run_setup(workload: Workload) -> dict[str, int]: | |
| | set(range(30, 36)) | ||
| | set(range(40, 43)) | ||
| | set(range(50, 53)) | ||
| | set(_DYNAMIC_MPT_RANGE) | ||
| | set(_IMMUTABLE_MPT_RANGE) | ||
| | set(range(60, 72)) | ||
| | set(range(72, 77)) | ||
| # Cross-resource pool (Phase 4): rich accts + their delegates/sponsors must | ||
|
|
@@ -1093,6 +1116,52 @@ async def run_setup(workload: Workload) -> dict[str, int]: | |
| _mpt_issuance_exists, | ||
| ) | ||
|
|
||
| # ── 4b. Dynamic MPT (XLS-0094) cohorts ────────────────────────── | ||
| # XLS-0094 is opt-in: an issuance is immutable unless a create-time | ||
| # MutableFlags (tmfMPT*) bit declares a capability/field as mutable. The | ||
| # mutable cohort (53-55) declares every CAN_ENABLE_* bit plus | ||
| # CAN_MUTATE_METADATA/CAN_MUTATE_TRANSFER_FEE, so every later flag-enable / | ||
| # metadata / TransferFee mutation passes preclaim; base CanTransfer lets | ||
| # fee>0 mutations stick and CanLock keeps the regular lock/unlock Set path | ||
| # reachable on this cohort. The immutable cohort (56-58) sends NO MutableFlags | ||
| # so every mutation reliably draws tecNO_PERMISSION. | ||
| summary["dynamic_mpt_issuances"] = await _run_phase( | ||
| workload, | ||
| "dynamic_mpt", | ||
| [ | ||
| ( | ||
| "MPTokenIssuanceCreate", | ||
| MPTokenIssuanceCreate( | ||
| account=accs[i].address, | ||
| flags=_LOCK | _XFER, | ||
| mutable_flags=_DYNAMIC_MUTABLE_FLAGS, | ||
| ), | ||
| accs[i].wallet, | ||
| ) | ||
| for i in _DYNAMIC_MPT_RANGE | ||
| if i < len(accs) | ||
| ], | ||
| _mpt_issuance_exists, | ||
| ) | ||
|
|
||
| summary["immutable_mpt_issuances"] = await _run_phase( | ||
| workload, | ||
| "immutable_mpt", | ||
| [ | ||
| ( | ||
| "MPTokenIssuanceCreate", | ||
| MPTokenIssuanceCreate( | ||
| account=accs[i].address, | ||
| flags=_LOCK | _XFER, | ||
| ), | ||
| accs[i].wallet, | ||
| ) | ||
| for i in _IMMUTABLE_MPT_RANGE | ||
| if i < len(accs) | ||
| ], | ||
| _mpt_issuance_exists, | ||
| ) | ||
|
|
||
| # ── 5. MPT authorization: holders authorize for each issuance ──── | ||
| mpt_auth_txns = [] | ||
| for mpt in workload.mpt_issuances: | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -77,8 +77,14 @@ | |
| loan_pay, | ||
| loan_set, | ||
| ) | ||
| from workload.transactions.mpt import mpt_authorize, mpt_create, mpt_destroy, mpt_issuance_set | ||
| from workload.transactions.mpt import ( | ||
| mpt_authorize, | ||
| mpt_create, | ||
| mpt_destroy, | ||
| mpt_issuance_set, | ||
| ) | ||
| from workload.transactions.mpt_dex import offer_create_mpt, payment_mpt | ||
| from workload.transactions.mpt_dynamic import mpt_issuance_set_dynamic | ||
| from workload.transactions.nft import ( | ||
| nftoken_accept_offer, | ||
| nftoken_burn, | ||
|
|
@@ -287,6 +293,9 @@ def _on_mpt_create(w: Workload, tx: dict, meta: dict) -> None: | |
| require_auth=bool(flags & int(MPTokenIssuanceCreateFlag.TF_MPT_REQUIRE_AUTH)), | ||
| # lock state set later by setup, not at create | ||
| locked=False, | ||
| # XLS-0094: create-time MutableFlags (tmfMPT*, opt-in). 0 ⇒ fully | ||
| # immutable; a set bit declares a flag/field may later be enabled/mutated. | ||
| mutable_flags=int(tx.get("MutableFlags", 0) or 0), | ||
| ) | ||
| w.mpt_issuances.append(issuance) | ||
|
|
||
|
|
@@ -1098,6 +1107,17 @@ def _on_payment_maybe_sponsored_account(w: Workload, tx: dict, meta: dict) -> No | |
| lambda w: (w.accounts, w.mpt_issuances, w.client), | ||
| None, | ||
| ), | ||
| # DynamicMPTSet (XLS-0094): synthetic name; on-ledger type stays | ||
| # MPTokenIssuanceSet (mutation carries MutableFlags set-enable bits, | ||
| # MPTokenMetadata, or TransferFee). ws_listener fires tx_result for this | ||
| # bucket; no separate updater. | ||
| ( | ||
| "DynamicMPTSet", | ||
| "/mpt/set/dynamic/random", | ||
| mpt_issuance_set_dynamic, | ||
| lambda w: (w.accounts, w.mpt_issuances, w.client), | ||
| None, | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nothing updates tracked state when a set-enable lands. Flip CanTrade on-ledger and |
||
| ), | ||
| ( | ||
| "MPTokenIssuanceDestroy", | ||
| "/mpt/destroy/random", | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.