$$ \newcommand \Hash {\mathrm{Hash}} \newcommand \MaxTxGroupSize {GT_{\max}} \newcommand \MinTxnFee {T_{\Fee,\min}} \newcommand \BytesPerBoxReference {\Box_{\mathrm{IO}}} \newcommand \LogicSigMaxSize {\LogicSig_{\max}} $$
Transaction Groups
A transaction MAY include a group field (msgpack codec grp
), a 32-byte hash
that specifies what transaction group the transaction belongs to.
Informally, a transaction group is an ordered list of transactions that MUST all be confirmed together, in the specified order, and included in the same block. If any transaction in the group fails to be confirmed, none of them will be.
The group field, in each transaction part of the same group, is set to the hash representing a commitment to the entire group. This group hash is computed by creating an ordered list of the hashes of all transactions in the group. When computing each transaction’s hash for this purpose, its own group field is omitted to avoid circular dependency.
📎 EXAMPLE
A user wants to require transaction \( A \) to confirm if and only if transactions \( B \) and \( C \) confirm in a certain order. The user performs the following procedure:
Specifies transactions’ order: \( [A, B, C] \);
Computes the hashes of each transaction in the list (without their group field set): \( [\Hash(A), \Hash(B), \Hash(C)] \);
Hash them together in the specified order, getting the group hash: \( G = \Hash([\Hash(A), \Hash(B), \Hash(C)]) \);
Set the group field of all the transactions to the group hash (\( G \)) before signing them.
A group MAY contain no more than \( \MaxTxGroupSize \) transactions.
More formally, when evaluating a block, the \( i \)-th and \( i+1 \)-th transactions in the payset are considered to belong to the same transaction group if the group fields of the two transactions are equal and non-zero.
The block may now be viewed as an ordered sequence of transaction groups, where each transaction group is a contiguous sublist of the payset consisting of one or more transactions with equal group field.
For each transaction group where the transactions have non-zero group, compute the group hash as follows:
-
Take the hash of each transaction in the group, but with its group field omitted.
-
Hash this ordered list of hashes. More precisely, hash the canonical msgpack encoding of a structure with a field
txlist
containing the list of hashes, usingTG
as domain separation prefix.
If the group hash of any transaction group in a block does not match the group field of the transactions in that group (and that group field is non-zero), then the block is invalid.
Additionally, if a block contains a transaction group of more than \( \MaxTxGroupSize \) transactions, the block is invalid.
If the sum of the fees paid by the \( n \) transactions in a transaction group is less than \( n \times \MinTxnFee )\, then the block is invalid. There are two exceptions to this fee requirement:
-
State Proof transactions require no fee;
-
Heartbeat transactions require no fee if they have a zero group field, and the heartbeat address was challenged between \( 100 \) and \( 200 \) rounds ago, and has not proposed or heartbeat since that challenge.
Further explanation of this rule is found in Heartbeat transaction semantics section.
If the sum of the lengths of the boxes denoted by the box references in a transaction group exceeds \( \BytesPerBoxReference \) times the total number of box references in the transaction group, then the block is invalid. Call this limit the I/O Budget for the group. Box references with an empty name are counted toward the total number of references, but add nothing to the sum of lengths.
If the sum of the lengths of the boxes modified (by creation or modification) in a transaction group exceeds the I/O Budget of the group at any time during evaluation (see Application Call transaction semantics), then the block is invalid.
If the sum of the lengths of all the logic signatures and their arguments in a transaction group exceeds the number of transactions in the group times \( \LogicSigMaxSize \), then the block in invalid.
Beyond the group field, group minimum fee, group I/O Budget, and group logic sig size checks, each transaction in a group is evaluated separately and MUST be valid on its own, as described in the Validity and State Changes section.
📎 EXAMPLE
An account with balance \( 50 \) ALGO could not spend \( 100 \) ALGO in transaction \( A \) and afterward receive \( 500 \) in transaction \( B \), even if transactions \( A \) and \( B \) are in the same group, because transaction \( A \) would overspend the account’s balance.