Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,22 @@
# Changes

### 10.10.0.0 07/28/2026
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated
* **Transaction fields declared by the protocol but missing from the models** — `TxFormat` listed them and the binary codec knew them, so the values travelled fine through `Dictionary<string, object>`, but the typed models had no property: reading silently dropped them and the typed API could not set them at all. A field-level diff of `TxFormat` against the transaction models found four such names; the earlier 10.7.0.0 completeness pass had closed the ledger-object side (`LOAccountRoot.WalletLocator`/`WalletSize`) but not the transaction side:
* `TransactionRequest`/`TransactionResponse` + **`Delegate`** and **`OperationLimit`** — both are rippled *common* fields (`TxFormats.cpp` `commonFields`), valid on every transaction type, so they belong on the shared base rather than on individual transactions. `Delegate` identifies a transaction submitted under DelegateSet permissions (previously readable only from raw JSON, though `BatchUtils` already honored it when collecting required batch signers). `OperationLimit` is inert on XRPL but is the marker Xahau's Burn-2-Mint reads on a burn — consumers no longer need to build the burn as a dictionary to get it onto the wire, nor read raw JSON to tell a burn from a plain `AccountSet`
* `AccountSet`/`AccountSetResponse` + **`WalletLocator`** and **`WalletSize`** — both still stand in rippled's AccountSet format (`transactions.macro`). `WalletSize` is legacy and not acted on by the transactor; it is exposed so a transaction carrying it survives a round trip
* `ValidateBaseTransaction` type-checks the two new common fields, as it already does for every other common field
* **`Target` deliberately not added** — it is not a protocol field: `sfTarget` is retired (AccountID nth 7 is marked unused in `sfields.macro`, and the name is absent from `definitions.json`), and since the TicketBatch amendment rippled's TicketCreate carries only `sfTicketCount`. The stale `Target`/`Expiration` entries were removed from `TicketCreate` in `TxFormat`; `Field.Target` stays in the codec so historical blobs still decode
* `TestUTransactionProtocolFields` pins the whole cycle — deserialization, `ToJson`/`ToDictionary` round trip, typed-vs-dictionary signing parity byte for byte, and, as the regression guard for touching the common base, blobs of transactions that set none of the new fields against signatures captured from 10.9.1.0

* **`TxFormat` brought into full conformance with rippled, and held there** — the table is inert at runtime (`TxFormat.Validate` is not on the signing path; the codec serializes from `definitions.json`), so wrong entries produced no symptom and nothing in the suite noticed. A field-by-field diff against rippled `transactions.macro` found six wrong formats out of 82; all are corrected and the table now matches upstream exactly:
* `CheckCreate`, `CheckCash`, `CheckCancel` — all three were a verbatim copy of the `PaymentChannelClaim` entry above them (`Channel`/`Amount`/`Balance`/`Signature`/`PublicKey`). Now `CheckCreate` = `Destination`+`SendMax` required, `Expiration`/`DestinationTag`/`InvoiceID` optional; `CheckCash` = `CheckID` required, `Amount`/`DeliverMin` optional; `CheckCancel` = `CheckID` required
* `NFTokenMint` — was missing `Amount`/`Destination`/`Expiration`; the NFTokenMintOffer fields reached the *model* in 10.7.0.0 but the format never followed, so the two had silently drifted apart from each other
* `OracleSet` — dropped `BaseAsset`/`QuoteAsset`/`AssetPrice`/`Scale`, and `SignerListSet` dropped `WalletLocator`: in both cases these are members of a nested object (`PriceDataSeries` entries, `SignerEntry`) that had been hoisted to the top level
* `VaultCreate` — dropped `Amount`, which is not a field of that transaction
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated
* **`TestUTxFormatConformance`** now diffs every one of the 82 formats against a vendored, ref-pinned copy of `transactions.macro` (`Tests/Xrpl.Tests/Fixtures/`) and reports each divergence by name. Pinned rather than live on purpose: upstream drift is already protocol-watch's job (`transactions.macro` is in its watch list), and a network-backed test would go red on Ripple's release schedule instead of ours. The parser fails loudly on an unknown `Soe*` keyword or a short parse, so a macro-layout change cannot turn the guard green on an empty table
* **Fix `CheckCreate.InvoiceID`: `uint?` → `string`** (**breaking signature change**, though nothing could have depended on it) — `sfInvoiceID` is a `Hash256`, `Payment.InvoiceID` was already `string`, and `ValidateCheckCreate` already rejected anything but a string. The typed property was `uint?`, so every non-null value threw at signing time (``Can't decode `InvoiceID` from `123` ``): the field was unusable through the typed API in any release that had it. Found while writing the integration coverage for the corrected `CheckCreate` format
* **Integration coverage for the corrected field sets** (`TestIProtocolFieldSets`, standalone stand) — `TxFormat` itself cannot be exercised end-to-end, so these pin the claim underneath it against a real node: `CheckCreate` carrying `Expiration`/`DestinationTag`/`InvoiceID` lands and the `Check` object reads them back; `CheckCash` settles through the previously untested `DeliverMin` branch; `NFTokenMint` with `Amount`/`Destination`/`Expiration` creates the mint-time sell offer; and an `AccountSet` with `WalletLocator`/`WalletSize`/`OperationLimit` survives a full ledger round trip back into the typed `AccountSetResponse` — the end-to-end proof for the model work above

### 10.9.1.0 07/27/2026
* **Fix `account_tx` losing the payment amount and, on API v1, the whole transaction** — a silent regression introduced by the 10.3.0.0 `Newtonsoft.Json` → `System.Text.Json` migration; affects every release from 10.3.0.0 on:
* `Payment`/`PaymentResponse.DeliverMax` — the private set-only alias that maps API v2's `DeliverMax` onto `Amount` was carried over from Newtonsoft (which deserializes attributed non-public members) but `System.Text.Json` skips non-public members without `[JsonInclude]`. Every Payment read through `AccountTransactions`, `TxV2` or the transaction streams came back with `Amount = null` — no exception, no diagnostic. `Tx()` was unaffected because it pins `ApiVersion = 1`, and `meta.delivered_amount` kept parsing correctly, which is why the loss went unnoticed. The alias stays set-only, so `DeliverMax` is still never serialized back out
Expand Down
Loading
Loading