-
Notifications
You must be signed in to change notification settings - Fork 575
feat: Support BatchV1_1 #3371
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?
feat: Support BatchV1_1 #3371
Changes from 6 commits
a0a7bb1
f5ff13a
317072b
a0b63d5
4d6054e
dfb978a
e0680e6
ad7f86b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,6 +4,9 @@ Subscribe to [the **xrpl-announce** mailing list](https://groups.google.com/g/xr | |
|
|
||
| ## Unreleased | ||
|
|
||
| ### Changed | ||
| * Add XLS-56 Batch V1_1 support to `signMultiBatch` and `combineBatchSigners` ([XRPLF/rippled#6446](https://github.com/XRPLF/rippled/pull/6446)). | ||
|
Collaborator
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. nit: A |
||
|
|
||
| ## 5.0.0 (2026-06-05) | ||
|
|
||
| ### BREAKING CHANGES: | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -45,6 +45,21 @@ function constructBatchSignerObject( | |
| return batchSigner | ||
| } | ||
|
|
||
| /** | ||
| * Resolve the sequence value bound into a Batch signature: the `Sequence` when | ||
| * non-zero, otherwise the `TicketSequence` value (or 0). | ||
| * | ||
| * @param transaction - The Batch transaction being signed. | ||
| * @returns The sequence value to bind into the signature. | ||
| */ | ||
| function getBatchSeqValue(transaction: Batch): number { | ||
| const sequence = transaction.Sequence ?? 0 | ||
| if (sequence !== 0) { | ||
| return sequence | ||
| } | ||
| return transaction.TicketSequence ?? 0 | ||
| } | ||
|
|
||
| /** | ||
| * Sign a multi-account Batch transaction. | ||
| * | ||
|
|
@@ -56,6 +71,7 @@ function constructBatchSignerObject( | |
| * The actual address is only needed in the case of regular key usage. | ||
| * @throws ValidationError if the transaction is malformed. | ||
| */ | ||
| // eslint-disable-next-line max-lines-per-function -- cohesive signing routine | ||
| export function signMultiBatch( | ||
| wallet: Wallet, | ||
| transaction: Batch, | ||
|
|
@@ -79,19 +95,33 @@ export function signMultiBatch( | |
| // eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- validate does not accept Transaction type | ||
| validate(transaction as unknown as Record<string, unknown>) | ||
|
|
||
| const involvedAccounts = new Set( | ||
| transaction.RawTransactions.map((raw) => raw.RawTransaction.Account), | ||
| ) | ||
| // An account must sign the Batch if it submits an inner transaction or is the | ||
| // `Counterparty` of one. | ||
| const involvedAccounts = new Set<string>() | ||
| transaction.RawTransactions.forEach((raw) => { | ||
| involvedAccounts.add(raw.RawTransaction.Account) | ||
|
Collaborator
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. This format does not account for potential Delegate of the inner transaction. Please refer to line 427 in this file: https://github.com/XRPLF/rippled/pull/6446/changes#diff-a9cdff3331a64b75a44d24094b4699fd27c8e4fdc52537eb97f881ce8b28c2db
|
||
| // eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- Counterparty only exists on some inner tx types | ||
| const counterparty = (raw.RawTransaction as Record<string, unknown>) | ||
| .Counterparty | ||
| if (typeof counterparty === 'string') { | ||
| involvedAccounts.add(counterparty) | ||
| } | ||
| }) | ||
| if (!involvedAccounts.has(batchAccount)) { | ||
| throw new ValidationError( | ||
| 'Must be signing for an address submitting a transaction in the Batch.', | ||
| ) | ||
| } | ||
| const fieldsToSign = { | ||
| account: transaction.Account, | ||
| sequence: getBatchSeqValue(transaction), | ||
| flags: transaction.Flags, | ||
| txIDs: transaction.RawTransactions.map((rawTx) => | ||
| hashSignedTx(rawTx.RawTransaction), | ||
| ), | ||
| batchAccount, | ||
| // Multi-signed batch signers also bind the inner signer account. | ||
| ...(multisignAddress ? { signerAccount: multisignAddress } : {}), | ||
| } | ||
| const signature = sign(encodeForSigningBatch(fieldsToSign), wallet.privateKey) | ||
|
|
||
|
|
@@ -186,13 +216,28 @@ function validateBatchTransactionEquivalence(transactions: Batch[]): void { | |
| } | ||
|
|
||
| function getTransactionWithAllBatchSigners(transactions: Batch[]): Batch { | ||
| const outerAccount = transactions[0].Account | ||
|
|
||
| // Signers must be sorted in the combined transaction - See compareSigners' documentation for more details | ||
| const sortedSigners: BatchSigner[] = transactions | ||
| .flatMap((tx) => tx.BatchSigners ?? []) | ||
| .filter((signer) => signer.BatchSigner.Account !== transactions[0].Account) | ||
| // A batch signer cannot be the outer account (rippled: temBAD_SIGNER). | ||
| .filter((signer) => signer.BatchSigner.Account !== outerAccount) | ||
|
depthfirst-app[bot] marked this conversation as resolved.
|
||
| .sort((signer1, signer2) => | ||
| compareSigners(signer1.BatchSigner, signer2.BatchSigner), | ||
| ) | ||
|
|
||
| return { ...transactions[0], BatchSigners: sortedSigners } | ||
| // BatchSigners must be strictly ascending and unique by account, so | ||
| // de-duplicate when combining fragments that share a signer. | ||
| const dedupedSigners: BatchSigner[] = [] | ||
| let lastAccount = '' | ||
| for (const signer of sortedSigners) { | ||
| const account = signer.BatchSigner.Account | ||
| if (account !== lastAccount) { | ||
| dedupedSigners.push(signer) | ||
| lastAccount = account | ||
| } | ||
| } | ||
|
|
||
| return { ...transactions[0], BatchSigners: dedupedSigners } | ||
| } | ||
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.
My understanding was that beta releases have a suffix of the form:
2.9.0-beta-batch-1.Are we sure this released is not interpreted as a "General Availability" release by the community? @pdp2121
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.
Other feature beta/experimental releases are following the same pattern, for example:
https://github.com/XRPLF/xrpl.js/releases/tag/xrpl%404.7.0-smartcontract.0