Skip to content

Merge injectable-definitions - #44

Merged
AlexanderBuzz merged 2 commits into
masterfrom
injectable-definitions
Aug 24, 2026
Merged

Merge injectable-definitions#44
AlexanderBuzz merged 2 commits into
masterfrom
injectable-definitions

Conversation

@AlexanderBuzz

@AlexanderBuzz AlexanderBuzz commented Aug 24, 2026

Copy link
Copy Markdown
Owner

Summary

Prepares the ground for a separate Xahau package by letting the codec work against definitions handed in from outside.

2.0.0 documented that Xahau support is broken for 23 transaction types but could not fix it: the two networks assign different ordinals to the types they share, so a single merged definitions set is wrong for one side no matter which
way the merge resolves. MPTokenIssuanceCreate is 54 on the XRP Ledger and 63 on Xahau; of the 59 shared types only 36 line up.

This PR does not fix Xahau — it makes fixing it possible from outside:

$definitions = Definitions::fromFile('xahau-definitions.json');

$codec  = new BinaryCodec($definitions);
$wallet = Wallet::fromSeed($seed, $definitions);
$client = new JsonRpcClient($url, null, null, 3.0, $definitions);

Verified against the live Xahau node's own server_definitions: the same transaction encodes to ordinal 54 with the bundled definitions and 63 with Xahau's, and both signatures verify.

Why not a Network enum

Because it would put a second network's concept into the public API of a library that is otherwise entirely about the XRP Ledger — Wallet::fromSeed() would grow a network parameter that most callers never touch. Handing in a Definitions instance keeps the seam internal and works for any network, not just Xahau. When the Xahau types eventually leave this library, nothing in the API has to change back.

Scope

Smaller than it first looked. Only two serialized types resolve field names, so only those two needed a parameter:

Touched Untouched
Definitions, BinaryParser, Binary/BinaryCodec, StObject, StArray, Wallet, JsonRpcClient, HashLedger, two Sugar helpers The other 27 serialized types — Amount, Blob, AccountId, all Hash*/UInt*, Issue, PathSet, Vector256, Number ...

BinaryParser carries the definitions through the decode, so fromParser() needed no signature change anywhere. StObject and StArray keep them on the parsed instance so that toJson() resolves names against the same set.

No breaking changes. Every new parameter is optional and falls back to the bundled XRP Ledger definitions.

Fixed along the way

  • Wallet::sign() hashed through the wrong definitions. It encoded against the wallet's set but handed the blob to HashLedger, which used the default one. Hashing decodes the blob to check a signature is present, and decoding resolves every field — so a transaction with a field only the injected definitions know threw inside sign().
  • HashLedger::hashSignedTx() can return a silently wrong hash. Given an array it encodes the blob that then gets hashed, so the definitions decide the result. The string path is unaffected, since there the hash comes from the input blob.
  • Sugar\getLastLedgerSequence() and Sugar\isAccountDelete() decode a whole blob to read one field. My first assessment called this harmless because those ordinals match across networks — that misses that the decode has to resolve every other field first. Both now take the definitions too.

Tests

11 new tests in InjectableDefinitionsTest, covering encode, decode, nested objects, wallet signing, hashing, and that an injected set does not leak into the shared default instance.

The alternative definitions are built by remapping ordinals in the bundled set rather than checking in a second large fixture — that reproduces exactly what makes the networks incompatible, without a network dependency in the suite.

One note on test quality: the first version of the hashing test compared two hashes over the string path, where the hash is definitions-independent by construction. It would have passed without the fix. It is replaced by one that uses a field only the injected definitions know, and I verified it fails at Wallet.php:152 → HashLedger.php:50 when the fix is reverted.

550 tests green.

Not covered

  • The bundled definitions still merge the Xahau ones, so 2.x behaves as before for anyone not injecting their own set. The Xahau types leave in 3.0.0, once the separate package exists.
  • HashLedger remains a singleton; hashSignedTx() builds a codec on demand when definitions are passed rather than restructuring it. Untangling the singleton belongs with the wider cleanup.

AlexanderBuzz and others added 2 commits August 24, 2026 20:17
The 2.0.0 entry stated that the lock file had been stale since the buffer
bump and that a fresh `composer install` therefore failed. composer.lock is
gitignored in this repository, so no consumer and no fresh clone ever saw
that lock - it was an artifact of one local working copy, and
`composer require hardcastle/xrpl_php` resolves from composer.json as usual.

What does stand is the reason for the guzzle bump: the constraint `^7.4`
allowed 7.4.0 through 7.15.1, all of which carry open advisories, so anyone
resolving the tree could land on a vulnerable version. The Security entry is
reworded accordingly.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
- Definitions::fromArray() and Definitions::fromFile() build a set from
  outside; the constructor takes the decoded definitions and validates that
  all five sections are present
- BinaryCodec, BinaryParser, Wallet, JsonRpcClient, HashLedger::hashSignedTx(),
  Sugar\getLastLedgerSequence() and Sugar\isAccountDelete() take an optional
  Definitions instance
- BinaryParser carries the definitions through the decode; StObject and StArray
  keep them on the parsed instance so toJson() uses the same set
- StObject::fromJson() and StArray::fromJson() take an optional Definitions and
  pass it into nested objects and arrays
- Wallet::sign() hashes through the wallet's own definitions instead of the
  default ones
- The Sugar functions build their codec from the client's definitions
- README: section "Using your own definitions"
- 11 tests in InjectableDefinitionsTest

All parameters are optional and default to the bundled XRP Ledger definitions.
@AlexanderBuzz
AlexanderBuzz merged commit 1777218 into master Aug 24, 2026
3 checks passed
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