# TX rollup design
Rollups proceed in blocks, just like L1. L1 needs to know when rollup blocks are final, so that it can apply their L1 effects. A L1 block is final 30 blocks after its first non-rejected commitment is received. So L1 needs to store all commitments until either they are rejected, or they are final.
A block is broken into batches of operations to reduce the size of commitment rejections.
## L1 Storage (per rollup):
- Commitment table
- key: Rollup address * Commitment hash = H(data excluding committer account id)
- Because the commitment key does not include the account id, we can reject duplicate commitments before storing them.
- value Commitment
- committer account id
- ancestor commitment hash
- (effect list * after root) list
- each entry is one batch
- Candidates table
- key: Rollup address * Rollup level (that the commitment applies to)
- value:
- (Commitment hash) list
- Tezos level for finalization
- Inbox
- key: Rollup address * Rollup level
- value:
- (rollup-operation list) list
- Ticket ledger
- key: Ticket hash (= H (ticketer, content, type))
- value : ticketer, content, type, amount
Note:
- Nodes must store the rollup operation batches so that we can replay them in the event of a rejection. Once a commitment to a block is final, we no longer need to retain these.
- If amount = 0, then an entry can be removed from the ticket values table
## L1 operations:
(including gas and fees)
[Chiachi: I added some details [here](https://hackmd.io/XfjDXcL-SFSAAQprpFZ54w?both) but I havn't finished it yet.]
- Create rollup: creates a rollup identified by a hash of the operation
- This burns 100 tez, which is somewhat arbitrary, but which should be sufficient to reduce unnecessary rollup creation
- Append: append a L2 operation to a rollup
- No gas cost beyond the storage
- Deposit: transfer tickets to a rollup
- ?? gas cost ??
- Commitment: commit to a rollup block
- Contents:
- rollup id
- rollup level
- committer account id
- ancestor commitment hash
- (effect list * after root) list
- Requires a deposit of 10,000 tz
- Probably no need for gas cost given the deposit requirement
- Rejection:
- Key:
commitment hash * batch index * H(after_root, effects)
(earliest batch index is checked first; after a successful rejection, subsequent rejections of the same commitment hash get no reward)
- Value:
- rejector account id
- commitment hash
- batch index
- after root
- effect list
- Requires a deposit
- Gets a reward on success
## L2 storage (per rollup):
- Part of the shared hash (sent to the L1 in commitments)
- Counter (anti-replay) table, per-account
- key: account
- value: Z
- Ticket table (per-account)
- key: account * ticket_hash
- value: Z
- Maintained by rollup node only
- Rollup block table
- key: rollup block hash (?)
- value: We need a notion of rollup blocks
- L2 operation hashes
- L2 operation receipts (`Applied`, `Rejected`)
## L2 operations:
- operations (signed by an account, and comes with a counter):
- Transfer (ticket from the signer to an account)
- account id to
- ticket hash
- amount
- (TODO in MR 4) Burn (part of withdraw)
- “trades”: a list of operations to be executed atomically (maybe be a list of 1 element). It is signed by the origin account of each individual operation
- batch: a list of “trades”, with an aggregated signature for each of the trade
Proposed approach to carbonate:
- For the BLS, fixed cost * number of signature to check
- If failure, then the all batch is a no-op, and operations can be resubmitted in a smaller batch
- For IO, fixed cost * (number of bytes of the key + number of expected bytes of the value, since (if?) of values are of fixed size)
- The `Counter` table is not carbonated
- If failure, the counters are incremented and therefore the operations cannot be resubmitted
Pros:
- Easy to provide a upper-bound
- We can implement a `simulate` RPC in the rollup node to mimic how it is done in L1