What is Celestia Fibre?
Celestia Fibre is a second way to publish blobs on Celestia, added in celestia-app v10: the blob's bytes are stored and served by Fibre servers that the validators run, and do not go into Celestia blocks. The chain only records that the blob was published, who endorsed it, and that it was paid for.
This page explains how it works; for how this site derives its numbers, see Methodology.
What Fibre is
A second blob path: the data stays off-block; payment and signatures go on chain
The regular blob path (MsgPayForBlobs) stays as it is. Publishers choose a path for each blob. On this network, Fibre is active from block 1,082,620.
Why a second path
Regular blobs are stored inside the block itself, so every byte competes for block space. Fibre keeps the payload outside the block and puts only a commitment to it on chain. That allows more data to be published without making blocks larger.
What goes on chain
- A MsgPayForFibre transaction (a PFF). It carries the publisher's payment promise and the signatures of the validators that stored and checked their part of the blob.
- A small blob in the publisher's namespace, created by the chain. It holds the Fibre blob version, the 32-byte commitment, and the address of the account that submitted the PFF.
- The payment, taken from the publisher's prepaid escrow account.
The blob's data itself never enters a block.
Fibre is not long-term storage. Fibre servers keep their part of a blob for at least 4 hours after the payment promise was created (the shard_retention parameter), or until the promise expires if that is later. On this network that is 4 hours. This is how the Fibre server software behaves; the chain does not enforce it. After that the rows may be deleted. Publishers and readers should keep their own copy.
Fibre compared with regular blobs
| Property | Regular blobs | Fibre |
|---|---|---|
| Where the data lives | In the block | On validators' Fibre servers, cut into rows. Only a commitment goes in the block |
| Largest blob | The whole transaction must fit in 8 MiB | 134,217,723 bytes of data (128 MiB with the 5-byte header) |
| How it is paid | Transaction fee. The blob adds 8 gas for every byte of the 512-byte shares it fills, padding included, on top of the transaction's other gas. The fee is the gas times the gas price | A fixed amount per blob, by its billed size (formula), taken from a prepaid escrow. The transaction fee is paid separately |
| What shows the data was available | Consensus on the block, and light nodes sampling it | Signatures from validators holding at least 2/3 of the stake, each given after storing and checking its rows |
| Light-node sampling | Light nodes sample the block, which holds the blob | For this blob, the block holds only the PFF and the commitment blob, so that is all light nodes can sample. The blob's data is not in it |
| How it is fetched | By height, namespace and commitment | By its 33-byte blob ID |
Sources
CIP-51; celestia-app v10.4.0-mocha: specs/src/fibre_encoding.md, x/fibre/README.md, fibre/protocol_params.go, fibre/blob.go, fibre/blob_id.go, fibre/validator/signature_set.go, x/blob/keeper/keeper.go and x/blob/types/payforblob.go (regular blob gas), pkg/appconsts/app_consts.go, specs/src/parameters_v10.md; Celestia docs: Fibre guide (written for Mocha), Data availability FAQ; live shard_retention from this site's parameters.
How a blob is split into rows
Each blob is cut into 4,096 rows plus 12,288 parity rows; any 4,096 rebuild it
Before upload, the blob is cut into 4,096 equal slices called rows. Every blob has 4,096 data rows, whatever its size; a bigger blob has wider rows. The encoder then computes 12,288 parity rows from them, so each blob becomes 16,384 rows of the same width. Any 4,096 of the 16,384 rows are enough to rebuild the blob.
| Blob | Width of each row | Billed size (4,096 rows) |
|---|---|---|
| 300 bytes | 64 bytes, the minimum | 256 KiB, mostly padding |
| 10 MiB | 2,624 bytes | 10,747,904 bytes |
| 134,217,723 bytes (largest) | 32 KiB | 128 MiB |
The width is the blob plus its 5-byte header, divided by 4,096 and rounded up to a multiple of 64 bytes. That rounding is why the smallest billed size is 4,096 × 64 bytes = 256 KiB.
The rows form a grid only while the blob is encoded: the parity rows are computed down the columns of that grid. After that, each row is a separate numbered piece. It comes with a proof that it belongs to the blob's commitment, so it can be checked on its own. Validators are assigned rows roughly in proportion to their stake (exact rule under Endorsements and security), store them, and serve them to readers, who collect any 4,096 different rows.
See real rows of a 300-byte blob
Output of celestia-app's own encoder for a 300-byte sample text. Each row is 64 bytes, shown as hex with the readable characters on the right.
00 00 00 00 01 2c 46 69 62 72 65 20 6b 65 65 70 73 |....,Fibre keeps| 10 20 62 6c 6f 62 20 64 61 74 61 20 6f 6e 20 76 61 | blob data on va| 20 6c 69 64 61 74 6f 72 73 2e 20 46 69 62 72 65 20 |lidators. Fibre | 30 6b 65 65 70 73 20 62 6c 6f 62 20 64 61 74 61 20 |keeps blob data |
00 64 61 74 6f 72 73 2e 20 46 69 62 72 65 20 6b 65 |dators. Fibre ke| 10 65 70 73 20 62 6c 6f 62 20 64 61 74 61 20 6f 6e |eps blob data on| 20 20 76 61 6c 69 64 61 74 6f 72 73 2e 20 46 69 62 | validators. Fib| 30 72 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |r...............|
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00 46 6d e8 61 c5 0f ce 6a a9 8a 36 4e fb b3 6c 8d |Fm.a...j..6N..l.| 10 e8 4c c1 61 b1 12 a4 17 92 d0 31 03 22 6f 47 c5 |.L.a......1."oG.| 20 94 62 2c 6a c1 4c 04 95 a6 02 18 d8 41 0e d8 c6 |.b,j.L......A...| 30 0a 79 5f b7 c7 47 5e 25 e9 e6 85 7a 95 74 ed 50 |.y_..G^%...z.t.P|
Sources
celestia-app v10.4.0-mocha: fibre/protocol_params.go (row count, row width), fibre/blob.go (header), pkg/rsema1d/README.md and pkg/rsema1d/SPEC.md (parity computed down columns, any 4,096 rows rebuild, per-row proofs), specs/src/fibre_client.md (assignment, download). Example rows produced with fibre.NewBlob from that version.
Blob lifecycle
Fund escrow → promise → upload → validators sign → PFF settles → retrieve
A Fibre blob goes through these steps, from funding to retrieval.
- 1Fund escrow
- 2Encode and promise
- 3Upload rows
- 4Check, store, sign
- 5Settle at ≥ 2/3 stake
- 6Retrieve any 4,096 rows
- Fund the escrow. The publisher deposits TIA into a Fibre escrow account (MsgDepositToEscrow). Fibre payments are taken from this account, not from the publisher's regular balance. A withdrawal is paid out only 1 day after it is requested, so the publisher cannot promise a payment and then empty the escrow before it settles.
- Encode and promise. The publisher's client cuts the blob into rows, adds the parity rows, and computes a 32-byte commitment to them. It signs a payment promise naming the chain, the namespace, the billed size, the commitment, the creation time and the height of the current validator set.
- Upload. Each validator is assigned a set of rows, roughly in proportion to its stake. The assignment follows from the commitment and the validator set at the promise's height. The client sends each validator its rows, with proofs and the promise, to the Fibre server host the validator registered on chain.
- Check, store, sign. Each Fibre server checks the promise (owner signature, freshness, and that the escrow covers the payment), checks that it received exactly its assigned rows, and checks each row against the commitment. It stores the rows first, then signs the promise.
- Settle. Once the signatures cover at least 2/3 of the stake, a MsgPayForFibre carrying the promise and the signatures is submitted. Anyone may submit it. The Fibre client's Put helper submits it itself; the x/fibre README notes it is typically one of the endorsing validators. It must be included less than 1 hour after the promise was created, and at most 1,000 blocks after the promise's height. The chain then takes the payment from the escrow, adds the small commitment blob to the block, and records the promise as processed, so it cannot be paid twice.
If it never settles. When 1 hour has passed without a PFF, anyone can submit MsgPaymentPromiseTimeout, until 1 day after the promise was created. The escrow is charged the same amount, but no commitment blob is added. This is how a promise that was handed out but never settled still gets paid for, if someone submits the timeout in that window.
- Retrieve. Anyone with the 33-byte blob ID can download the blob. The client asks validators for their rows in a random order weighted by stake, so higher-stake validators tend to be tried first, and checks each row against the commitment. Any 4,096 rows are enough to rebuild the blob. This only works while Fibre servers still hold the rows: on this network at least 4 hours after the promise was created.
Payments, settled or timed out, go to the fee collector and are distributed to validators and delegators like regular transaction fees. The amount does not depend on which validators signed, and it is not sent to them directly.
See it live: the latest blobs (each blob page shows which validators signed, by stake), validators' signing records, and what a blob costs.
Sources
CIP-51; celestia-app v10.4.0-mocha: specs/src/fibre_client.md (upload and download flows), specs/src/fibre_server.md (UploadShard flow), specs/src/fibre_module.md, x/fibre/README.md, x/fibre/keeper/keeper.go (promise validation), x/fibre/keeper/msg_server.go (settlement, timeout, fee collector), fibre/validator/set.go (download order), x/valaddr/README.md, pkg/rsema1d/README.md; live parameters from this site.
Endorsements and security
A blob settles at 2/3 of stake; what a signature proves and what it does not
What a validator signature means
CIP-51: “A validator signature means the validator accepted and stored its assigned shard.” Before signing, the validator's Fibre server has checked that:
- the payment promise is signed by the escrow owner, is still fresh, and the escrow can pay it;
- the rows it received are exactly the rows assigned to it;
- each row belongs to the blob's commitment.
What a signature does not guarantee
- That the data will be served later. CIP-51: if too many assigned validators are “unavailable, pruning early, misconfigured, or unreachable, readers may fail to reconstruct the blob even though the on-chain commitment exists.”
- That the data is kept beyond the retention period. Fibre servers may delete rows once shard_retention has passed and the promise has expired (see Parameters).
- That the blob was encoded correctly. A publisher could build the commitment from wrongly encoded rows that still pass each row's check. Readers can detect and skip such rows, but, as the client specification notes, this “does not prevent a bad commitment from being accepted on-chain if enough validators sign it”.
- That the content is meaningful. CIP-51: “The Fibre commitment binds bytes, not application meaning.” Applications check namespace, signer and validity themselves.
The two thresholds
| Threshold | Where it is used | Rule in the code |
|---|---|---|
| 2/3 of stake | Settling a PFF | Signed stake must reach total stake × 2 / 3, rounded down. Exactly two thirds is enough. Stake is taken from the validator set at the promise's height |
| 1/3 of stake | Assigning rows | A validator gets ⌈4,096 × 3 × its stake ÷ total stake⌉ rows, raised to a minimum and capped at 4,096. So any group of validators with at least 1/3 of the stake is assigned at least 4,096 rows, the number needed to rebuild a blob |
Rows are dealt out from a shuffled list, and once the list runs out it starts again from the top. A row can therefore be assigned to more than one validator, so the number of rows assigned to a group is not always the number of different rows it holds.
Who checks the signatures
The chain checks the signatures when it accepts a PFF, but only until the 2/3 threshold is reached; later signatures in the same PFF are not checked on chain. This site checks every signature itself and counts only valid ones as endorsements (see Methodology).
Sources
CIP-51 (Security Considerations); celestia-app v10.4.0-mocha: specs/src/fibre_server.md, specs/src/fibre_client.md (download flow, assignment), fibre/validator/signature_set.go (threshold), fibre/validator/set.go (assignment), x/fibre/keeper/msg_server.go (validateValidatorSignatures), fibre/protocol_params.go.
Parameters
Current x/fibre values on this network; rows are kept for at least 4 hours
These x/fibre parameters can be changed by governance. The values below are the current ones on this network, in effect from block 1,082,620. Past values are on the Parameters page.
| Parameter | Current value | Meaning | Allowed range |
|---|---|---|---|
| shard_ | 4 hours | Minimum time a Fibre server keeps a blob's rows after the payment promise was created. Rows are also kept until the promise expires, if that is later | 10 minutes to 7 days |
| payment_ | 1 hour | How long a promise can be settled with a PFF. After it, the promise can only be charged as a timeout | 10 minutes to 12 hours |
| payment_ | 1,000 blocks | How many blocks after the promise's height a PFF can still be included | At least 1 block |
| withdrawal_ | 1 day | Time between an escrow withdrawal request and its payout. It is also the maximum age of a payment promise: older promises can no longer be settled, not even as a timeout | 12 hours 10 minutes to 7 days |
| full_ | 2.00 TiB (2,199,023,255,552 bytes) | Storage cap per validator over one retention window, for a validator assigned the maximum 4,096 rows. Others get it in proportion to their rows. A Fibre server refuses uploads beyond its cap | Any positive number of bytes |
Fixed by the protocol
These values are set in code and change only with a new celestia-app version.
| Rows per blob | 4,096 data rows plus 12,288 parity rows (16,384 in total). Any 4,096 rebuild the blob |
|---|---|
| Largest blob | 134,217,723 bytes of data (128 MiB with the 5-byte header) |
| Row width | Rounded up to a multiple of 64 bytes, so the smallest billed size is 4,096 × 64 bytes = 256 KiB |
| Payment per blob | 650,000 utia plus 45,000 utia per started 256 KiB of billed size. A 300-byte blob costs 695,000 utia; a 128 MiB blob costs 23,690,000 utia |
| PFFs per block | At most 200 |
| Promise clock skew | A promise's creation time may be at most 10 minutes ahead of block time |
| Replay protection | A settled promise is remembered for withdrawal_delay plus 10 minutes. Older promises are rejected as too old |
| Blob ID | 33 bytes: 1 version byte and the 32-byte commitment |
Sources
celestia-app v10.4.0-mocha: x/fibre/types/params.go (defaults and ranges), fibre/protocol_params.go, fibre/blob_id.go, pkg/appconsts/fibre_consts.go, pkg/appconsts/fibre_gas_consts.go, x/fibre/types/gas.go, x/fibre/keeper/keeper.go, fibre/server.go and fibre/server_upload.go (storage cap); CIP-51 (parameter table); Celestia docs: Fibre guide (written for Mocha) (example charges); current values read from chain by this site.
Glossary
The terms used on this site: rows, shards, promises, escrow, PFF and more
- Blob
- Data published to Celestia under a namespace. With Fibre, its bytes stay on validators' Fibre servers.
- Namespace
- A 29-byte identifier every blob is published under. Fibre adds the commitment blob to the publisher's namespace.
- Fibre server
- The service a validator runs to receive, store and serve Fibre rows. Its host is registered on chain.
- Provider registry
- The on-chain list (x/valaddr) mapping each validator to its Fibre server host. A validator that is not registered receives no Fibre traffic.
- Row
- One of the 4,096 equal slices a blob is cut into, or one of the parity rows computed from them. Rows are as wide as the blob needs: 64 bytes to 32 KiB.
- Parity rows
- The 12,288 rows computed from the 4,096 data rows. Any 4,096 of the 16,384 rows rebuild the blob.
- Shard
- The rows assigned to one validator for one blob, sent and stored with their proofs.
- Commitment
- A 32-byte value that binds all rows of a blob. Each row is checked against it on upload and download.
- Blob ID
- 33 bytes: the blob version followed by the commitment. Used to download a blob.
- Blob version
- The encoding format of a Fibre blob. Version 0 is the only one in use.
- Billed size
- The size a Fibre blob is charged for and that the payment promise records: row width × 4,096, padding included. The code calls it the upload size (blob_size).
- Payment promise
- A message signed by the escrow owner promising to pay for one blob. Validators sign the same message after storing their rows.
- Escrow account
- Prepaid funds held by the Fibre module, from which payments are taken.
- Escrow owner
- The account whose key signed the payment promise and whose escrow pays. It can differ from the account that submits the PFF.
- PFF (MsgPayForFibre)
- The transaction that settles a payment promise, carrying the validator signatures.
- Endorsement
- A validator's signature on a payment promise, given after it stored its rows.
- Stake (voting power)
- The tokens bonded to a validator, which give it voting power. Row assignment and the 2/3 threshold use each validator's share in the validator set at the promise's height.
- Promise height
- The block height named in the promise. Its validator set decides row assignment and whose signatures count.
- Timeout settlement
- Charging an unsettled promise after payment_promise_timeout, via MsgPaymentPromiseTimeout. No validator signatures are needed.
- TIA, utia
- Celestia's token. 1 TIA = 1,000,000 utia; amounts on this site are exact utia.
- Gas
- The unit a transaction's work is measured in. A transaction fee is its gas times the gas price. Fibre payments are a fixed 1 utia per gas.
- Light node
- A Celestia node that checks that block data is available by sampling small random pieces of each block.
- Governance
- On-chain proposals and votes by stakers. The x/fibre parameters can only be changed this way.
- Fee collector
- The account that receives transaction fees and Fibre payments before they are distributed to validators and delegators.
- Consensus address (valcons)
- The address of a validator's consensus key, used on validator pages. The provider registry is keyed by it.
- Operator address (valoper)
- The address that identifies a validator in staking, used on validator pages. It is the signer named when a validator registers its Fibre server host.
Sources
celestia-app v10.4.0-mocha: specs/src/fibre_client.md (glossary), specs/src/fibre_module.md, specs/src/fibre_encoding.md, x/valaddr/README.md, fibre/blob_id.go, x/fibre/keeper/msg_server.go; CIP-51.
Sources and verification
What every statement was checked against, and where the sources disagree
Every statement on this page was checked against these sources on 2026-10-19, in this order of authority:
- celestia-app source code at v10.4.0-mocha, the version this site decodes this network with, including its specifications and module READMEs.
- CIP-51, the Fibre protocol proposal (status: Implemented).
- Celestia's documentation: Fibre guide (written for Mocha) and the Data availability FAQ (both last updated 16 October 2026).
- Current parameter values, read from chain by this site.
Each section lists its own sources under “Sources”. When sources disagree, the code wins. These disagreements were found:
- The 2/3 threshold. The x/fibre README says signatures must represent “more than 2/3 of the voting power”. The code accepts total × 2 / 3 rounded down, so exactly two thirds is enough. The module specification states the same rule, but a few lines later also calls it a “2/3+ threshold”.
- Storage cap refusals. The Fibre server specification says the server does not currently return ResourceExhausted “for the cases described by older target designs”. The code returns it when an upload would exceed the server's storage cap.
- Storage cap size. The x/fibre README describes full_stake_storage_budget as the cap of a “hypothetical 100%-stake validator” (CIP-51: “hypothetical full-stake validator”), from which each server or validator derives a “stake-proportional budget”. The code scales it by assigned rows (budget × rows ÷ 4,096), and rows are capped at 4,096, so every validator with at least 1/3 of the stake gets the full budget.
How this site turns chain and probe data into numbers is described in Methodology.