# Data Availability

Citrea utilizes Bitcoin as its unified layer for data availability and settlement. The [`bitcoin-da`](https://github.com/chainwayxyz/citrea/tree/nightly/crates/bitcoin-da) implementation handles publishing rollup data to Bitcoin and retrieving that data for verification within the [light client proof](/essentials/architecture-and-transaction-lifecycle.md#light-client-prover) circuit:

By leveraging the transaction Merkle root in Bitcoin block headers and verifying the header-chain proof-of-work, Citrea generates ZK proofs that cryptographically confirm specific transactions exist on the blockchain. This allows the protocol to verify data inclusion mathematically, ensuring the rollup state is always derivable from Bitcoin itself.

## Bitcoin as Settlement Layer

Beyond data availability, Bitcoin serves as Citrea's settlement layer. Unlike Ethereum rollups that settle via on-chain verifier contracts, Citrea achieves settlement through a cryptographic proof chain anchored to Bitcoin's proof-of-work; the proofs themselves are the settlement mechanism.

### State Commitment Pipeline

Settlement on Citrea follows a three-stage pipeline, each stage publishing data to Bitcoin:

1. **Sequencer Commitments**: The [sequencer](/essentials/architecture-and-transaction-lifecycle.md#sequencer) periodically publishes [commitments](/essentials/architecture-and-transaction-lifecycle.md#4-sequencer-commitments-on-bitcoin) containing a Merkle root over sequential L2 block hashes and the batch's ending L2 block number (the start is implicitly the previous commitment's end + 1). Once finalized on Bitcoin, these commitments pin the canonical ordering of L2 blocks, the sequencer cannot reorder or omit transactions without contradicting data already settled on Bitcoin.
2. **Batch Proofs**: The [batch prover](/essentials/architecture-and-transaction-lifecycle.md#batch-prover) generates a zkSNARK proving that executing all transactions in a committed batch, starting from the previous proven state root, produces the claimed new state root. This proof, along with compressed state diffs, is published to Bitcoin. The proof attests: *"the state transition is valid"*. Proof payloads are Brotli-compressed before inscribed on-chain. Batch proofs under [MAX\_TX\_BODY\_SIZE](https://github.com/chainwayxyz/citrea/blob/nightly/crates/primitives/src/constants.rs#L24) (397KB) fit in a single transaction; larger proofs are chunked and later aggregated.
3. **Light Client Proofs**: The [light client prover](/essentials/architecture-and-transaction-lifecycle.md#light-client-prover) produces recursive proofs that chain together, each verifying the previous proof plus new batch proofs. The resulting proof encapsulates the entire rollup history: *"starting from genesis and applying all batches yields state root X"*. This single proof is sufficient for external verifiers to confirm Citrea's state without processing the full history.

### Settlement Without Smart Contracts

Bitcoin lacks the programmability to verify zkSNARKs directly on-chain. Citrea addresses this through two mechanisms:

* **Full node verification**: Citrea full nodes fetch batch proofs from Bitcoin and verify them locally. Once verified, the batch reaches [proven finality](/essentials/transaction-finality.md#proven). The state transition is cryptographically guaranteed, secured by both the zkSNARK soundness and Bitcoin's proof-of-work protecting the data.
* **BitVM-based bridge verification**: The [Clementine bridge](https://github.com/chainwayxyz/citrea-docs/blob/main/essentials/clementine-bridge.md) uses BitVM to optimistically verify light client proofs on Bitcoin. Operators can be challenged if they claim an incorrect state, with the light client proof serving as the dispute resolution mechanism. This enables trust-minimized BTC withdrawals without requiring Bitcoin soft forks.

### Finality Guarantees

L2 transactions inherit Bitcoin's finality in stages (see [Transaction Finality](/essentials/transaction-finality.md)):

| Stage          | Anchor                          | Guarantee                                                                                     |
| -------------- | ------------------------------- | --------------------------------------------------------------------------------------------- |
| Soft-confirmed | Sequencer signature             | Fast UX, but can still be reorged                                                             |
| Finalized      | Sequencer commitment on Bitcoin | Transactions are considered finalized after [6 L1 confirmations](/advanced/reorg-handling.md) |
| Proven         | Batch proof on Bitcoin          | Execution validity is cryptographically verified                                              |

Once proven, reverting an L2 transaction would require either breaking the zkSNARK (computationally infeasible) or executing a deep Bitcoin reorganization beyond the finality depth—making proven L2 transactions effectively as secure as L1 Bitcoin transactions.

## Publishing Data on Bitcoin Using Inscriptions

Citrea publishes data using a Taproot commit-reveal scheme. The commit transaction locks funds to a script that can only be spent by revealing the inscription data. The reveal transaction then spends this output, embedding the data in the witness. This type of data was popularized and named "inscriptions" by the [Ordinals protocol](https://docs.ordinals.com/inscriptions.html).

The reveal script has a header identifying the transaction type:

```
PushBytes(XOnlyPublicKey)
OP_CHECKSIGVERIFY
PushBytes([2 bytes for transaction type in LE])
```

The body follows with an `OP_FALSE OP_IF ... OP_ENDIF` pattern that creates an unexecuted code branch, allowing data storage without affecting script execution. Each body chunk is limited to 520 bytes due to Bitcoin's script push size limit.

Witness data benefits from the SegWit discount, costing approximately 1/4 the fee of equivalent data stored in transaction outputs.

## WTXID Prefix

The [light client proof](/essentials/architecture-and-transaction-lifecycle.md#light-client-prover) must verify that all relevant DA transactions in a Bitcoin block are included. Scanning and parsing every transaction in a block to check if it's a Citrea inscription adds significant overhead to the ZK circuit—the circuit cost grows linearly with the number of transactions, regardless of whether they are Citrea-related.

Citrea uses a witness transaction ID (WTXID) prefix mechanism to reduce this overhead. The transaction publisher (sequencer, batch prover, or security council) adjusts a nonce in the reveal script until the resulting WTXID starts with a specific prefix ([`0x0202`](https://github.com/chainwayxyz/citrea/blob/nightly/crates/primitives/src/constants.rs#L7)). The circuit then filters candidate transactions by checking only the first two bytes of each WTXID, parsing only those that match.

With a 2-byte prefix, a random transaction has a 1/65,536 chance of matching, resulting in approximately 0.0015% false positives per block. These are filtered out during [transaction format parsing](https://github.com/chainwayxyz/citrea/blob/nightly/crates/bitcoin-da/src/helpers/parsers.rs). The prefix mechanism is purely a performance optimization for the ZK circuit—it has no security value since anyone can craft a matching nonce. Security comes entirely from signature verification: all Citrea inscriptions must contain a valid signature from an authorized key (sequencer, batch prover, or security council).

## Transaction Types

The bitcoin-da implementation supports [multiple transaction types](https://github.com/chainwayxyz/citrea/blob/nightly/crates/bitcoin-da/src/helpers/mod.rs#L21-L36): Complete batch proofs (type `0x00`), Aggregate batch proofs (`0x01`), Chunks (`0x02`), BatchProofMethodId updates (`0x03`), and Sequencer Commitments (`0x04`).

### Batch Proofs

A batch proof that fits within 397KB is published as a single Complete transaction. This limit exists because Bitcoin Core's [default mempool policy](https://github.com/bitcoin/bitcoin/blob/d52ba21dfff99173abb927bc964ce831071c2f6f/src/policy/policy.h#L26-L27) rejects transactions exceeding 400KB (MAX\_STANDARD\_TX\_WEIGHT), and 397KB leaves room for script overhead while ensuring transactions propagate across the network. The inscription contains a signature, the [batch prover's](/essentials/architecture-and-transaction-lifecycle.md#batch-prover) public key, and the compressed proof data split into 520-byte chunks:

```
OP_FALSE
OP_IF
  OP_PUSHDATA(signature)
  OP_PUSHDATA(batch_prover_public_key)
  OP_PUSHDATA(proof_chunk_1)
  ...
  OP_PUSHDATA(proof_chunk_n)
OP_ENDIF
OP_PUSHDATA(8 random bytes [nonce])
OP_NIP
```

When a batch proof exceeds 397KB, it's split across multiple Chunk transactions. Each chunk contains only the raw data (no signature or public key). An Aggregate transaction then ties these chunks together by containing pointers to each chunk's txid and wtxid, along with a signature from the batch prover covering the aggregate data. The light client proof verifies the aggregate transaction's signature and uses the pointers to locate and reconstruct the full proof from the referenced chunks.

### BatchProofMethodId

The [BatchProofMethodId](https://github.com/chainwayxyz/citrea/blob/nightly/crates/sovereign-sdk/rollup-interface/src/state_machine/da.rs#L61-L74) transaction allows the security council to update the ZK verification key (method ID) used by the light client proof to verify batch proofs. This enables the light client proof to verify batch proofs generated with an updated proving system. It contains a new method ID, the L2 activation height, and 3-of-5 security council signatures.

### Sequencer Commitment

The [sequencer](/essentials/architecture-and-transaction-lifecycle.md#sequencer) publishes [commitments](/essentials/architecture-and-transaction-lifecycle.md#4-sequencer-commitments-on-bitcoin) that include a Merkle root of L2 block hashes, a monotonic index, and the ending L2 block number. See [`SequencerCommitment`](https://github.com/chainwayxyz/citrea/blob/nightly/crates/sovereign-sdk/rollup-interface/src/state_machine/da.rs#L21-L28) for the full structure.

{% hint style="info" %}
For implementation details and full transaction format specifications, see the [bitcoin-da crate](https://github.com/chainwayxyz/citrea/tree/nightly/crates/bitcoin-da).
{% endhint %}

## Verification in the Light Client Proof

The [DA verifier](https://github.com/chainwayxyz/citrea/blob/nightly/crates/bitcoin-da/src/verifier.rs#L36) runs inside the light client proof circuit and enforces both completeness and correctness of data.

**Completeness** ensures no relevant transactions are omitted. A transaction is "relevant" if its WTXID starts with the Citrea prefix (`0x0202`) and successfully parses as a valid Citrea inscription. The verifier iterates through all transaction WTXIDs in the block, filters by prefix, parses matching transactions, and rejects the proof if any valid Citrea transaction is missing from the provided data.

**Correctness** ensures included data is valid and untampered:

* **Witness data verification**: The verifier computes the witness Merkle root from all WTXIDs in the block. The coinbase transaction contains a SegWit commitment in its output (prefixed [`0x6a24aa21a9ed`](https://github.com/chainwayxyz/citrea/blob/nightly/crates/bitcoin-da/src/verifier.rs#L21)). The verifier confirms `SHA256d(witness_merkle_root || witness_nonce)` matches this commitment.
* **Coinbase inclusion**: The coinbase transaction itself is verified against the header's Merkle root via a txid Merkle proof, establishing that the witness commitment comes from the actual block.
* **Sender authentication**: Inscriptions include the sender's public key and a signature over `SHA256(blob_body)`. The verifier checks this ECDSA signature to confirm data originated from an authorized party (sequencer, batch prover, or security council).
* **Decompression bounds**: When reconstructing Brotli-compressed payloads, the circuit enforces protocol size limits on the decompressed output. Any payload that expands beyond allowed bounds of 100 MB (see [MAX\_DECOMPRESSED\_BLOB\_SIZE](https://github.com/chainwayxyz/citrea/blob/nightly/crates/primitives/src/constants.rs#L58)) causes proof failure, preventing decompression-bomb style attacks inside the circuit.

The verifier also validates the Bitcoin header chain itself—checking block hashes, height continuity, difficulty targets, proof of work, and timestamp validity. On mainnet, [6 block confirmations](https://github.com/chainwayxyz/citrea/blob/nightly/crates/bitcoin-da/src/network_constants.rs#L12) are required before data is considered final (see [Transaction Finality](/essentials/transaction-finality.md)). See [`NetworkConstants`](https://github.com/chainwayxyz/citrea/blob/nightly/crates/bitcoin-da/src/network_constants.rs#L52-L59) for network-specific parameters.

### Recursive Proof Accumulation

The light client proof is recursive: each proof verifies the previous proof before processing the next L1 block. This creates a chain where verifying a single proof attests that, for the given Bitcoin chain up to that block, the L2 state produced by the circuit is correct and consistent with all on-chain commitments.

#### Chain Structure

Each light client proof takes as input:

* The previous light client proof (None for the genesis proof)
* A Bitcoin block header with inclusion and completeness proofs
* A witness for accessing the circuit's JMT state

The circuit first verifies the previous proof using the zkVM's verification API, extracting the previous output. It then verifies the new block header follows the previous block under Bitcoin's consensus rules—checking proof-of-work, height continuity, difficulty targets, and timestamp validity.

#### Accumulated State

The circuit maintains a [JellyFish Merkle Tree](https://github.com/penumbra-zone/jmt) (JMT) that accumulates the following data across blocks:

| Data Type                  | Purpose                                                                          |
| -------------------------- | -------------------------------------------------------------------------------- |
| Block hashes               | Proves a specific L1 block was seen by the circuit                               |
| Sequencer commitments      | Stores commitment data indexed by monotonic index                                |
| Verified state transitions | Maps commitment index to verified (initial\_root, final\_root, last\_l2\_height) |
| Proof chunks               | Stores chunk bodies by wtxid for later aggregation                               |
| Batch proof method IDs     | Tracks verification keys with activation heights                                 |

#### Transaction Processing

For each Bitcoin block, the circuit processes all relevant transactions extracted via the completeness proof:

1. **Sequencer commitments**: Stored in the JMT by their index. The circuit verifies the sender is the authorized sequencer.
2. **Batch proofs** (Complete or Aggregate): The circuit verifies the zkSNARK using the appropriate method ID from the JMT. It then validates the sequencer commitment relation—ensuring the batch proof's referenced commitments exist in the JMT with matching hashes. Upon successful verification, each commitment in the batch's range is marked as a `VerifiedStateTransition` in the JMT.
3. **Proof chunks**: Stored in the JMT by their wtxid. When an Aggregate transaction arrives, the circuit retrieves and concatenates the chunks to reconstruct the full proof.
4. **Method ID updates**: Stores new verification keys with their activation L2 height after validating 3-of-5 security council signatures.

#### State Root Advancement

After processing all transactions, the circuit attempts to advance the L2 state. It checks if the next sequencer commitment index has a verified state transition whose initial state root matches the current L2 state root. If so, it updates:

* The L2 state root to the transition's final state root
* The last L2 height
* The last sequencer commitment index

This advancement continues for as many consecutive verified transitions as available, ensuring the L2 state only advances through cryptographically verified state transitions that form a continuous chain from genesis.

#### Output

The circuit output contains:

* `l2_state_root`: The verified L2 state root
* `lcp_state_root`: Root of the circuit's JMT, committing to all accumulated data
* `light_client_proof_method_id`: The verification key of this proof, used to ensure the next proof verifies against the same circuit version
* `latest_da_state`: Bitcoin chain state (block hash, height, total work, difficulty parameters)
* `last_l2_height` and `last_sequencer_commitment_index`: Progress markers

By the time a proof is generated for block height `h`, every Citrea transaction from the initial Bitcoin block to `h` has been extracted, verified for sender authorization, and processed. The `lcp_state_root` cryptographically commits to this complete history. The [Clementine bridge](https://github.com/chainwayxyz/citrea-docs/blob/main/essentials/clementine-bridge.md) uses this proof to obtain the verified L2 state root, which it then uses to validate withdrawal claims via storage proofs.

## References

* [SegWit Commitment - BIP 141](https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki)
* [Citrea bitcoin-da crate](https://github.com/chainwayxyz/citrea/tree/nightly/crates/bitcoin-da)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.citrea.xyz/advanced/data-availability.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
