# CKB Take-All-And-Then Lock Script
## Metadata
**Status**:: #x
**Zettel**:: #zettel/permanent
**Topic**:: [[♯ CKB Open Transaction]]
**Parent**:: [[♯ CKB Script]]
**Created**:: [[2022-10-01]]
**Published**:: [[2022-10-14]]
**URL**:: [nervosnetwork/ckb#3638](https://github.com/nervosnetwork/ckb/discussions/3638)
## Synopsis
When I have been analyzing the user stories of CKB Open Transaction, I often need a facility to ensure that there is only one payee in the transaction and he/she will take all the payments except the transaction fee for miners. The lock script Take-All-And-Then is my answer. Since I will refer to it many times, I write a post about it first for my convenience.
## Why We Need *Take-All-And-Then*
Partial signed transaction works because we can deduce how the final transaction looks like from the signed part. This leaves flexibility to construct the transaction without interactive re-signing.
For example, instead of signing a specific input cell, we can sign the cell lock script. Any cell with the same lock script is a valid candidate. If the lock script is the secp256k1-blake2b lock owned by Alice, we know that in the final transaction, Alice has provided one of his cell, which one does not matter, and has signed the whole transaction. One intention of such a partially signed transaction is that we trust Alice to do the final review and approve the transaction. The proof of Alice's work is her signature.
To make partial signed transaction powerful, we need something interesting to sign. The partial signing script provides the most basic functionality, selecting which parts of the transaction to sign. But it cannot cover the data that require complicated computation, because it cannot foresee all the computation requirements. Also, a signing script that covering all scenarios is too complex to develop and maintain. Complexity also means error-prone and vulnerable in terms of security.
The best practice to address this issue is via script composition. If a script asks to place the computation result somewhere in the transaction, and it will verify that the result is correct, we can sign the script and the result in the signature. The script and the result make up an assertion. We sign the assertion to ensure it holds in the final transaction.
Look at a simple example, the *Max-Fee* script, which takes a single arg that is the maximum allowed transaction fee in the unit of Shannon. The script will compute the transaction fee and succeed if the fee is not larger than its arg. If we sign the partial transaction that one of its input uses *Max-Fee* as the lock script and the arg is 5000, the fee of the final transaction should not exceed 5000 Shannons.
Script *Take-All-And-Then* is like *Max-Fee*. But before delving into it, I'll talk about the *And-Then* pattern first.
## *And-Then* Patten
One input cell has two slots for executing scripts, the lock script and the type script. If we want to run more scripts, we either add more cells into the transaction, or we put several scripts into one slot.
*And-Then* is a solution in the latter category. It is a pattern of scripts composition to take the advantage of the [exec syscall](https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0034-vm-syscalls-2/0034-vm-syscalls-2.md#exec).
It's a simplified version of Xuejie's [ideas on chained lock](https://talk.nervos.org/t/ideas-on-chained-locks/5887).
An And-Then script serializes the inner script in args. It should not store data in witness, which are reserved for the inner script. Instead, the script should put its own data in args as well.
Here is an example of *Max-Fee-And-Then* script, which applies the pattern to the script *Max-Fee* mentioned above. This example script serializes args in JSON.
```json
{
"fee": 5000,
"inner": {
"code_hash": "0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d…",
"hash_type": "type",
"args": "0xe463d7c4cb28457b3a2f735d1d92a971b0f5a751"
}
}
```
The inner script is the [secp256k1-blake160](https://explorer.nervos.org/scripts#secp256k1_blake160) lock script. I truncated the code hash for better display.
It will execute its own logic first, checking whether the transaction fee does not exceed 5000 Shannon, **and then** loads the inner script to `exec`ute it.
## The Informal Specification of *Take-All-And-Then*
The *Take-All-And-Then* script accepts the same serialization format as *Max-Fee-And-Then*.
```json
{
"fee": number,
"inner": Script
}
```
Besides checking that the transaction fee does not exceed the arg `fee`, it also ensures that there's only one payee in the transaction.
It's hard to recognize identities in a transaction, but we can simplify it by assuming that every pair of input and output cells having the same position is a participant of the transaction. So the algorithm to check the payee looks like:
- For each output cell of the transaction, assuming that the output index is *i* (starting from 0), check whether the output cell *i* is a payee.
- If there are less than *i + 1* input cells, count output *i* as a payee.
- If there are enough input cells, compare the CKB balance of input cell *i* and output cell *i*. If the input balance is less than the output balance, output *i* is a payee.
If the transaction bypasses the fee and number of payees checking, the script continues executing the inner script.
It's easy to extend to user defined tokens, but that's beyond the scope of user scenarios analysis and PoC version of CKB Open Transaction.