Skip to content

v11.6.0

Choose a tag to compare

@github-actions github-actions released this 21 Sep 20:06
11cc4d4
  • The protocol schema follows rippled develop at e3c8996e, the 3.4.0-rc1 build the nightly stand is pinned to (#182 bumps the pin). definitions.json had been synced for 3.3.0 and was eight fields behind develop, which definitions-watch had reported as node-only for three weeks. The nightly-pin bump that would have listed them opened with an empty "definitions.json vs the new build" section: the step inherits bash -e from the runner, and the diff exits 1 whenever it finds drift, so errexit ended the step at the assignment - before the report was echoed or recorded - in the one case the step exists for. Fixed alongside.

    • closed-ended vaults (rippled #7921, LendingProtocolV1_1): VaultCreate and LOVault carry VaultKind, SubscriptionDate and RedemptionDate, and the VaultKind enum names the two kinds. ValidateVaultCreate pins rippled's preflight: the dates only on a closed-ended vault, both of them, with the redemption at least three minutes and less than thirty years after the subscription (rippled #8151 raised the floor from one minute; caught by running the closed-ended flow on the nightly stand). Deposits are accepted in the subscription phase only, withdrawals in every phase but investment
    • confidential MPT key rotation (rippled #7915, ConfidentialMPTKeyRotation): LOMPTokenIssuance carries IssuerKeyEpoch and AuditorKeyEpoch, incremented each time MPTokenIssuanceSet replaces the key. The transaction is unchanged - the same IssuerEncryptionKey/AuditorEncryptionKey fields rotate a key once the amendment is active, and the current key is refused with tecDUPLICATE. LOMPToken carries the holder side, IssuerKeyMirrorEpoch and AuditorKeyMirrorEpoch: the epoch each mirrored encrypted balance was produced under, which rippled compares against the issuance's epoch to decide whether the mirror is still current, so a rotation marks it stale. ContractResult (rippled #7988) is known to the codec but belongs to no format yet
    • the vendored ledger_entries.macro moves to develop f6b51f0b, the commit that placed the mirror epochs on MPToken. TestULedgerEntryFieldsConformance reads that file in both directions, so moving the pin also named the two Smart Escrow entries it carries, and the models follow them: LOEscrow gains Bytecode and Data, LOFeeSettings the voted GasLimit, BytecodeSizeLimit and GasPrice. Ledger-object fields only - the SmartEscrow amendment is Supported::No on every build, so nothing returns them yet and the transaction side stays out of this release
    • VaultWithdraw and LoanBrokerCoverWithdraw accept CredentialIDs, for a Destination that requires deposit authorization; validated the way Payment.CredentialIDs is
    • a protocol field is a member on the transaction's interface as well as on its classes, so IVaultCreate, IVaultWithdraw and ILoanBrokerCoverWithdraw each gained one. Anything outside the SDK that implements one of those interfaces - an adapter, a test double - stops compiling until it declares the new member. No default bodies: on a data contract a default would have to accept a value and drop it, which is the silent outcome these interfaces exist to avoid, and unlike IXrplClient nothing implements them to add behaviour
    • the vendored transactions.macro is pinned to the same develop commit as ledger_entries.macro instead of the 3.3.0 tag, so both conformance tests describe the build the nightly stand runs. Up to 3.3.0 the tag and develop agreed on transaction fields; they no longer do
    • Xrpl.BinaryCodec 11.6.0.0 for the new codec entries, numbered with Xrpl since both move in this release. The CI stand (3.3.0) knows none of the new fields, so the unit suite covers them with round trips and validation, and TestIClosedEndedVault drives them against the nightly stand (LendingProtocolV1_1 at genesis, the pin from #182): a closed-ended vault through its three phases, an open-ended one carrying no VaultKind on the ledger, and a VaultWithdraw to a deposit-authorized destination that is tecNO_PERMISSION without CredentialIDs and succeeds with them. Key rotation has no stand: ConfidentialMPTKeyRotation is Supported::No, and the shared amendment generator cannot preset a name the 3.3.0 binary does not know
    • the Loan integration suite follows the amendment too. Under LendingProtocolV1_1 LoanBrokerSet refuses an open-ended vault ("LoanBroker requires a closed-ended Vault", tecNO_PERMISSION) and every Loan test built its broker on one, so all 18 of TestILoan failed on the nightly stand - identically on untouched dev, which is what said it was the node's rule rather than a regression. TestILoanBase now creates a closed-ended vault where the node asks for one and waits for the investment phase before handing the broker back: rippled originates a loan only there, while the vault deposit that funds it is taken only in the subscription phase before it, and the two dates are measured from the ledger's close time rather than the machine's clock, which on a standalone stand is a different clock. A node without the amendment does not know the fields at all - it answers invalidTransaction, not a result code - so the open-ended path stays for it, chosen through AmendmentGuard
    • what that unblocks, and what it does not: on the nightly stand TestILoan goes from 0 of 18 to 7 of 18, and all 11 that still failed reported Counterparty: Invalid signature - the role signing prefixes fixCleanup3_4_0 introduces, which is what the entry above this one goes on to implement, and which was the whole of what remained. TestISponsoredVaultLoan is blocked by the same thing on 3.4.x, at Sponsor: Invalid signature. Neither failure was about vaults any more, which is what this entry set out to establish; the signatures are the subject of the entry above, and are green there. The CI stand (3.3.0) is untouched by any of it; what the suite looks like there once the signing change lands is counted in the entry above
    • ValidatedCloseTimeAsync and WaitForCloseTimeAsync moved to IntegrationTestConfig: three test classes now need the ledger clock, and each had been carrying its own copy
  • A sponsor's and a counterparty's signature cover bytes of their own (rippled fixCleanup3_4_0, breaking against nodes without the amendment). Until it, every signature on a transaction covered the same bytes: the submitter's TxnSignature, the sponsor's SponsorSignature (XLS-68) and the borrower's CounterpartySignature (XLS-66) were all made over one preimage, so a signature could be lifted out of one role and pasted into another and still verify. rippled now gives each role its own four-byte hash prefix, and this release signs that way.

    • HashPrefix gains CounterpartyTransactionSig, CounterpartyTransactionMultiSig, SponsorTransactionSig and SponsorTransactionMultiSig, and EncodeForSigning / EncodeForMultiSigning gain overloads taking one. Overloads rather than an optional parameter, for the binary compatibility reason the SDK has met before. The transaction's own prefixes are untouched, so an ordinary signature - single or multisig, Batch included - is byte-for-byte what it was
    • the role is not something a caller states. It follows from the method: a wallet named as the Sponsor signs as sponsor, a LoanSet Counterparty as counterparty, and a multi-signature entry on a transaction whose main signature is single can only belong to the co-signing side. One shape is genuinely ambiguous, where the main signature and a co-signature are both multi-signed, and only there does the signer have to say: Sign(tx, multisign, signingFor, SignatureRole.Sponsor). Asking for it in a shape that does not have it is refused rather than signed wrongly
    • multi-signature entries are no longer portable between sections. The composer's premise - that tx.Signers, SponsorSignature.Signers and CounterpartySignature.Signers are identical bytes, so routing could be settled at composition time - held only before the amendment. Routing still happens in the composer, by account, but the signer now has to know its side already
    • what breaks: a signature this release makes is rejected by a node that has Sponsor or LendingProtocol enabled but not fixCleanup3_4_0. No public network is in that state - on mainnet and testnet none of the three is enabled, on devnet all of them are - so the affected combination is a private node on a release older than the amendment. The older scheme is not carried, and nothing asks the node which one it wants: signing stays offline
    • the one place the combination does occur is this repository's own CI stand, a 3.3.0 image with Sponsor and LendingProtocol voted in at genesis, so the integration tests that produce a role signature now skip there through AmendmentGuard and run on the nightly stand instead. Sixty of them, measured: the CI stand ran 346 integration tests before this release and runs 289, with 60 skipped. The guard sits on the tests that actually make a role signature, not on their classes - the SponsorshipSet tests carry none and keep running there. It is coverage deferred rather than lost, on a stand rather than in the suite, and the guard turns it back on by itself once the CI stand moves to a release carrying the amendment
    • the composer now checks what it composes. Routing an entry by account is a guess about what its signer meant, and since the amendment a wrong guess is no longer harmless. ComposeSignatures verifies every signature in the finished transaction against the bytes that transaction ships, under the prefix of the section the signature landed in, and names the account and the section when one does not verify. It catches the shape the transaction cannot express - the main signature multi-signed as well, so an entry could belong to either side - and the other direction too, a part signed over a SigningPubKey the composed transaction does not carry. Both were found by a cold review of this branch, on two models independently, and both used to reach the node as a transaction the caller believed was signed
    • SponsorSigningHelper.GetSigningPreimage is now GetSponsorPreimage, and the internal loan one GetCounterpartyPreimage. The name returned the bytes of both signatures while they were the same; keeping it would have changed what a call means without changing how it compiles. No [Obsolete] bridge, the same policy the breaks above it follow: a member that refuses is still a member on the public surface, and the compile error a removal gives is the migration notice
    • pinned by unit tests that read the prefixes out of rippled's own HashPrefix.h, vendored as a fixture beside the other protocol files, and assert that a role preimage is the transaction's preimage with four bytes changed and nothing else - a pinned blob cannot answer that question, since regenerating it from the same code only agrees with itself. What settles it is the node: on the nightly stand TestILoan passes 18 of 18 and the sponsorship classes are green, where before this release every one of them was refused with Invalid signature
    • two rules of the same amendment surfaced once the tests could reach them, and are in the tests rather than in the SDK: a loan may only be impaired once a payment is actually late, and a payment on an overdue loan must carry tfLoanLatePayment or it is tecEXPIRED