Skip to content

Observe LendingProtocolV1_1: principal-only accounting and closed-ended vaults - #91

Open
manasip-prog wants to merge 5 commits into
mainfrom
manasip/lending-v1_1-accounting
Open

Observe LendingProtocolV1_1: principal-only accounting and closed-ended vaults#91
manasip-prog wants to merge 5 commits into
mainfrom
manasip/lending-v1_1-accounting

Conversation

@manasip-prog

Copy link
Copy Markdown
Collaborator

Two commits, both under the LendingProtocolV1_1 amendment.

Principal-only accounting (XLS-66, rippled PR #582)

The amendment moves Vault.AssetsTotal from accrual- to cash-basis: interest no longer counts until it's paid. Legacy and amended vaults coexist forever (a pre-amendment vault never migrates), so the balance rows in workload::result were unattributable without knowing which basis produced them. tx_result now carries vault_le_version (Vault.LEVersion, XLS-65 §3.1.2.2) on any result touching a Vault node, and the balance_changes list tracks the vault's AssetsTotal/AssetsAvailable/LossUnrealized plus the broker's DebtTotal.

Closed-ended vaults + VaultDelete deletion reason (XLS-65)

VaultCreate gains VaultKind/SubscriptionDate/RedemptionDate; VaultDelete gains an optional MemoData deletion reason. The pinned xrpl-py has neither the model fields nor the codec definitions, so lending_v1_1_compat.py registers the field headers into the live binarycodec maps and subclasses both models. Validation stays server-side so faulty handlers can still build the out-of-range cases.

The amendment is latched off metadata, not config: a validated Vault's LEVersion is 1 only once the amendment is active, so the V1.1 fields join only after one has been seen. Pre-amendment they're temDISABLED — never validates, would starve the failure bucket.

A minority of vaults are closed-ended, so open-ended ones keep the phase-free deposit/withdraw valid paths stocked. Vault tracks the kind and both dates from the created node, and deposit/withdraw pick a vault whose current phase (Subscription / Investment / Redemption) permits the transaction. Date generation has two flavors: a long subscription window keeps a vault depositable for the whole run, a short one walks it through all three phases so the gates actually fire.

Faulty vectors: sub-kMinInvestmentPeriod gap (temMALFORMED), already-expired dates (tecEXPIRED — a tec, so it validates and feeds the failure bucket), out-of-enum VaultKind, and for VaultDelete an empty and an over-256-byte MemoData (validDataLength rejects both).

Genesis fix

Genesis was activating only Supported::Yes amendments, but Dockerfile.xrpld rewrites Supported::No to Yes before building — so LendingProtocolV1_1 was known to the binary yet inactive in the ledger, and every V1.1 field came back temDISABLED. Genesis now includes those too, skipping VoteBehavior::Obsolete (enabling one amendment-blocks the node).

Also scopes XRPLD_NO_PATCH_NIX_BINARY to the fuzzer's conan install, whose build folder lacks the loader script rippled's PatchNixBinary.cmake expects.

Follow-up

xrpl-py PR #1034 lands all of this upstream with matching field codes, so the shim's _register_field guard will stand down cleanly. It's targeting main rather than the pre-3.3-release-group branch we pin, and it adds client-side validation that would reject the deliberately-malformed vectors at construction — those move to submit_raw as part of the swap. Tracked separately.

Checks

check-imports, check-endpoints, check-fuzz-coverage, check-modifier-coverage, check-assembler-roundtrip, ruff, ruff format, basedpyright all pass. The two mypy no-any-return hits are pre-existing and untouched by this branch.

RXT-832


Pull Request opened by Augment Code with guidance from the PR author

Track the four Vault/LoanBroker fields the amendment moves (AssetsTotal,
AssetsAvailable, LossUnrealized, DebtTotal) and stamp Vault.LEVersion on any
result touching a Vault node, since LEVersion -- not amendment activation --
gates which accounting model a Vault follows and both coexist post-activation.
…-65)

LendingProtocolV1_1 adds VaultKind/SubscriptionDate/RedemptionDate to
VaultCreate and an optional MemoData deletion reason to VaultDelete. The
pinned xrpl-py has neither the model fields nor the codec definitions, so
lending_v1_1_compat registers the field headers into the live binarycodec
maps and subclasses both models. Length and range checks stay server-side
so faulty handlers can still build the out-of-range cases.

The amendment is latched off metadata, not config: a validated Vault's
LEVersion is 1 only once LendingProtocolV1_1 is active, so the V1.1 fields
join only after one has been seen. Pre-amendment they are temDISABLED, which
never validates and would starve the failure bucket.

VaultCreate now mints a minority of closed-ended vaults, so open-ended ones
keep the phase-free deposit/withdraw valid paths stocked. Vault tracks the
kind and both dates from the created node, and deposit/withdraw pick a vault
whose current phase permits the transaction. Faulty vectors cover the
sub-kMinInvestmentPeriod gap, already-expired dates, an out-of-enum
VaultKind, and for VaultDelete an empty and an over-256-byte MemoData
(validDataLength rejects both).

Genesis was activating only Supported::Yes amendments, but Dockerfile.xrpld
rewrites Supported::No to Yes before building, so LendingProtocolV1_1 was
known to the binary yet inactive in the ledger. Genesis now includes those
too, skipping VoteBehavior::Obsolete (enabling one amendment-blocks the
node). Also scopes XRPLD_NO_PATCH_NIX_BINARY to the fuzzer's conan install,
whose build folder lacks the loader script rippled's PatchNixBinary.cmake
expects.

RXT-832
Every XLS-65 path is gated on lending_v1_1_compat.enabled(), which latches off
a validated Vault's LEVersion. If that never flips -- amendment inactive, or a
genesis regression -- the whole feature goes dark while VaultCreate's
success/failure dims stay satisfied off the open-ended vectors, so a run would
report green having exercised none of it.

Five sometimes buckets off tx_result's validated stream: lending_v1_1_active
(the latch itself), vault_closed_ended_created (created node carries a nonzero
VaultKind), vault_deposit_phase_blocked (tecEXPIRED) and
vault_withdraw_phase_blocked (tecTOO_SOON) for the two phase gates, and
vault_delete_reason_used (validated MemoData). All must_hit=False, matching
conf_mpt_version_monotonic: they only fire against an xrpld with
LendingProtocolV1_1 active, so a run without it must not starve.

_fire_sometimes takes must_hit so the fire site can match its catalog entry.

RXT-832
The XLS-0096 crypto step cloned xrpl-py at `confidential-mpt`, a branch that
no longer exists on XRPLF/xrpl-py (no confidential-* ref remains). The clone
fails under `set -e`, so `build workload image` aborted ~30s in and every
Antithesis run since has never reached `launch experiment`.

`pre-3.3-release-group` — already the pin for the core dependency in
`pyproject.toml`, and the ref CLAUDE.md documents — carries the same
`xrpl/ext/confidential` source at MPT_CRYPTO_VERSION 1.0.2, matching the
rippled mpt-crypto pin. Using it for both means the proof bindings and the
installed models come from one ref rather than two that can drift.
rippled develop renamed CamelCase namespaces to snake_case
(XRPLF/rippled#7933): beast::IP -> beast::ip and xrpl::BuildInfo ->
xrpl::build_info. rippled-fuzzer (all branches) still uses the old
spelling in four call sites, so building the fuzzer fails against
develop and takes the whole `build xrpld` stage with it.

Rewrite the fuzzer's references in the image, gated on the cloned xrpld
actually declaring the new namespaces, so pre-rename refs (e.g.
xrpld-private staging/3.3.x-private) build unchanged. The includes keep
the BuildInfo.h filename, which the substitutions leave alone.

develop is the only ref carrying Lending v1.1 (closed-ended vaults
landed Aug 12, after the Aug 4 rename), so there is no commit with both
the v1.1 fields and the old namespaces to pin instead.
@manasip-prog
manasip-prog marked this pull request as ready for review September 2, 2026 17:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant