Skip to content

Commit 9625d0f

Browse files
authored
Merge branch 'master' into 68v2
2 parents e52ad03 + a1b05ef commit 9625d0f

File tree

1 file changed

+118
-47
lines changed

1 file changed

+118
-47
lines changed

XLS-0056-batch/README.md

Lines changed: 118 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
status: Final
88
category: Amendment
99
created: 2023-12-13
10+
updated: 2026-02-10
1011
</pre>
1112

1213
# Atomic/Batch Transactions
@@ -133,7 +134,50 @@ In other words, the fee is twice the base fee (a total of 20 drops when there is
133134

134135
The fees for the individual inner transactions are paid here instead of in the inner transaction itself, to ensure that fee escalation is calculated on the total cost of the transaction instead of just the overhead.
135136

136-
### 2.3. Metadata
137+
### 2.3. Failure Conditions
138+
139+
The standard transaction failure conditions still apply here.
140+
141+
1. The `Flags` field is not set to exactly one of the supported batch modes (`temINVALID_FLAG`).
142+
1. Inner transactions
143+
1. There are fewer than 2 transactions in the `RawTransactions` field (`temARRAY_EMPTY`).
144+
2. There are more than 8 transactions in the `RawTransactions` field (`temARRAY_TOO_LARGE`).
145+
3. The `RawTransactions` field contains a transaction that is not a valid transaction.
146+
4. One of the inner transactions has a `Fee` greater than 0 (`temBAD_FEE`).
147+
5. One of the inner transactions has a `TxnSignature` field included (`temBAD_SIGNATURE`).
148+
6. One of the inner transactions has a non-empty `SigningPubKey` (`temBAD_REGKEY`).
149+
7. One of the inner transactions is has a `Signers` field included (`temBAD_SIGNER`).
150+
8. One of the inner transactions has `TransactionType` of `Batch` (`temINVALID`).
151+
9. One of the inner transactions has a different invalid `TransactionType` (`temINVALID_INNER_BATCH`).
152+
10. There is a duplicate transaction in the `RawTransactions` field (`temREDUNDANT`).
153+
11. One of the inner transactions does not have the `tfInnerBatchTxn` flag set (`temINVALID_FLAG`).
154+
12. One of the inner transactions fails its preflight checks (i.e. is invalid, irrespective of ledger state) (`temINVALID_INNER_BATCH`).
155+
13. Either both or neither of `TicketSequence` and `Sequence` are set (`temSEQ_AND_TICKET`).
156+
1. `BatchSigners`
157+
1. The length of `BatchSigners` is greater than the number of transactions in `RawTransactions` (`temARRAY_TOO_LARGE`).
158+
2. The `BatchSigners` field contains a signature from the account signing the outer transaction (`temBAD_SIGNER`).
159+
3. The `BatchSigners` field contains a duplicate signature (`temREDUNDANT`).
160+
4. The `BatchSigners` field contains a signature from an account that does not have any inner transactions (`temBAD_SIGNER`).
161+
5. The `BatchSigners` field is missing a signature from an account that has inner transactions (`temBAD_SIGNER`).
162+
6. The `BatchSigners` field contains an invalid signature (`temBAD_SIGNATURE`).
163+
1. Preclaim/doApply errors
164+
1. The public key for a signer is not a valid public key (`tefBAD_AUTH`). (This should be caught by preflight checks, but it is an additional backup check just in case).
165+
2. The batch signer is single-signing:
166+
1. The public key for a signer is not valid for the account ('`tefBAD_AUTH`).
167+
2. The account is signing with the account's master key, but the master key is disabled (`tefMASTER_DISABLED`).
168+
3. The batch signer is multi-signing:
169+
1. The account does not have a signer list (`tefNOT_MULTI_SIGNING`).
170+
2. The signing account is not a signer on the signer list (`tefBAD_SIGNATURE`).
171+
3. The `SigningPubkey` field in a `SignerEntry` field is empty or not a valid public key (`tefBAD_SIGNATURE`).
172+
4. The signing account is signing with the account's master key, but the master key is disabled (`tefMASTER_DISABLED`).
173+
5. The `SigningPubKey` field is not the `Account`'s master or regular key (`tefBAD_SIGNATURE`).
174+
6. There is not enough signing weight to meet the `SignerQuorum` (`tefBAD_QUORUM`).
175+
176+
### 2.4. State Changes
177+
178+
The state changes for the outer transaction are the same as for a normal transaction. The state changes for the inner transactions are the same as if they were submitted as normal transactions.
179+
180+
### 2.5. Metadata
137181

138182
The inner transactions will be committed separately to the ledger and will therefore have separate metadata. This is to ensure better backwards compatibility for legacy systems, so they can support `Batch` transactions without needing any changes to their systems.
139183

@@ -147,60 +191,23 @@ For example, a ledger that only has one `Batch` transaction containing 2 inner t
147191
]
148192
```
149193

150-
#### 2.6.1. Outer Transactions
194+
#### 2.5.1. Outer Transactions
151195

152196
Each outer transaction will only contain the metadata for its sequence and fee processing, not for the inner transaction processing. The error code will also only be based on the outer transaction processing (e.g. sequence and fee), and it will return a `tesSUCCESS` error even if the inner transaction processing fails.
153197

154-
#### 2.6.2. Inner Transactions
198+
#### 2.5.2. Inner Transactions
155199

156200
Each inner transaction will contain the metadata for its own processing. Only the inner transactions that were actually committed to the ledger will be included. This makes it easier for legacy systems to still be able to process `Batch` transactions as if they were normal.
157201

158202
There will also be a pointer back to the parent outer transaction (`ParentBatchID`).
159203

160-
## 3. Transaction Common Fields
161-
162-
This standard doesn't add any new field to the [transaction common fields](https://xrpl.org/docs/references/protocol/transactions/common-fields/), but it does add another global transaction flag:
163-
164-
| Flag Name | Value |
165-
| ----------------- | ------------ |
166-
| `tfInnerBatchTxn` | `0x40000000` |
167-
168-
This flag should only be used if a transaction is an inner transaction in a `Batch` transaction. This signifies that the transaction shouldn't be signed. Any normal transaction that includes this flag should be rejected.
169-
170-
## 4. Security
171-
172-
### 4.1. Trust Assumptions
173-
174-
Regardless of how many accounts' transactions are included in a `Batch` transaction, all accounts need to sign the collection of transactions.
175-
176-
#### 4.1.1. Single Account
177-
178-
In the single account case, this is obvious; the single account must approve all of the transactions it is submitting. No other accounts are involved, so this is a pretty straightforward case.
179-
180-
#### 4.1.2. Multi Account
181-
182-
The multi-account case is a bit more complicated and is best illustrated with an example. Let's say Alice and Bob are conducting a trustless swap via a multi-account `Batch`, with Alice providing 1000 XRP and Bob providing 1000 USD. Bob is going to submit the `Batch` transaction, so Alice must provide her part of the swap to him.
204+
### 2.6. Example JSONs
183205

184-
If Alice provides a fully autofilled and signed transaction to Bob, Bob could submit Alice's transaction on the ledger without submitting his and receive the 1000 XRP without losing his 1000 USD. Therefore, the inner transactions must be unsigned.
185-
186-
If Alice just signs her part of the `Batch` transaction, Bob could modify his transaction to only provide 1 USD instead, thereby getting his 1000 XRP at a much cheaper rate. Therefore, the entire `Batch` transaction (and all its inner transactions) must be signed by all parties.
187-
188-
### 4.2. Inner Transaction Safety
189-
190-
An inner batch transaction is a very special case. It doesn't include a signature or a fee (since those are both included in the outer transaction). Therefore, they must be handled very carefully to ensure that someone can't somehow directly submit an inner `Batch` transaction without it being included in an outer transaction.
191-
192-
Namely:
193-
194-
- Inner transactions may not be broadcast (and won't be accepted if they happen to be broadcast, e.g. from a malicious node). They must be generated from the `Batch` outer transaction instead.
195-
- Inner transactions may not be directly submitted via the `submit` RPC.
196-
197-
## 5. Examples
198-
199-
### 5.1. One Account
206+
#### 2.6.1. One Account
200207

201208
In this example, the user is creating an offer while trading on a DEX UI, and the second transaction is a platform fee.
202209

203-
#### 5.1.1. Sample Transaction
210+
##### 2.6.1.1. Sample Transaction
204211

205212
<details open>
206213
<summary>
@@ -253,7 +260,7 @@ The inner transactions are not signed, and the `BatchSigners` field is not neede
253260

254261
</details>
255262

256-
#### 5.1.2. Sample Ledger
263+
##### 2.6.1.2. Sample Ledger
257264

258265
<details open>
259266
<summary>
@@ -335,11 +342,11 @@ Note that the inner transactions are committed as normal transactions.
335342

336343
</details>
337344

338-
### 5.2. Multiple Accounts
345+
#### 2.6.2. Multiple Accounts
339346

340347
In this example, two users are atomically swapping their tokens, XRP for GKO.
341348

342-
#### 5.2.1. Sample Transaction
349+
##### 2.6.2.1. Sample Transaction
343350

344351
<details open>
345352
<summary>
@@ -401,7 +408,7 @@ The inner transactions are still not signed, but the `BatchSigners` field is nee
401408

402409
</details>
403410

404-
#### 5.2.2. Sample Ledger
411+
##### 2.6.2.2. Sample Ledger
405412

406413
<details open>
407414
<summary>
@@ -494,6 +501,70 @@ Note that the inner transactions are committed as normal transactions.
494501

495502
</details>
496503

504+
## 3. Transaction Common Fields
505+
506+
This standard doesn't add any new field to the [transaction common fields](https://xrpl.org/docs/references/protocol/transactions/common-fields/), but it does add another global transaction flag:
507+
508+
| Flag Name | Value |
509+
| ----------------- | ------------ |
510+
| `tfInnerBatchTxn` | `0x40000000` |
511+
512+
This flag should only be used if a transaction is an inner transaction in a `Batch` transaction. This signifies that the transaction shouldn't be signed. Any normal transaction that includes this flag should be rejected.
513+
514+
## 4. Rationale
515+
516+
The design of batch transactions prioritizes flexibility, security, and backward compatibility with the existing XRP Ledger infrastructure.
517+
518+
### 4.1. Multiple Batch Modes
519+
520+
Four distinct batch modes (`ALLORNOTHING`, `ONLYONE`, `UNTILFAILURE`, `INDEPENDENT`) were chosen to accommodate a wide range of use cases:
521+
522+
- **`ALLORNOTHING`** is essential for trustless swaps and any scenario where partial completion would leave the system in an undesirable state.
523+
- **`ONLYONE`** enables try-multiple-options patterns, such as submitting offers with different slippage tolerances.
524+
- **`UNTILFAILURE`** provides a middle ground for sequential operations that can partially succeed.
525+
- **`INDEPENDENT`** allows for transaction bundling without strict interdependency.
526+
527+
Alternatives considered included a simpler single-mode design, but this would have forced users to work around limitations for their specific use cases.
528+
529+
### 4.2. Separate Metadata for Inner Transactions
530+
531+
Inner transactions are committed separately to the ledger with their own metadata rather than being embedded within the outer transaction's metadata. This design choice ensures backward compatibility with legacy systems that can continue processing transactions without understanding or adding special support for the `Batch` transaction type. A more compact design with nested metadata was considered but rejected due to the extensive changes it would require for existing infrastructure.
532+
533+
### 4.3. Transaction Limits
534+
535+
The current limit of 8 inner transactions and a minimum of 2 was chosen to balance utility against potential abuse vectors and performance concerns. This limit can be relaxed in future amendments as the community gains experience with how batch transactions are used in practice.
536+
537+
### 4.4. Inner Transaction Safety
538+
539+
Requiring the `tfInnerBatchTxn` flag, prohibiting signatures, and mandating zero fees on inner transactions creates a clear separation between inner and outer transactions. This prevents inner transactions from being extracted and submitted independently, which would bypass the atomicity guarantees and potentially enable theft in multi-account scenarios.
540+
541+
## 5. Security
542+
543+
### 5.1. Trust Assumptions
544+
545+
Regardless of how many accounts' transactions are included in a `Batch` transaction, all accounts need to sign the collection of transactions.
546+
547+
#### 5.1.1. Single Account
548+
549+
In the single account case, this is obvious; the single account must approve all of the transactions it is submitting. No other accounts are involved, so this is a pretty straightforward case.
550+
551+
#### 5.1.2. Multi Account
552+
553+
The multi-account case is a bit more complicated and is best illustrated with an example. Let's say Alice and Bob are conducting a trustless swap via a multi-account `Batch`, with Alice providing 1000 XRP and Bob providing 1000 USD. Bob is going to submit the `Batch` transaction, so Alice must provide her part of the swap to him.
554+
555+
If Alice provides a fully autofilled and signed transaction to Bob, Bob could submit Alice's transaction on the ledger without submitting his and receive the 1000 XRP without losing his 1000 USD. Therefore, the inner transactions must be unsigned.
556+
557+
If Alice just signs her part of the `Batch` transaction, Bob could modify his transaction to only provide 1 USD instead, thereby getting his 1000 XRP at a much cheaper rate. Therefore, the entire `Batch` transaction (and all its inner transactions) must be signed by all parties.
558+
559+
### 5.2. Inner Transaction Safety
560+
561+
An inner batch transaction is a very special case. It doesn't include a signature or a fee (since those are both included in the outer transaction). Therefore, they must be handled very carefully to ensure that someone can't somehow directly submit an inner `Batch` transaction without it being included in an outer transaction.
562+
563+
Namely:
564+
565+
- Inner transactions may not be broadcast (and won't be accepted if they happen to be broadcast, e.g. from a malicious node). They must be generated from the `Batch` outer transaction instead.
566+
- Inner transactions may not be directly submitted via the `submit` RPC.
567+
497568
# Appendix
498569

499570
## Appendix A: FAQ

0 commit comments

Comments
 (0)