Tickets
XRPL enforces a strict per-account Sequence number on every transaction (the same role an EVM nonce plays). For the multisig account that backs the bridge, this would normally mean only one transaction can be in flight at a time, and confirmations would have to land strictly in order. To get around that, the XRPL Multisig Prover uses tickets: pre-allocated sequence numbers that the multisig account reserves in advance, drawn from a pool of up to 250.
Tickets let many bridge transactions be signed and submitted in parallel, and let them confirm out of order. Operations that fundamentally have to be serial (pool refill, verifier set rotation, trust line management) still use a plain sequence number.
| Transaction type | Sequence field | Why |
|---|---|---|
Payment | Ticket | Many in flight at once; can confirm out of order |
TicketCreate | Plain sequence | Refills the ticket pool; must be strictly ordered |
SignerListSet | Plain sequence | Verifier set rotation; one at a time |
TrustSet | Plain sequence | One trust line at a time |
Ticket assignment
At any point a set of available tickets is tracked by the prover: ticket numbers that have been created with a TicketCreate transaction but that are not known to have been consumed by a transaction that made it to the XRPL ledger. New outbound transactions get assigned available tickets in order until the pool is exhausted.
If the number of available tickets falls below a configurable threshold, the prover constructs a new TicketCreate transaction (see Ticket creation flow below).
Ticket reuse under contention
If transactions are produced faster than the ticket pool can be refilled, ticket assignment wraps around to the first available ticket (similar to a round-robin scheduler). This can lead to multiple in-flight transactions being assigned the same ticket number:
tx8
This is safe because of how XRPL handles ticket consumption: only one of the transactions sharing a ticket will ultimately be included in the ledger. Once that happens, the ticket is consumed permanently by that single transaction; every other transaction that tried to use the same ticket will be rejected by the ledger.
Ticket creation flow
XRPL limits the number of available tickets at any given time to 250. When the size of the prover's ticket pool drops below a configurable threshold, a new TicketCreate transaction must be submitted to top it back up.
The flow:
- A
Paymenttransaction is confirmed on the XRPL ledger (and observed on Axelar through the standardProverMessageverification path), which reduces the number of available tickets below the creation threshold. - The relayer requests a new
TicketCreatetransaction from the XRPL Multisig Prover. - The prover serializes a
TicketCreatethat asks the ledger to create250 - len(available_tickets)new tickets. There may actually be fewer usable tickets on XRPL than the prover currently knows about (in-flight transactions that have not been confirmed yet on Axelar), but there can never be more, so this bound is safe. - Axelar verifiers sign the new
TicketCreatetransaction through the standard multi-sign session. - The relayer submits the signed transaction to XRPL.
- Once the transaction is included in a validated ledger, the relayer reports the inclusion back to Axelar as a
ProverMessage. - Axelar verifiers vote on whether the XRPL transaction has been finalized.
- If the poll succeeds, the newly created tickets become available to be assigned to subsequent
Paymenttransactions.
Fee reserve
In addition to the ticket pool, the prover tracks a FEE_RESERVE counter (in XRP drops) that represents the multisig account's available XRP for paying transaction fees. Every new transaction the prover builds is gated by ensure_sufficient_fee_reserve, which checks the budget against:
xrpl_base_reserve + xrpl_owner_reserve * (251 + trust_line_count) + tx_fee
The + 251 term accounts for the maximum 250 tickets plus the multisig account's own SignerList, each of which counts as an "owned object" on XRPL and contributes to the reserve requirement. The reserve is topped up via ConfirmAddReservesMessage after the XRPL Voting Verifier confirms an operator-initiated XRP top-up AddReservesMessage.