# Celestia documentation full context > Full cleaned markdown export of the Celestia documentation for LLM and agent ingestion. --- Title: Blobstream proof queries (legacy) URL: https://docs.celestia.org/build/blobstream/proof-queries.md Source: app/build/blobstream/proof-queries/page.mdx --- # Blobstream proof queries (legacy) > **Legacy reference:** As of September 2026, the Succinct-operated SP1 Blobstream deployments are no longer maintained and do not receive new commitments, and Celenium no longer offers its Blobstream explorer. This page preserves the proof-query and contract-format reference. It does not imply that a maintained deployment is available. ## Prerequisites - Access to a Celestia consensus full node RPC endpoint (or full node). The node doesn't need to be a validating node in order for the proofs to be queried. A full node is enough. ## Querying the proofs To prove PFBs, blobs or shares, we can use the Celestia consensus node's RPC to query proofs for them: ### Heavy RPC request limit Proof queries such as `data_root_inclusion_proof` and `prove_shares` are memory-intensive. They share the consensus node's process-wide heavy RPC request limit with other heavy endpoints and transports. When the limit is reached, clients receive a temporary capacity response: - HTTP GET requests return `503 Service Unavailable`. - JSON-RPC and WebSocket requests return a JSON-RPC error with `server busy: too many concurrent heavy RPC requests, retry later` in the error's `data` field. Use this message to distinguish temporary overload from other JSON-RPC errors. - gRPC requests return `ResourceExhausted`. These responses indicate that the node is busy, not that proof generation failed. Retry with exponential backoff and jitter. Where appropriate, bound the maximum delay or number of retries. ### 1. Data root inclusion proof To prove the data root is committed to by the Blobstream smart contract, we will need to provide a Merkle proof of the data root tuple to a data root tuple root. This can be created using the [`data_root_inclusion_proof`](https://github.com/celestiaorg/celestia-core/blob/c3ab251659f6fe0f36d10e0dbd14c29a78a85352/rpc/client/http/http.go#L492-L511) query. This [endpoint](https://github.com/celestiaorg/celestia-core/blob/793ece9bbd732aec3e09018e37dc31f4bfe122d9/rpc/openapi/openapi.yaml#L1045-L1093) allows querying a data root to data root tuple root proof. It takes a block `height`, a starting block, and an end block, then it generates the binary Merkle proof of the `DataRootTuple`, corresponding to that `height`, to the `DataRootTupleRoot` which is committed to in the Blobstream contract. Example request: `/data_root_inclusion_proof?height=15&start=10&end=20` Which queries the proof of the height `15` to the data commitment defined by the range `[10, 20)`. Example response: ```json { "jsonrpc": "2.0", "id": -1, "result": { "proof": { "total": "10", "index": "5", "leaf_hash": "vkRaRg7FGtZ/ZhsJRh/Uhhb3U6dPaYJ1pJNEfrwq5HE=", "aunts": [ "nmBWWwHpipHwagaI7MAqM/yhCDb4cz7z4lRxmVRq5f8=", "nyzLbFJjnSKOfRZur8xvJiJLA+wBPtwm0KbYglILxLg=", "GI/tJ9WSwcyHM0r0i8t+p3hPFtDieuYR9wSPVkL1r2s=", "+SGf6MfzMmtDKz5MLlH+y7mPV9Moo2x5rLjLe3gbFQo=" ] } } } ``` > **Note:** The values are base64 encoded. For these to be usable with the solidity smart contract, they need to be converted to `bytes32`. Check the next section for more information. ### 2. Transaction inclusion proof To prove that a rollup transaction is part of the data root, we will need to provide two proofs: (1) a namespace Merkle proof of the transaction to (2) a row root. This could be done via proving the shares that contain the transaction to the row root using a namespace Merkle proof. And, a binary Merkle proof of the row root to the data root. These proofs can be generated using the [`ProveShares`](https://github.com/celestiaorg/celestia-core/blob/c3ab251659f6fe0f36d10e0dbd14c29a78a85352/rpc/client/http/http.go#L526-L543) query. This [endpoint](https://github.com/celestiaorg/celestia-core/blob/793ece9bbd732aec3e09018e37dc31f4bfe122d9/rpc/core/tx.go#L175-L213) allows querying a shares proof to row roots, then a row roots to data root proofs. It takes a block `height`, a starting share index and an end share index which define a share range. Then, two proofs are generated: - An NMT proof of the shares to the row roots - A binary Merkle proof of the row root to the data root > **Note:** If the share range spans multiple rows, then the proof can contain multiple NMT and binary proofs. Example request: `/prove_shares?height=15&startShare=0&endShare=1` Which queries the proof of shares `[0,1)` in block `15`. Example response: ```json { "jsonrpc": "2.0", "id": -1, "result": { "data": [ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBAAABXAAAACbaAgrOAgqgAQqdAQogL2NlbGVzdGlhLmJsb2IudjEuTXNnUGF5Rm9yQmxvYnMSeQovY2VsZXN0aWExdWc1ZWt0MmNjN250dzRkdG1zZDlsN3N0cTBzN3Z5ZTd5bTJyZHISHQAAAAAAAAAAAAAAAAAAAAAAAAASExIyQkMkMoiZGgKXAiIgrfloW1M/Y33zlD2luveDELZzr9cF92+2eTaImIWhN9pCAQASZwpQCkYKHy9jb3Ntb3MuY3J5cHRvLnNlY3AyNTZrMS5QdWJLZXkSIwohA36hewmW/AXtrw6S+QsNUzFGfeg37Da6igoP2ZQcK+04EgQKAggBGAISEwoNCgR1dGlhEgUyMTAwMBDQ6AwaQClYLQPNrFoD6H8mgmwxjFeNhwhRu39EcrVKMFkNQ8+HHuodhdOQIG/8DXEmrBwrpwj6hi+3uEsZ+0p5vrf3v8sSAQEaBElORFgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=" ], "share_proofs": [ { "end": 1, "nodes": [ "AAAAAAAAAAAAAAAAAAAAAAAAABITEjJCQyQyiJkAAAAAAAAAAAAAAAAAAAAAAAAAEhMSMkJDJDKImbiwnpOdwIZBFr0UiFhPKwGy/XIIjL+gqm0fqxIw0z0o", "/////////////////////////////////////////////////////////////////////////////3+fuhlzUfKJnZD8yg/JOtZla2V3g2Q7y+18iH5j0Uxk" ] } ], "namespace_id": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABA==", "row_proof": { "row_roots": [ "000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000121312324243243288993946154604701154F739F3D1B5475786DDD960F06D8708D4E870DA6501C51750" ], "proofs": [ { "total": "8", "index": "0", "leaf_hash": "300xzO8TiLwPNuREY6OJcRKzTHQ4y6yy6qH0wAuMMrc=", "aunts": [ "ugp0sV9YNEI5pOiYR7RdOdswwlfBh2o3XiRsmMNmbKs=", "3dMFZFaWZMTZVXhphF5TxlCJ+CT3EvmMFOpiXFH+ID4=", "srl59GiTSiwC9LqdYASzFC6TvusyY7njX8/XThp6Xws=" ] } ], "start_row": 0, "end_row": 0 }, "namespace_version": 0 } } ``` > **Note:** The values are base64 encoded. For these to be usable with the solidity smart contract, they need to be converted to `bytes32`. Check the next section for more information. ## Converting the proofs to be usable in the DAVerifier contract The `DAVerifier` smart contract takes the following proof format: ```solidity /// @notice Contains the necessary parameters to prove that some shares, which were posted to /// the Celestia network, were committed to by the Blobstream smart contract. struct SharesProof { // The shares that were committed to. bytes[] data; // The shares proof to the row roots. If the shares span multiple rows, we will have multiple nmt proofs. NamespaceMerkleMultiproof[] shareProofs; // The namespace of the shares. Namespace namespace; // The rows where the shares belong. If the shares span multiple rows, we will have multiple rows. NamespaceNode[] rowRoots; // The proofs of the rowRoots to the data root. BinaryMerkleProof[] rowProofs; // The proof of the data root tuple to the data root tuple root that was posted to the Blobstream contract. AttestationProof attestationProof; } /// @notice Contains the necessary parameters needed to verify that a data root tuple /// was committed to, by the Blobstream smart contract, at some specific nonce. struct AttestationProof { // the attestation nonce that commits to the data root tuple. uint256 tupleRootNonce; // the data root tuple that was committed to. DataRootTuple tuple; // the binary Merkle proof of the tuple to the commitment. BinaryMerkleProof proof; } ``` To construct the `SharesProof`, we will need the proof that we queried above, and it goes as follows: ### data This is the raw shares that were submitted to Celestia in the `bytes` format. If we take the example blob that was submitted in the [`RollupInclusionProofs.t.sol`](https://github.com/celestiaorg/blobstream-contracts/blob/3a552d8f7bfbed1f3175933260e6e440915d2da4/src/lib/verifier/test/RollupInclusionProofs.t.sol#L64-L65), we can convert it to bytes using the `abi.encode(...)` as done for [this variable](https://github.com/celestiaorg/blobstream-contracts/blob/3a552d8f7bfbed1f3175933260e6e440915d2da4/src/lib/verifier/test/RollupInclusionProofs.t.sol#L384-L402). This can be gotten from the above result of the [transaction inclusion proof](#2-transaction-inclusion-proof) query in the field `data`, which is in `base64` encoded then be converted to hex to be used as described. ### shareProofs This is the shares proof to the row roots. These can contain multiple proofs if the shares containing the blob span across multiple rows. To construct them, we will use the result of the [transaction inclusion proof](#2-transaction-inclusion-proof) section: ```json "share_proofs": [ { "start": ..., "end": ..., "nodes": [ "...", "..." ] } ], ``` > **Note:** If any of the fields is empty, then it will not be in the response. For example, if the `start` field is `0`, it will be omitted in the response. While the `NamespaceMerkleMultiproof` being: ```solidity /// @notice Namespace Merkle Tree Multiproof structure. Proves multiple leaves. struct NamespaceMerkleMultiproof { // The beginning key of the leaves to verify. uint256 beginKey; // The ending key of the leaves to verify. uint256 endKey; // List of side nodes to verify and calculate tree. NamespaceNode[] sideNodes; } ``` So, we can construct the `NamespaceMerkleMultiproof` with the following mapping: - `beginKey` in the Solidity struct **==** `start` in the query response - `endKey` in the Solidity struct **==** `end` in the query response - `sideNodes` in the Solidity struct **==** `nodes` in the query response The `NamespaceNode`, which is the type of the `sideNodes`, is defined as follows: ```solidity /// @notice Namespace Merkle Tree node. struct NamespaceNode { // Minimum namespace. Namespace min; // Maximum namespace. Namespace max; // Node value. bytes32 digest; } ``` So, we construct a `NamespaceNode` via taking the values from the `nodes` field in the query response, we convert them from base64 to `hex`, then we use the following mapping: - `min` == the first 29 bytes in the decoded value - `max` == the second 29 bytes in the decoded value - `digest` == the remaining 32 bytes in the decoded value The `min` and `max` are `Namespace` type which is: ```solidity /// @notice A representation of the Celestia-app namespace ID and its version. /// See: https://celestiaorg.github.io/celestia-app/namespace.html struct Namespace { // The namespace version. bytes1 version; // The namespace ID. bytes28 id; } ``` So, to construct them, we separate the 29 bytes in the decoded value to: - first byte: `version` - remaining 28 bytes: `id` An example of doing this can be found in the [RollupInclusionProofs.t.sol](https://github.com/celestiaorg/blobstream-contracts/blob/3a552d8f7bfbed1f3175933260e6e440915d2da4/src/lib/verifier/test/RollupInclusionProofs.t.sol#L465-L477) test. ### namespace Which is the namespace used by the rollup when submitting data to Celestia. As described above, it can be constructed as follows: ```solidity /// @notice A representation of the Celestia-app namespace ID and its version. /// See: https://celestiaorg.github.io/celestia-app/namespace.html struct Namespace { // The namespace version. bytes1 version; // The namespace ID. bytes28 id; } ``` Via taking the `namespace` value from the `prove_shares` query response, decoding it from base64 to hex, then: - first byte: `version` - remaining 28 bytes: `id` An example can be found in the [RollupInclusionProofs.t.sol](https://github.com/celestiaorg/blobstream-contracts/blob/3a552d8f7bfbed1f3175933260e6e440915d2da4/src/lib/verifier/test/RollupInclusionProofs.t.sol#L488) test. ### rowRoots Which are the roots of the rows where the shares containing the Rollup data are localized. These can be taken from the `prove_shares` query response: ```json "row_proof": { "row_roots": [ "..." ], }, ``` The values inside the `row_roots` are already in hex, and the Solidity type of the `rowRoots` is `NamespaceNode`. So, we will construct them similar to the `sideNodes` of the [shareProofs](#shareproofs). Except that no base64 conversion is needed. ### rowProofs These are the proofs of the rows to the data root. They are of type `BinaryMerkleProof`: ```solidity /// @notice Merkle Tree Proof structure. struct BinaryMerkleProof { // List of side nodes to verify and calculate tree. bytes32[] sideNodes; // The key of the leaf to verify. uint256 key; // The number of leaves in the tree uint256 numLeaves; } ``` To construct them, we take the response of the `prove_shares` query: ```json "row_proof": { "row_roots": [ "..." ], "proofs": [ { "total": "...", "index": "...", "leaf_hash": "...", "aunts": [ "...", "..." ] } ], ``` and do the following mapping: - `key` in the Solidity struct **==** `index` in the query response - `numLeaves` in the Solidity struct **==** `total` in the query response - `sideNodes` in the Solidity struct **==** `aunts` in the query response The type of the `sideNodes` is a `bytes32`. So, we take the values in the query response, we convert them from base64 to hex, then we create the values. An example can be found in the [RollupInclusionProofs.t.sol](https://github.com/celestiaorg/blobstream-contracts/blob/3a552d8f7bfbed1f3175933260e6e440915d2da4/src/lib/verifier/test/RollupInclusionProofs.t.sol#L479-L484) test. ### attestationProof This is the proof of the data root to the data root tuple root, which is committed to in the Blobstream contract: ```solidity /// @notice Contains the necessary parameters needed to verify that a data root tuple /// was committed to, by the Blobstream smart contract, at some specific nonce. struct AttestationProof { // the attestation nonce that commits to the data root tuple. uint256 tupleRootNonce; // the data root tuple that was committed to. DataRootTuple tuple; // the binary Merkle proof of the tuple to the commitment. BinaryMerkleProof proof; } ``` - `tupleRootNonce`: the nonce at which Blobstream committed to the batch containing the block containing the data. - `tuple`: the `DataRootTuple` of the block: ```solidity /// @notice A tuple of data root with metadata. Each data root is associated /// with a Celestia block height. /// @dev `availableDataRoot` in /// https://github.com/celestiaorg/celestia-specs/blob/master/src/specs/data_structures.md#header struct DataRootTuple { // Celestia block height the data root was included in. // Genesis block is height = 0. // First queryable block is height = 1. uint256 height; // Data root. bytes32 dataRoot; } ``` which comprises a `dataRoot`, i.e. the block containing the Rollup data data root, and the `height` which is the `height` of that block. - `proof`: the `BinaryMerkleProof` of the data root tuple to the data root tuple root. Constructing it is similar to constructing the row roots to data root proof in the [rowProofs](#rowproofs) section. An example can be found in the [RollupInclusionProofs.t.sol](https://github.com/celestiaorg/blobstream-contracts/blob/3a552d8f7bfbed1f3175933260e6e440915d2da4/src/lib/verifier/test/RollupInclusionProofs.t.sol#L488) test. If the `dataRoot` or the `tupleRootNonce` is unknown during the verification: - `dataRoot`: can be queried using the `/block?height=15` query (`15` in this example endpoint), and taking the `data_hash` field from the response. - `tupleRootNonce`: can be retrieved using a `gRPC` query to the app to the [`/qgb/v1/data_commitment/range/height`](https://github.com/celestiaorg/celestia-app/blob/c517bd27c4e0b3d6e4521a7d2946662cb0f19f1d/proto/celestia/qgb/v1/query.proto#L51-L56) endpoint. An example can be found in the [`verify`](https://github.com/celestiaorg/celestia-app/blob/c517bd27c4e0b3d6e4521a7d2946662cb0f19f1d/x/blobstream/client/verify.go#L245-L251) command. ## High-level diagrams The two diagrams below summarize how a single share is committed to in Blobstream. The share is highlighted in green. `R0`, `R1`, etc represent the respective row and column roots, the blue and pink gradients are erasure encoded data. More details on the square layout can be found [in the data square layout](https://github.com/celestiaorg/celestia-app/blob/v1.1.0/specs/src/specs/data_square_layout.md) and [data structures](https://github.com/celestiaorg/celestia-app/blob/v1.1.0/specs/src/specs/data_structures.md#erasure-coding) portion of the specs. ### The Celestia square ![Square](/img/blobstream/blobstream-square.png) ### The commitment scheme ![Blobstream Commitment Diagram](/img/blobstream/blobstream-commitment-diagram.png) ## Conclusion After creating all the proofs, and verifying them: 1. Verify inclusion proof of the transaction to Celestia data root 2. Prove that the data root tuple is committed to by the Blobstream smart contract We can be sure that the data was published to Celestia. > **Note:** The above proof constructions are implemented in Solidity, and may require different approaches in other programming languages. --- Title: Go client tutorial URL: https://docs.celestia.org/build/post-retrieve-blob/client/go.md Source: app/build/post-retrieve-blob/client/go/page.mdx --- # Go client tutorial The Celestia Go client lets you submit and retrieve data from the Celestia network without running your own node. This tutorial shows you how to get started with the basics. ## What you can do - **Submit blobs**: Store data on Celestia's data availability layer - **Retrieve blobs**: Get data back from the network - **Check balance**: See your account's token balance - **Read-only mode**: Just retrieve data without submitting ## Prerequisites - Go 1.25.x (Go 1.26 is not yet supported by a transitive dependency, `bytedance/sonic`; if your default toolchain is newer, run the tutorial with `GOTOOLCHAIN=go1.25.1 go run main.go`) - A Celestia account (created automatically) - Testnet tokens from the [Mocha faucet](/operate/networks/mocha-testnet#mocha-testnet-faucet) ## Quick setup ### Create your project ```bash mkdir celestia-client-example cd celestia-client-example go mod init celestia-client-example ``` ### Create main.go ```go package main import ( "context" "fmt" "os" "time" "github.com/celestiaorg/celestia-node/api/client" "github.com/celestiaorg/celestia-node/blob" "github.com/celestiaorg/celestia-node/nodebuilder/p2p" "github.com/celestiaorg/go-square/v3/share" "github.com/cosmos/cosmos-sdk/crypto/keyring" ) func main() { ctx := context.Background() // Get connection details from environment daURL := os.Getenv("CELE_DA_URL") coreGRPC := os.Getenv("CELE_CORE_GRPC") daTLS := os.Getenv("CELE_DA_TLS") == "true" daToken := os.Getenv("CELE_DA_TOKEN") coreTLS := os.Getenv("CELE_CORE_TLS") == "true" coreToken := os.Getenv("CELE_CORE_TOKEN") if daURL == "" { fmt.Println("Error: Set CELE_DA_URL environment variable") fmt.Println("Example: export CELE_DA_URL=http://localhost:26658") return } // Create a new account fmt.Println("Creating account...") kr, err := client.KeyringWithNewKey(client.KeyringConfig{ KeyName: "my_key", BackendName: keyring.BackendTest, }, "./keys") if err != nil { panic(err) } // Show your address keyInfo, err := kr.Key("my_key") if err != nil { panic(err) } address, err := keyInfo.GetAddress() if err != nil { panic(err) } fmt.Printf("Your address: %s\n", address.String()) // Connect to Celestia (read-only or full client) cfg := client.Config{ ReadConfig: client.ReadConfig{ BridgeDAAddr: daURL, EnableDATLS: daTLS, }, SubmitConfig: client.SubmitConfig{ DefaultKeyName: "my_key", }, } // Add DA auth token if provided if daToken != "" { cfg.ReadConfig.DAAuthToken = daToken } // Add Core gRPC config if provided if coreGRPC != "" { network := p2p.Network("mocha-5") cfg.SubmitConfig.Network = network cfg.SubmitConfig.CoreGRPCConfig = client.CoreGRPCConfig{ Addr: coreGRPC, TLSEnabled: coreTLS, } if coreToken != "" { cfg.SubmitConfig.CoreGRPCConfig.AuthToken = coreToken } fmt.Println("Full client mode (can submit blobs)") } else { fmt.Println("Read-only mode (cannot submit blobs)") fmt.Println("To submit blobs, set CELE_CORE_GRPC environment variable") } fmt.Println("Connecting to Celestia...") c, err := client.New(ctx, cfg, kr) if err != nil { panic(err) } defer c.Close() // Check your balance balance, err := c.State.Balance(ctx) if err != nil { panic(err) } fmt.Printf("Balance: %s\n", balance.String()) // Submit a blob only if in full mode if coreGRPC != "" { // Check if account has funds before trying to submit balanceStr := balance.String() if balanceStr == "0utia" || balanceStr == "0 utia" { fmt.Println("Account has no funds. Fund this address at the Mocha faucet to submit blobs:") fmt.Printf("Address: %s\n", address.String()) fmt.Println("Faucet: https://mocha.celenium.io/faucet") } else { if err := submitAndRetrieveBlob(ctx, c); err != nil { panic(err) } } } fmt.Println("✓ Tutorial complete!") } func submitAndRetrieveBlob(ctx context.Context, c *client.Client) error { // Set timeout for network operations ctx, cancel := context.WithTimeout(ctx, time.Minute) defer cancel() // Create namespace (groups your data) ns, err := share.NewV0Namespace([]byte("tutorial")) if err != nil { return err } // Create blob with your data message := "Hello Celestia!" blobData := []byte(message) b, err := blob.NewBlob(share.ShareVersionZero, ns, blobData, nil) if err != nil { return err } // Submit to network fmt.Println("Submitting blob...") height, err := c.Blob.Submit(ctx, []*blob.Blob{b}, nil) if err != nil { return err } fmt.Printf("✓ Blob submitted at block %d\n", height) // Retrieve it back fmt.Println("Retrieving blob...") retrieved, err := c.Blob.Get(ctx, height, ns, b.Commitment) if err != nil { return err } // Verify the data retrievedData := string(retrieved.Data()) fmt.Printf("✓ Retrieved: %s\n", retrievedData) if retrievedData != message { return fmt.Errorf("data mismatch!") } fmt.Println("✓ Data verified!") return nil } ``` ### Set up your go.mod Create `go.mod` with these dependencies: ```go module celestia-client-example go 1.25.1 require ( github.com/celestiaorg/celestia-node v0.28.2-mocha github.com/celestiaorg/go-square/v3 v3.0.2 github.com/cosmos/cosmos-sdk v0.50.13 ) replace ( cosmossdk.io/x/upgrade => github.com/celestiaorg/cosmos-sdk/x/upgrade v0.2.0 github.com/cometbft/cometbft => github.com/celestiaorg/celestia-core v0.39.10 github.com/cosmos/cosmos-sdk => github.com/celestiaorg/cosmos-sdk v0.51.4 github.com/cosmos/ibc-go/v8 => github.com/celestiaorg/ibc-go/v8 v8.7.2 github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1 // broken goleveldb needs to be replaced for the cosmos-sdk and celestia-app github.com/syndtr/goleveldb => github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // celestia-core(v0.34.x): used for multiplexing abci v1 requests github.com/tendermint/tendermint => github.com/celestiaorg/celestia-core v1.55.0-tm-v0.34.35 ) replace github.com/ipfs/boxo => github.com/celestiaorg/boxo v0.29.0-fork-4 replace github.com/ipfs/go-datastore => github.com/celestiaorg/go-datastore v0.0.0-20250801131506-48a63ae531e4 ``` Then run: ```bash go mod tidy ``` ## Running the tutorial ### Set environment variables Choose your connection type: To submit blobs, you need both a DA JSON-RPC endpoint and a consensus gRPC endpoint. The public Quicknode Mocha endpoint serves both, and the full submit and retrieve flow in this guide was verified against it: `https://public-endpoint.celestia-mocha.quiknode.pro` for DA JSON-RPC and `public-endpoint.celestia-mocha.quiknode.pro:9090` for consensus gRPC. **Public endpoints (tested on Mocha):** ```bash export CELE_DA_URL=https://public-endpoint.celestia-mocha.quiknode.pro export CELE_DA_TLS=true export CELE_CORE_GRPC=public-endpoint.celestia-mocha.quiknode.pro:9090 export CELE_CORE_TLS=true ``` **Managed provider (for example Quicknode):** ```bash export CELE_DA_URL=https://your-quicknode-url.celestia-mocha.quiknode.pro/ export CELE_DA_TLS=true export CELE_CORE_GRPC=your-quicknode-url:9090 export CELE_CORE_TLS=true export CELE_CORE_TOKEN= ``` **Local bridge node + local consensus node:** ```bash export CELE_DA_URL=http://localhost:26658 export CELE_DA_TLS=false export CELE_CORE_GRPC=localhost:9090 export CELE_CORE_TLS=false ``` **Read-only mode (no blob submission):** ```bash export CELE_DA_URL=https://public-endpoint.celestia-mocha.quiknode.pro export CELE_DA_TLS=true # Don't set CELE_CORE_GRPC for read-only mode ``` ### Run the program ```bash go run main.go ``` **First run:** You'll see your account address. Fund it at [https://mocha.celenium.io/faucet](https://mocha.celenium.io/faucet). **Second run:** After funding, you'll see: ``` Creating account... Your address: celestia16k0wsej6rewd2pfh0taah35suzf3apj552q8c3 Full client mode (can submit blobs) Connecting to Celestia... Balance: 1000000utia Submitting blob... ✓ Blob submitted at block 1234567 Retrieving blob... ✓ Retrieved: Hello Celestia! ✓ Data verified! ✓ Tutorial complete! ``` **First run (unfunded account):** ``` Creating account... Your address: celestia16k0wsej6rewd2pfh0taah35suzf3apj552q8c3 Full client mode (can submit blobs) Connecting to Celestia... Balance: 0utia Account has no funds. Fund this address at the Mocha faucet to submit blobs: Address: celestia16k0wsej6rewd2pfh0taah35suzf3apj552q8c3 Faucet: https://mocha.celenium.io/faucet ✓ Tutorial complete! ``` **Read-only mode output:** ``` Creating account... Your address: celestia16k0wsej6rewd2pfh0taah35suzf3apj552q8c3 Read-only mode (cannot submit blobs) To submit blobs, set CELE_CORE_GRPC environment variable Connecting to Celestia... Balance: 1000000utia ✓ Tutorial complete! ``` ## Understanding the code ### Key components - **Keyring**: Manages your Celestia account keys - **Client**: Connects to Celestia nodes for read/write operations - **Namespace**: Groups related data together (like a folder) - **Blob**: The data structure you submit to the network - **Commitment**: A hash that uniquely identifies your blob ### Connection types | Purpose | Node type | Example URL | | ----------- | ----------------------- | --------------------------------------------- | | Read data | DA JSON-RPC | `http://localhost:26658` | | Submit data | Consensus node gRPC | `localhost:9090` | ### Read-only mode To only retrieve data (no submission), remove the `SubmitConfig` from your client configuration: ```go cfg := client.Config{ ReadConfig: client.ReadConfig{ BridgeDAAddr: daURL, }, // No SubmitConfig for read-only } ``` ## Advanced features ### Submitting multiple blobs You can submit multiple blobs in a single transaction. All blobs are included atomically at the same block height, which is useful for grouping related data together. ```go func submitMultipleBlobs(ctx context.Context, c *client.Client) error { ctx, cancel := context.WithTimeout(ctx, 2*time.Minute) defer cancel() // Create namespace ns, err := share.NewV0Namespace([]byte("tutorial")) if err != nil { return err } // Create multiple blobs (can use same namespace, or different namespaces) blob1, err := blob.NewBlob(share.ShareVersionZero, ns, []byte("First blob"), nil) if err != nil { return err } blob2, err := blob.NewBlob(share.ShareVersionZero, ns, []byte("Second blob"), nil) if err != nil { return err } blob3, err := blob.NewBlob(share.ShareVersionZero, ns, []byte("Third blob"), nil) if err != nil { return err } // Submit all blobs in a single transaction height, err := c.Blob.Submit(ctx, []*blob.Blob{blob1, blob2, blob3}, nil) if err != nil { return err } fmt.Printf("✓ All 3 blobs submitted at block %d\n", height) // Retrieve each blob using its unique commitment retrieved1, _ := c.Blob.Get(ctx, height, ns, blob1.Commitment) retrieved2, _ := c.Blob.Get(ctx, height, ns, blob2.Commitment) retrieved3, _ := c.Blob.Get(ctx, height, ns, blob3.Commitment) fmt.Printf("✓ Retrieved: %s, %s, %s\n", string(retrieved1.Data()), string(retrieved2.Data()), string(retrieved3.Data())) return nil } ``` **Key points:** - All blobs in the array are included in a single `PayForBlobs` transaction - They all appear at the same block height - Each blob can have a different namespace - Retrieve blobs individually using their namespace and commitment ### Transaction submission modes Celestia supports three transaction submission modes controlled by `TxWorkerAccounts` in your client configuration. This setting affects how transactions are queued and submitted, impacting throughput and ordering guarantees. #### Default mode (TxWorkerAccounts = 0) This is the default behavior (same as the basic tutorial). Transactions are submitted immediately without a queue: ```go cfg := client.Config{ ReadConfig: client.ReadConfig{ BridgeDAAddr: daURL, EnableDATLS: daTLS, }, SubmitConfig: client.SubmitConfig{ DefaultKeyName: "my_key", Network: p2p.Network("mocha-5"), CoreGRPCConfig: client.CoreGRPCConfig{ Addr: coreGRPC, TLSEnabled: coreTLS, }, // TxWorkerAccounts defaults to 0 (immediate submission) }, } ``` **Characteristics:** - Transactions enter the mempool immediately - No queuing or waiting for confirmations - Potential sequence number conflicts if submitting multiple transactions quickly - Same behavior as versions prior to v0.28.2 #### Queued mode (TxWorkerAccounts = 1) Enable synchronous, ordered submission by setting `TxWorkerAccounts` to `1`: ```go cfg.SubmitConfig.TxWorkerAccounts = 1 ``` **Characteristics:** - Each transaction queues until the previous one is confirmed - Preserves strict ordering of transactions based on submission time - Works with both sequential and concurrent submission patterns - Avoids sequence mismatch errors - Throughput: approximately 1 PayForBlobs transaction every other block **Example:** Submitting 5 blobs in queued mode: ```go import ( "golang.org/x/sync/errgroup" ) func submitBlobsQueued(ctx context.Context, c *client.Client) error { // Create 5 blobs blobs := make([]*blob.Blob, 5) namespaces := make([]share.Namespace, 5) commitments := make([][]byte, 5) for i := 0; i < 5; i++ { nsBytes := make([]byte, 10) copy(nsBytes, fmt.Sprintf("blob-%d", i)) ns, _ := share.NewV0Namespace(nsBytes) namespaces[i] = ns blobs[i], _ = blob.NewBlob(share.ShareVersionZero, ns, []byte(fmt.Sprintf("Data %d", i)), nil) commitments[i] = blobs[i].Commitment } heights := make([]uint64, 5) var g errgroup.Group for i := 0; i < 5; i++ { idx := i g.Go(func() error { height, err := c.Blob.Submit(ctx, []*blob.Blob{blobs[idx]}, nil) if err != nil { return err } heights[idx] = height fmt.Printf("Blob %d submitted at height %d\n", idx+1, height) return nil }) } if err := g.Wait(); err != nil { return err } // Retrieve and verify all blobs for i := 0; i < 5; i++ { retrieved, err := c.Blob.Get(ctx, heights[i], namespaces[i], commitments[i]) if err != nil { return err } fmt.Printf("✓ Blob %d retrieved: %s\n", i+1, string(retrieved.Data())) } return nil } ``` **Expected output:** ``` Blob 3 submitted at height 1234567 // First to call Submit() Blob 1 submitted at height 1234568 // Second to call Submit() Blob 5 submitted at height 1234569 // Third to call Submit() Blob 2 submitted at height 1234570 // Fourth to call Submit() Blob 4 submitted at height 1234571 // Fifth to call Submit() ✓ Blob 1 retrieved: Data 0 ✓ Blob 2 retrieved: Data 1 ✓ Blob 3 retrieved: Data 2 ✓ Blob 4 retrieved: Data 3 ✓ Blob 5 retrieved: Data 4 ``` Note: With concurrent submission, blobs may print in any order, but their heights will always reflect their submission order (first submitted = lowest height). #### Parallel mode (TxWorkerAccounts > 1) For high-throughput applications that don't require sequential ordering, enable parallel submission: ```go cfg.SubmitConfig.TxWorkerAccounts = 8 // Creates 8 parallel lanes ``` **How it works:** - Creates `TxWorkerAccounts` parallel submission lanes - Each lane is a subaccount automatically created and funded from your default account - Example: `TxWorkerAccounts = 8` creates 7 subaccounts + 1 default account = 8 parallel lanes - Enables at least 8 PayForBlobs transactions per block **Important:** To actually utilize parallel lanes, you must submit blobs concurrently (using goroutines). Each `Blob.Submit()` call blocks until the transaction is confirmed, so sequential calls will still be processed sequentially even with `TxWorkerAccounts > 1`. Concurrent submission allows multiple transactions to be processed simultaneously across different parallel lanes. **Example:** Submitting 8 blobs concurrently in parallel mode: ```go import ( "golang.org/x/sync/errgroup" ) func submitBlobsParallel(ctx context.Context, c *client.Client) error { // Create 8 blobs blobs := make([]*blob.Blob, 8) namespaces := make([]share.Namespace, 8) commitments := make([][]byte, 8) for i := 0; i < 8; i++ { nsBytes := make([]byte, 10) copy(nsBytes, fmt.Sprintf("parallel-%d", i)) ns, _ := share.NewV0Namespace(nsBytes) namespaces[i] = ns blobs[i], _ = blob.NewBlob(share.ShareVersionZero, ns, []byte(fmt.Sprintf("Parallel data %d", i)), nil) commitments[i] = blobs[i].Commitment } heights := make([]uint64, 8) var g errgroup.Group for i := 0; i < 8; i++ { idx := i g.Go(func() error { height, err := c.Blob.Submit(ctx, []*blob.Blob{blobs[idx]}, nil) if err != nil { return err } heights[idx] = height fmt.Printf("Blob %d submitted at height %d\n", idx+1, height) return nil }) } if err := g.Wait(); err != nil { return err } // Retrieve and verify all blobs for i := 0; i < 8; i++ { retrieved, err := c.Blob.Get(ctx, heights[i], namespaces[i], commitments[i]) if err != nil { return err } fmt.Printf("✓ Blob %d retrieved: %s\n", i+1, string(retrieved.Data())) } return nil } ``` **Expected output (unordered):** ``` Blob 1 submitted at height 1234567 Blob 2 submitted at height 1234567 // Same block! Blob 3 submitted at height 1234568 Blob 4 submitted at height 1234567 // Same block as 1 and 2! Blob 5 submitted at height 1234568 Blob 6 submitted at height 1234568 Blob 7 submitted at height 1234569 Blob 8 submitted at height 1234568 ✓ Blob 1 retrieved: Parallel data 0 ✓ Blob 2 retrieved: Parallel data 1 ✓ Blob 3 retrieved: Parallel data 2 ✓ Blob 4 retrieved: Parallel data 3 ✓ Blob 5 retrieved: Parallel data 4 ✓ Blob 6 retrieved: Parallel data 5 ✓ Blob 7 retrieved: Parallel data 6 ✓ Blob 8 retrieved: Parallel data 7 ``` **Important considerations:** **Ordering**: Parallel submission does NOT guarantee transaction ordering. Blobs may be included in blocks in a different order than submitted. **Default account only**: Queued and parallel submission modes always use your default account (`DefaultKeyName`). If you specify a different account in `TxConfig` (via `WithKeyName` or `WithSignerAddress`), it will be ignored and the default account will be used instead. **Retrieving blobs from parallel submission:** Since you don't know which subaccount submitted each blob, retrieve them using namespace, height, and commitment: ```go // Store these when submitting height, err := c.Blob.Submit(ctx, []*blob.Blob{myBlob}, nil) commitment := myBlob.Commitment namespace := myBlob.Namespace() // Later, retrieve using stored values retrieved, err := c.Blob.Get(ctx, height, namespace, commitment) ``` **Subaccount management:** - Subaccounts are automatically created and funded from your default account - They are named `parallel-worker-1`, `parallel-worker-2`, etc. in your keyring - Subaccounts are reused across node restarts if `TxWorkerAccounts` value remains the same - If you decrease `TxWorkerAccounts`, only the first N workers are used - If you increase `TxWorkerAccounts`, additional workers are created #### Comparison table | Mode | TxWorkerAccounts | Ordering | Throughput | Use case | | -------- | ---------------- | -------------- | ---------------- | ---------------------------------------- | | Default | 0 | Not guaranteed | Immediate | Simple applications, single transactions | | Queued | 1 | Guaranteed | ~1 tx per block | Applications requiring strict ordering | | Parallel | >1 | Not guaranteed | ≥N txs per block | High-throughput, unordered workflows | ## Next steps - **Production**: Use `keyring.BackendFile` instead of `keyring.BackendTest` - **Security**: Enable TLS with authentication tokens for production - **Advanced**: Read the [full client documentation](https://github.com/celestiaorg/celestia-node/blob/main/api/client#readme) ## Troubleshooting Common errors and solutions: ### Connection errors **`failed to initialize [share|header|blob] client`** - Check that your `CELE_DA_URL` is correct and accessible - Verify the bridge node is running and reachable - Ensure TLS settings match your node configuration **`couldn't connect to core endpoint`** - Verify your `CELE_CORE_GRPC` address is correct - Check that the consensus node is running - Ensure firewall rules allow the connection ### Configuration errors **`default key name should not be empty`** - Ensure `DefaultKeyName` is set in your `SubmitConfig` **`keyring is nil`** - Pass a valid keyring to `client.New()` (cannot be `nil`) ### Blob submission errors **`blob: not found`** - The blob doesn't exist at the specified height/namespace/commitment - Verify the height, namespace, and commitment are correct **`not allowed namespace ... were used to build the blob`** - The namespace is reserved or invalid - Use `share.NewV0Namespace()` with valid user namespaces **`account for signer ... not found`** - The account has not been funded yet - Fund your account at the [Mocha faucet](/operate/networks/mocha-testnet#mocha-testnet-faucet) **`failed to submit blobs due to insufficient gas price`** - The estimated or configured gas price is too low - Either increase `MaxGasPrice` in `TxConfig` or let the client estimate - Check network congestion (gas prices may be elevated) **`context deadline exceeded`** - Network timeout occurred - Increase the context timeout: `context.WithTimeout(ctx, 5*time.Minute)` - Check network connectivity to the node --- Title: Rust client URL: https://docs.celestia.org/build/post-retrieve-blob/client/rust.md Source: app/build/post-retrieve-blob/client/rust/page.mdx --- # Rust client The [Lumina Rust client](https://github.com/celestiaorg/lumina/tree/main/client) provides a high-level API for interacting with a Celestia node over RPC and gRPC. It builds on top of the lower-level `celestia-rpc` and `celestia-grpc` crates and exposes a unified `Client` that supports both **read-only** and **submit** modes. In read-only mode, the client connects to a node via RPC (and optionally gRPC) to query headers, blobs, and state. In submit mode, it additionally uses gRPC and a local signer to build, sign, and broadcast transactions such as transfers and PayForBlobs. The crate re-exports common Celestia types (namespaces, blobs, app versions, etc.) and is designed to be the easiest way for Rust applications to integrate with Celestia nodes for data retrieval, blob submission, and general chain interaction. ([lib.rs][1], [docs.rs][2]) [1]: https://lib.rs/crates/celestia-client "celestia-client, in Rust // Lib.rs" [2]: https://docs.rs/celestia-client/latest/celestia_client/ "celestia-client, in Rust // Docs.rs" --- Title: Submit and retrieve a Fibre blob on Mocha URL: https://docs.celestia.org/build/post-retrieve-blob/fibre.md Source: app/build/post-retrieve-blob/fibre/page.mdx --- # Submit and retrieve a Fibre blob on Mocha Fibre stores blob shards on validator-operated servers and settles payment on-chain with `MsgPayForFibre`. This walkthrough deposits testnet TIA into escrow, submits a namespaced payload, waits for settlement, and downloads the original bytes. Use `fibre.Submit` for this first test: it waits for transaction confirmation. Fibre is separate from the [blob/transaction client flow](/build/post-retrieve-blob/overview) that uses `blob.Submit` and PayForBlob. Fibre retrieval uses a `blob_id`, rather than the height, namespace and commitment tuple used by `blob.Get`. ## Prepare a Mocha node You need: - A Mocha light or bridge node with Fibre support. The examples use celestia-node `v0.34.3-mocha` and a core endpoint running celestia-app `v10.4.0-mocha` on `mocha-5`. Follow [Install celestia-node](/operate/data-availability/install-celestia-node). - Bash, `curl`, `jq` and Python 3 for the commands below. - A local signer funded with Mocha testnet TIA. - Enough reachable Fibre providers to collect signatures representing the required two-thirds of voting power. Check the [Mocha Fibre dashboard](https://testnet.celestia.valopers.com/fibre). App v10 activation alone does not establish provider readiness. Check `celestia version` before starting. Older node releases without the `fibre` API cannot run these requests. The [released Node API reference](/build/rpc/node-api) covers these methods when you select `v0.34.3-mocha`. Select the specification that matches your node version. If you already have a synced Mocha light or bridge node with a Fibre-capable core endpoint, use its store, key and RPC address. Otherwise, initialise a separate light-node store: ```bash export FIBRE_HOME="$HOME/.celestia-fibre-mocha-guide" celestia light init --p2p.network mocha --node.store "$FIBRE_HOME" ``` Initialisation creates a signer. Keep the recovery phrase private. If another node is running on this machine, stop it or configure different P2P listen ports before starting this node. For faster initial sync, see [Syncing from a trusted hash](/operate/maintenance/trusted-hash-recovery), including its checkpoint trust assumption. Start the node in one terminal and leave it running: ```bash celestia light start --p2p.network mocha --node.store "$FIBRE_HOME" \ --core.ip grpc-mocha.pops.one \ --core.port 443 --core.tls \ --rpc.addr 127.0.0.1 --rpc.port 27658 ``` This core endpoint is a public community service and may rate-limit requests. For repeated or large tests, use your own Fibre-capable core endpoint or a provider with suitable limits. Fibre discovers validator upload/download hosts from the network; the core address is not a Fibre storage server address. ## Fund the signer and authenticate In a second Bash terminal, enable pipeline failure reporting and set the same store and local RPC address: ```bash set -o pipefail export FIBRE_HOME="$HOME/.celestia-fibre-mocha-guide" export NODE_RPC=http://127.0.0.1:27658 export KEY_NAME=my_celes_key celestia state account-address --node.store "$FIBRE_HOME" --url "$NODE_RPC" ``` Fund the returned address using the [Mocha faucet](https://mocha.celenium.io/faucet). Check the wallet balance: ```bash celestia state balance --node.store "$FIBRE_HOME" --url "$NODE_RPC" ``` With celestia-node v0.34.2-mocha, restart the node after funding a signer that was unfunded when the node started. Otherwise, `fibre.Deposit` can panic during gas estimation. Stop the node with Ctrl+C in the first terminal, then run the same start command again. Wait for header sync to catch up before submitting: ```bash celestia header sync-state --node.store "$FIBRE_HOME" --url "$NODE_RPC" ``` Check that the reported `height` has reached `to_height` and the initial sync has a non-zero `end` timestamp. The node should continue following new headers. Generate a token that permits writes. It also permits the read calls used here: ```bash export AUTH_TOKEN=$(celestia light auth write \ --p2p.network mocha --node.store "$FIBRE_HOME") export SIGNER=$(celestia state account-address \ --node.store "$FIBRE_HOME" --url "$NODE_RPC" | jq -er '.result') rpc() { curl --fail-with-body --silent --show-error \ --connect-timeout 10 --max-time 180 \ -H "Authorization: Bearer $AUTH_TOKEN" \ -H 'Content-Type: application/json' \ --data-binary @- "$NODE_RPC" } ``` The examples select `my_celes_key`, the default key created by initialisation. To use another key, start the node with `--keyring.keyname ` and set `KEY_NAME` to that name. `SIGNER` must be that key's public address. The key must exist in this node's keyring; an address alone does not give the node signing access. See [Node key management](/operate/keys-wallets/celestia-node-key). ## Query and deposit escrow Wallet funds pay transaction gas. Fibre escrow pays for blob storage. Keep some TIA in the wallet when depositing; escrow cannot pay transaction gas. Amounts use `utia`, where 1 TIA is 1,000,000 utia. Query this signer's escrow: ```bash jq -nc --arg signer "$SIGNER" \ '{jsonrpc:"2.0",id:1,method:"fibre.QueryEscrowAccount",params:[$signer]}' | rpc ``` For a new signer, `escrow account not found for signer` is expected. Deposit 2 testnet TIA for the small example below, after confirming the wallet holds more than 2 TIA: ```bash jq -nc --arg key "$KEY_NAME" \ '{jsonrpc:"2.0",id:2,method:"fibre.Deposit", params:[{denom:"utia",amount:"2000000"},{key_name:$key}]}' \ | rpc > deposit.json && jq -es ' length == 1 and (.[0] | type == "object" and (has("error") | not) and has("result") and .result == null) ' deposit.json ``` Success returns `{"jsonrpc":"2.0","id":2,"result":null}`, not a transaction receipt. Query escrow again and confirm the deposit before proceeding: ```bash jq -nc --arg signer "$SIGNER" \ '{jsonrpc:"2.0",id:3,method:"fibre.QueryEscrowAccount",params:[$signer]}' \ | rpc > escrow.json && jq -es ' length == 1 and (.[0] | type == "object" and (has("error") | not) and (.result | type == "object" and (.available_balance | type == "object" and .denom == "utia" and (.amount | type == "string" and test("^[0-9]+$"))))) ' escrow.json && jq '.result.available_balance' escrow.json ``` A newly deposited account has these balance fields: ```json { "balance": {"denom": "utia", "amount": "2000000"}, "available_balance": {"denom": "utia", "amount": "2000000"} } ``` These are fields inside `result`, alongside `signer`. Pending withdrawals reduce `available_balance` before they reduce the total `balance`. ## Submit and save the receipt Both the full 29-byte namespace and the payload are base64 strings in JSON. Create a version-0 namespace with the ID `fibre-demo` and a small file: ```bash printf 'Hello, Fibre!\n' > original.bin NS=$(python3 -c 'import base64; print(base64.b64encode(bytes(19)+b"fibre-demo").decode())') DATA=$(python3 -c 'import base64; print(base64.b64encode(open("original.bin","rb").read()).decode())') jq -nc --arg ns "$NS" --arg data "$DATA" --arg key "$KEY_NAME" \ '{jsonrpc:"2.0",id:4,method:"fibre.Submit",params:[$ns,$data,{key_name:$key}]}' \ | rpc > submit.json && jq -es ' length == 1 and (.[0] | type == "object" and (has("error") | not) and (.result | type == "object" and (.height | type == "number" and . > 0 and . == floor) and (.tx_hash | type == "string" and length > 0) and (.blob_id | type == "string" and length > 0))) ' submit.json && jq '.result | {blob_id,height,tx_hash}' submit.json > receipt.json && cat receipt.json ``` Stop if any command reports an error or a validation prints `false`. The `&&` chains run each next command only after the previous command succeeds. The checks require exactly one JSON response with the expected result fields, including when the response is empty. A failed submission or validation leaves any existing `receipt.json` unchanged; do not use an old receipt for this attempt. An empty response or timeout does not prove that payment failed. Reconcile settlement as described below before retrying. On success, `Submit` has uploaded the shards, collected signatures and confirmed the payment transaction. Save all three receipt fields. For example, the validated small-blob run returned: ```json { "blob_id": "AMGy8xgg3+lxgxQxMedurPYBoj8Q9V1eZWH05AEyeNTk", "height": 1111896, "tx_hash": "26E4B81DC2E88F41301F89FD36B7852B049653CFC7F03DF7153AEBDA5F3F49BE" } ``` Your transaction hash and height will differ. The full response also contains `validator_signatures` and `payment_promise`. Download your own freshly submitted blob rather than relying on the historical example remaining stored. ## Download and verify the bytes Pass the returned `blob_id` unchanged. In JSON-RPC it is base64, whereas the native Go client's `BlobID.String()` prints hexadecimal. A payment promise hash shown by an explorer is a separate identifier, not the download blob ID. ```bash BLOB_ID=$(jq -er '.blob_id' receipt.json) jq -nc --arg id "$BLOB_ID" \ '{jsonrpc:"2.0",id:5,method:"fibre.Download",params:[$id]}' \ | rpc > download.json python3 - <<'PY' import base64, hashlib, json response = json.load(open('download.json')) if 'error' in response: raise SystemExit(response['error']) data = base64.b64decode(response['result']['data'], validate=True) if data != open('original.bin', 'rb').read(): raise SystemExit('Downloaded bytes differ from original') open('downloaded.bin', 'wb').write(data) print('Verified identical bytes; SHA-256:', hashlib.sha256(data).hexdigest()) PY ``` The response's `result` is `{"data":"SGVsbG8sIEZpYnJlIQo="}` for this payload. The expected SHA-256 is: ```text f0e7fdccb71e36e867930a1f6f0b55bf5cdb5d0d8eca369a8675a7c1cec64cba ``` ## Larger blobs and the native client There are two different size limits in the tested releases: | Path | Limit | |---|---| | Fibre version-0 payload | 128 MiB minus the 5-byte header: 134,217,723 bytes | | Node HTTP JSON-RPC request | 16 MiB including JSON and base64, leaving slightly less than 12 MiB for payload | The [node RPC server](https://github.com/celestiaorg/celestia-node/blob/v0.34.2-mocha/api/rpc/server.go) limits the request body independently of the [Fibre protocol](https://github.com/celestiaorg/celestia-app/blob/v10.2.0-mocha/fibre/protocol_params.go). For larger blobs, use the native celestia-app [Fibre client](https://github.com/celestiaorg/celestia-app/blob/v10.2.0-mocha/fibre/client.go). Its upload sends shards directly to validators; only the payment transaction goes through core. See [`fibre.Put`](https://github.com/celestiaorg/celestia-app/blob/v10.2.0-mocha/fibre/client_put.go) for a combined upload/settlement example and [`tools/fibre-txsim`](https://github.com/celestiaorg/celestia-app/blob/v10.2.0-mocha/tools/fibre-txsim/main.go) for the separate upload, transaction and download steps. Storage charges use the encoded, padded size, not just the original file's length. The release's [payment calculation](https://github.com/celestiaorg/celestia-app/blob/v10.2.0-mocha/x/fibre/types/gas.go) explains the charge. The observations below are test results, not permanent prices or performance guarantees. Budget escrow and transaction gas separately. ### Verified Mocha results Tests on 25 September 2026 used celestia-node v0.34.2-mocha for JSON-RPC and celestia-app v10.2.0-mocha for the native client. Each successful run confirmed settlement and verified downloaded bytes against the original payload and hash. | Payload | Path | Settlement height | Escrow charge, excluding gas | |---|---|---|---| | 14 bytes | JSON-RPC | [1,111,896](https://testnet.celestia.valopers.com/transactions/26E4B81DC2E88F41301F89FD36B7852B049653CFC7F03DF7153AEBDA5F3F49BE) | 0.695 testnet TIA | | 10 MiB | JSON-RPC | [1,112,086](https://testnet.celestia.valopers.com/transactions/B937331E897D90D6B50AD6F7630AF681F970D2577D1D3463A067F1D386A8832C) | 2.495 testnet TIA | | 128 MiB minus 5 bytes | Native Go | [1,113,071](https://testnet.celestia.valopers.com/transactions/ADD4C5190131D0AFB55AF3341B347700B2ADEC2B128FAF3C7CA06495852C5C16) | 23.69 testnet TIA | The maximum-size run's SHA-256 was `53a0a70e69fac696d73438aada6cfa989c5a36c90c3164525f262fed2775721f`. Its blob ID was `AJ+0/lcm8YgL/06EFKHMnnMaQfJp/ChDQskMk7rkd8FQ`; the [Tensile record](https://tensile-mocha.huginn.tech/blob/?tx=ADD4C5190131D0AFB55AF3341B347700B2ADEC2B128FAF3C7CA06495852C5C16) links to the settlement transaction. Tensile accepts transaction hashes, blob IDs (base64 or hexadecimal), and payment promise hashes. If an identifier matches multiple records, it shows all matches. The native test trusted the selected core endpoint for validator state; the light-node path uses locally verified headers. ## Retention and withdrawals Fibre storage is time-limited. Query current Mocha parameters before planning retention or a withdrawal: ```bash curl --fail --silent --show-error \ https://api-mocha.pops.one/fibre/v1/params | jq '.params' ``` `shard_retention` determines the minimum shard-retention period; `payment_promise_timeout` bounds the settlement promise. Keep your own copy of the data: a confirmed payment is not a permanent storage guarantee. `fibre.Withdraw` requests a withdrawal, reducing available escrow. The chain processes it after `withdrawal_delay`; it is not an immediate wallet transfer. Use `fibre.PendingWithdrawals` with the signer's address to inspect the amount and `available_timestamp`. Do not reuse escrow committed to outstanding payment promises, including uploads whose settlement outcome is still unknown. ## Asynchronous uploads and recovery `fibre.Upload` returns after upload and starts settlement in the background. In v0.34.2-mocha, background settlement errors are logged. An upload result is not proof of confirmed payment. Use `Submit` for the first walkthrough. A timeout or rate limit while confirming a transaction does not prove that it failed. In the maximum-size test, the core endpoint returned HTTP 429 during confirmation even though the transaction had settled. A second endpoint confirmed execution code `0` and the matching Fibre event. Before resubmitting, check the transaction hash, node logs and chain state through a working endpoint or explorer. Native clients should retain the broadcast transaction hash before waiting for confirmation. If the client returns no hash, inspect the signer's transactions and match the namespace and commitment. Signed promises can also be charged through the timeout path after an upload failure; blindly retrying can create another payment obligation. ## Troubleshoot the walkthrough | Symptom | Check | |---|---| | `fibre client is not available` | Configure a Fibre-capable core endpoint, then restart the node. | | Missing Fibre services or method not found | Check both the node release and the core endpoint's app version and exposed services. | | Unfunded signer or insufficient escrow | Verify the selected key/address; fund the wallet and deposit into that signer's escrow. Retain wallet funds for gas. | | Deposit gas-estimation panic after faucet funding | Restart v0.34.2-mocha after the signer is funded, then query escrow before retrying. | | Header syncing or historical state unavailable | Wait for header sync and use a core endpoint that serves the required state. | | Not enough voting power, unreachable providers or TLS failures | Check registered/reachable provider stake and client logs. Some stored shards may be retrievable even when signature quorum was not reached. | | HTTP 429 or uncertain settlement | Back off or use another endpoint; reconcile payment status before resubmitting. | | Large JSON-RPC request rejected | Account for base64 and JSON overhead, or use the native client. | | Download fails after retention expires | Recover from your own stored copy. The on-chain receipt does not contain the blob bytes. | --- Title: Overview to posting and retrieving blobs on Celestia URL: https://docs.celestia.org/build/post-retrieve-blob/overview.md Source: app/build/post-retrieve-blob/overview/page.mdx --- # Overview to posting and retrieving blobs on Celestia This section will show you how to post and retrieve blobs on Celestia using the transaction client in Golang and Rust. There are two transaction clients available: | Option | What you need | Endpoints to set | Guides | | ---------- | ----------------------------------- | --------------------------------- | --------------------------------------------------------- | | **Golang** | Local keyring handled by the client | **2** — DA bridge RPC + Core gRPC | [Go client tutorial](/build/post-retrieve-blob/client/go) | | **Rust** | Local keyring handled by the client | **2** — DA bridge RPC + Core gRPC | [Rust client](/build/post-retrieve-blob/client/rust) | For Fibre storage on Mocha, follow [Submit and retrieve a Fibre blob](/build/post-retrieve-blob/fibre). That guide covers escrow, on-chain settlement, retrieval and the separate Fibre size limits. --- Title: About Private Blockspace URL: https://docs.celestia.org/build/private-blockspace/about.md Source: app/build/private-blockspace/about/page.mdx --- # About Private Blockspace The highest-stakes onchain markets—including perpetual exchanges, order books, and institutional rails—depend on information that cannot be public. Positions, balances, liquidations, and routing logic are inherently sensitive. Yet pushing that data offchain reintroduces trusted operators and weakens the core promise of being onchain: **independent auditing, verifiability, and safe exits when it matters most.** **Private Blockspace** is Celestia’s approach to solving this problem: keep sensitive state **confidential**, while still making it **publicly accountable**. Private Blockspace enables networks to publish **encrypted state to Celestia**, allowing anyone to verify data availability and protocol commitments **without revealing the underlying contents**. The result is **private systems with public verifiability guarantees**—fault-resistant, auditable, and designed to support safe exit mechanisms. At a high level, Private Blockspace adds an encryption + proof layer between your application and Celestia’s data availability layer. This layer is implemented as the **Private Blockspace Proxy**: a lightweight service that encrypts, proves, and routes data **without modifying existing Celestia integrations**. ## Submitting a blob The Private Blockspace Proxy acts as an intermediary between your JSON-RPC client and the Celestia network. When you submit a blob: 1. The proxy encrypts the data. 2. The proxy generates a proof inside a zkVM attesting to correct encryption and any configured “anchors” about the plaintext. 3. The proxy stores the job result in a local database and returns an acknowledgement while processing continues. 4. Once the proof completes, the result is cached so identical submissions can return immediately. 5. The proxy submits the verifiably encrypted blob to Celestia via `blob.Submit`. From the client’s perspective, posting encrypted data feels like a single RPC call, while the proxy handles encryption, verifiability, and coordination with Celestia behind the scenes. ```mermaid sequenceDiagram participant JSON RPC Client participant Proxy participant Celestia Node JSON RPC Client->>+Proxy: blob.Submit(blobs, options)
{AUTH_TOKEN in header} Proxy->>Proxy: Job Processing...
{If no DB entry, start new zkVM Job} Proxy->>-JSON RPC Client: Response{"Call back"} Proxy->>Proxy: ...Job runs to completion... JSON RPC Client->>+Proxy: blob.Submit(blobs, options)
{AUTH_TOKEN in header} Proxy->>Proxy: Query Job DB
Done!
{Job Result cached} Proxy->>Celestia Node: blob.Submit(V. Encrypt. blobs, options) Celestia Node->>Proxy: Response{Inclusion Block Height} Proxy->>-JSON RPC Client: Response{Inclusion Block Height} ``` ## Retrieving a blob When retrieving a blob, the proxy behaves as a transparent relay: 1. The client calls `blob.Get(height, namespace, commitment)`. 2. The proxy forwards the request to a Celestia node. 3. The proxy receives the raw blob response. 4. The proxy attempts to deserialize and decrypt using the configured encryption key. If the blob was encrypted through the proxy, decryption succeeds and the proxy returns the original plaintext bytes. If it was not, the proxy passes the response through unchanged. This ensures compatibility with both encrypted and unencrypted blobs, so existing clients can adopt Private Blockspace incrementally. ```mermaid sequenceDiagram participant JSON RPC Client participant Proxy participant Celestia Node JSON RPC Client->>+Proxy: blob.Get(height, namespace, commitment) Proxy->>Celestia Node: Celestia Node->>Proxy: Response{namespace,data,
share_version,commitment,index} Proxy->>Proxy: *Try* deserialize & decrypt Proxy->>-JSON RPC Client: *Success* -> Response{...,decrypted bytes,...} Proxy->>JSON RPC Client: *Failure* -> ``` ## Verifiable Encryption (VE) With normal encryption, ciphertext should be indistinguishable from random noise. That property is what keeps data private—but it also makes it difficult to prove _anything_ about encrypted data without decrypting it. Private Blockspace uses **Verifiable Encryption (VE)** to bridge this gap. VE enables proofs of _select properties_ of fully encrypted data **without decryption**. For example, a system can prove statements like: - “This encrypted blob contains a Merkle proof whose root is `0xabc123…`” - “This ciphertext was produced using the expected algorithm, key format, and nonce rules” - “The plaintext hashes to a specific commitment” This is accomplished by running encryption inside a zkVM, producing a proof that encryption was executed correctly while also exposing application-defined “anchors” (such as hashes or commitment checks) that remain safe to reveal. **Outcome:** anyone can verify availability and correctness constraints, while only authorized parties can decrypt the underlying contents. ## Key exchange and management strategies A critical design question in Private Blockspace is key management: > If keys are withheld, then the data is effectively withheld. Private Blockspace is designed to support different key exchange and reconstruction strategies depending on your application requirements and threat model. ### Account-centric model A proposed account-centric model enforces that **all account state is published and available**, while also being encrypted such that only the intended party (or parties) can decrypt. Key properties of this approach: - **User-defined encryption keys:** users define keys for encrypting their own account state, ensuring they can always decrypt their data and enabling forward secrecy. - **Conditional selective disclosure:** users can allow decryption by specific parties using standard public key cryptography, key exchange protocols, and/or threshold schemes. - **User-initiated protocol progression:** applications can allow users to progress the protocol themselves by proving correct state transitions onchain, enabling “forced” state updates such as withdrawals. This model is designed to support systems that remain private during normal operation, while still enabling safe exits and recovery paths under application-defined conditions. ## Use cases Private Blockspace is designed for applications where **privacy is required**, but **public accountability cannot be sacrificed**. ### Accountable offchain exchanges Operators of offchain or hybrid exchanges can keep internal state private while still being required (by protocol design) to prove state availability and commitments publicly. This improves fault tolerance and auditability without forcing users to trust an opaque operator for safe exits. **In production: Hibachi** Hibachi is the first independent deployment using Private Blockspace for a fast perps exchange. Hibachi publishes verifiably encrypted exchange state to Celestia, keeping balances and positions private while making data availability and correctness publicly verifiable. ### Trust-minimized data marketplaces Private Blockspace can also support trust-minimized private data markets: - sellers publish verifiably encrypted data to Celestia - buyers verify availability and integrity before payment—without seeing the plaintext - payment is enforced only once availability is proven This shifts trust away from intermediaries and toward verification, producing private exchange workflows that are auditable and fault-resistant by design. ## References and further reading - [Private Blockspace Proxy repo on GitHub](https://github.com/celestiaorg/private-blockspace-proxy/) - [Verifiable Encryption (VE) in depth](https://github.com/celestiaorg/private-blockspace-proxy/blob/main/doc/verifiable_encryption.md) - [Forum post: Account-centric model](https://forum.celestia.org/t/account-user-centric-private-blockspace/2155) --- Title: Private blockspace quickstart URL: https://docs.celestia.org/build/private-blockspace/quickstart.md Source: app/build/private-blockspace/quickstart/page.mdx --- # Private blockspace quickstart Private blockspace encrypts your blob data before it’s posted to Celestia using a lightweight proxy. In this quickstart, you’ll use hosted Celestia nodes (like Quicknode) instead of running your own. ## Get your node credentials To use Private Blockspace, you’ll need access to a hosted **Celestia Data Availability (DA) + Consensus Node**. The easiest option is [Quicknode’s Celestia service](https://www.quicknode.com/docs/celestia), which provides ready-to-use mainnet and Mocha testnet endpoints. They offer a free 30-day trial, which is enough for this quickstart. 1. Visit the [Quicknode Celestia dashboard](https://www.quicknode.com/docs/celestia) and log in (or create a free account). 2. Click **Create Endpoint**, then select: - **Chain:** `Celestia` - **Network:** `Mainnet` or `Mocha` 3. Copy the generated endpoint URL (it looks like this): `https://celestia-mocha.quiknode.pro//` 4. Copy the token from your endpoint URL (this is your **write / read token**). 5. Save both the **URL** and **token** — you’ll add them to your `.env` file next. ## Create your `.env` Download the repo’s `example.env` and save it as `.env`. Edit **only** the following items. | Key | What to do | | --- | --- | | `PBS_DB_PATH` | Absolute path for local proxy data (e.g. `/Users/you/dev/pbs-db`) | | `ENCRYPTION_KEY` | 32-byte key — see command below | | `CELESTIA_NODE_RPC` | Your Quicknode HTTPS endpoint (includes your token) | | `CELESTIA_CORE_GRPC` | Same host + `:9090` (no token in path) | | `CELESTIA_NODE_WRITE_TOKEN` | Your Quicknode token | | `CELESTIA_SIGNING_KEY` | 32-byte private key for your signer (funded on Mocha) | | `TLS_CERTS_PATH` / `TLS_KEY_PATH` | Path to your local TLS cert + key (see next step) | | `CELESTIA_NETWORK` etc. | Keep defaults; ensure all paths are absolute | ### Generate an `ENCRYPTION_KEY` (ChaCha20, 32 bytes) This is a random 256-bit symmetric key, **not** a wallet key. ```bash openssl rand -hex 32 # or python3 -c "import secrets; print(secrets.token_hex(32))" ``` Paste the value (no quotes) as your `ENCRYPTION_KEY`. ## Generate TLS certificates The proxy requires TLS certificates (even for local testing). ```bash mkdir -p tls openssl req -x509 -nodes -newkey rsa:2048 -keyout tls/tls.key -out tls/tls.crt -days 365 -subj "/CN=localhost" ``` Then mount that folder when running Docker and set: ``` TLS_CERTS_PATH=/app/tls/tls.crt TLS_KEY_PATH=/app/tls/tls.key ``` Without valid certs, the proxy will exit with `TLS_CERTS_PATH required: NotPresent`. ## Fund your signer Your `CELESTIA_SIGNING_KEY` corresponds to a Mocha testnet address. That address must exist and hold some test TIA. **Get funds from the [Celestia Mocha faucet](https://faucet.celestia-mocha.com).** You can verify your signer address in the proxy logs it prints the address when starting. ## Run the proxy container **Apple Silicon (M1/M2/M3)** The published image is `amd64` only — run it under emulation: ```bash docker pull --platform=linux/amd64 ghcr.io/celestiaorg/pda-proxy:latest mkdir -p "$PBS_DB_PATH" docker run --name pda-proxy --rm -it --platform=linux/amd64 --env-file ./.env -v "$PBS_DB_PATH:$PBS_DB_PATH" -v "./tls:/app/tls" -p 26657:26657 ghcr.io/celestiaorg/pda-proxy:latest ``` **Intel/AMD Linux or other amd64 hosts** ```bash docker pull ghcr.io/celestiaorg/pda-proxy:latest mkdir -p "$PBS_DB_PATH" docker run --name pda-proxy --rm -it --env-file ./.env -v "$PBS_DB_PATH:$PBS_DB_PATH" -v "./tls:/app/tls" -p 26657:26657 ghcr.io/celestiaorg/pda-proxy:latest ``` ### Verify it’s running Check logs: ```bash docker logs -f pda-proxy ``` Or test status: ```bash curl -k -sS -X POST -H "Content-Type: application/json" -H "Authorization: Bearer YOUR_TOKEN" --data '{"jsonrpc":"2.0","id":1,"method":"status","params":[]}' https://127.0.0.1:26657 | jq . ``` On Apple Silicon, keep `--platform=linux/amd64` until a native arm64 image exists. ## Send a blob Try a small encrypted payload: ```bash curl -k -sS \ -H "Content-Type: application/json" \ -H "Authorization: Bearer YOUR_TOKEN" \ -X POST --data '{ "id": 1, "jsonrpc": "2.0", "method": "blob.Submit", "params": [[ { "namespace": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAMJ/xGlNMdE=", "data": "SSBMb3ZlIEJpZyBCbG9icw==", "share_version": 0, "commitment": "aHlbp+J9yub6hw/uhK6dP8hBLR2mFy78XNRRdLf2794=", "index": -1 } ], {}] }' https://127.0.0.1:26657 | jq . ``` The proxy will: - Encrypt your blob - Submit to Celestia - Return a `height` and `tx hash` If the response includes `"result": { "height": "…" }`, you’re set. Jump to **Verify your blob** with that height. If you see `"[pda-proxy] Verifiable encryption processing..."`, the proxy queued the job. Two quick options: **Option A — resend once** Sometimes it finishes fast and you’ll get the height on the next call. **Option B — find the height** Either tail logs: ```bash docker logs -f pda-proxy | egrep -i 'submit|height|commit|error' ``` Or poll a small window around the tip for your namespace: ```bash LATEST=$( curl -k -sS \ -H "Content-Type: application/json" \ -H "Authorization: Bearer YOUR_TOKEN" \ -X POST --data '{"jsonrpc":"2.0","id":1,"method":"status","params":[]}' \ https://127.0.0.1:26657 | jq -r '.result.sync_info.latest_block_height' ) for h in $(seq $((LATEST-2)) $((LATEST+2))); do RES=$( curl -k -sS \ -H "Content-Type: application/json" \ -H "Authorization: Bearer YOUR_TOKEN" \ -X POST --data "{ \"id\":1, \"jsonrpc\":\"2.0\", \"method\":\"blob.GetAll\", \"params\":[ $h, [ \"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAMJ/xGlNMdE=\" ] ] }" \ https://127.0.0.1:26657 ) if echo "$RES" | jq -e '.result | length > 0' >/dev/null; then echo "Height $h" echo "$RES" | jq . fi done ``` Copy the `commitment` you see there and use it with `blob.Get`. ## Verify your blob Now, fetch the same blob through your proxy using the following command with `HEIGHT` replaced with your actual height: ```bash curl -k -sS -H "Content-Type: application/json" -H "Authorization: Bearer YOUR_TOKEN" -X POST --data "{ \"id\":1, \"jsonrpc\":\"2.0\", \"method\":\"blob.GetAll\", \"params\":[HEIGHT,[\"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAMJ/xGlNMdE=\"]] }" https://127.0.0.1:26657 | jq . ``` You’ll see a `commitment` and your decrypted data: ```json { "commitment": "…base64…", "data": "SSBMb3ZlIEJpZyBCbG9icw==", "namespace": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAMJ/xGlNMdE=" } ``` **Decode base64 to plaintext** When you retrieve a blob, the `data` field is base64. To see the plaintext: **macOS/Linux** ```bash echo "SSBMb3ZlIEJpZyBCbG9icw==" | base64 -d ``` **Python** ```bash python3 - <<'PY' import base64 print(base64.b64decode("SSBMb3ZlIEJpZyBCbG9icw==").decode()) PY ``` **Node.js** ```bash node -e 'console.log(Buffer.from("SSBMb3ZlIEJpZyBCbG9icw==","base64").toString())' ``` ## Troubleshooting | Error message | Cause | Fix | | --- | --- | --- | | `TLS_CERTS_PATH required` | Missing or commented-out cert vars | Generate certs (see above). | | `account not found` | Unfunded signer | Use [Mocha faucet](https://faucet.celestia-mocha.com). | | `blob: not found` | Wrong commitment | Run `blob.GetAll` to find the real one. | | `grpc-status header missing` | Invalid gRPC URL | Must be `https://:9090`, no token. | ## ✅ You’re done You’re running **private blockspace** end-to-end using hosted infrastructure. ✅ No local Celestia node ✅ Fully containerized ✅ Encrypted data posted to Celestia --- Title: Client Libraries URL: https://docs.celestia.org/build/rpc/clients.md Source: app/build/rpc/clients/page.mdx --- # Client Libraries Celestia Node API can be accessed through various client libraries in different programming languages. ## Official Clients ### Golang Client Official Go implementation of the Celestia Node RPC client and Transaction Client - **Repository**: [celestiaorg/celestia-node @ /api/client](https://github.com/celestiaorg/celestia-node/tree/main/api/client) - **Tutorial**: [Go Client Tutorial](/build/post-retrieve-blob/client/go/) - Learn how to submit and retrieve blobs without running your own node ### Rust Client Official Rust implementation of the Celestia Node RPC client (Lumina) - **Repository**: [celestiaorg/lumina](https://github.com/celestiaorg/lumina) - **Tutorial**: [Rust Client Tutorial](/build/post-retrieve-blob/client/rust/) - Submit and retrieve blobs using the Lumina Rust client ## Community Clients ### Python Client Community-maintained Python client for the Celestia Node RPC API - **Repository**: [grumpyp/celestia-node-client-py](https://github.com/grumpyp/celestia-node-client-py) ### TypeScript Client Community-maintained TypeScript/JavaScript client for the Celestia Node RPC API - **Repository**: [ashishbhintade/cntsc](https://github.com/ashishbhintade/cntsc) ## Getting Started Each client library provides methods to interact with the Celestia Node RPC API. Choose the language that best fits your project requirements. For API reference and method documentation, see the [Node API](/build/rpc/node-api) section. --- Title: Community services URL: https://docs.celestia.org/build/rpc/community-services.md Source: app/build/rpc/community-services/page.mdx --- # Community services Community providers offer paid RPC reads, indexed data APIs, and Model Context Protocol (MCP) connections for Celestia Mainnet Beta. These services are operated by their respective providers. Follow their documentation for current pricing, supported methods, and client compatibility. ## NODERS paid archive RPC [NODERS archive RPC](https://noders.services/mainnet/celestia/archive-rpc/) provides paid reads from a Celestia archive consensus node through CometBFT RPC. Paid requests use the x402 payment protocol with TIA. This is a consensus RPC service; for blob retrieval through the DA node API, see [archival DA RPC endpoints](/operate/networks/mainnet-beta#archival-da-rpc-endpoints). Check connectivity with the free `status` method: ```bash curl -s https://celestia-archive-rpc.noders.services/status ``` Paid methods return HTTP `402 Payment Required` until payment is supplied. To make paid calls, follow the provider's [setup guide](https://noders.services/mainnet/celestia/archive-rpc/#quick-start) for `x402-celestia-rpc-payer`, fund its wallet with TIA, and configure spending limits. Each paid call also incurs a network transaction fee. The provider's guide covers current prices and payment troubleshooting. ## NODERS MCP server The [NODERS MCP server](https://noders.services/mainnet/celestia/mcp/) lets AI clients query indexed Mainnet Beta data, including validators, delegations, staking metrics, account balances, and transactions. Its tools are read-only. In a client that supports remote MCP servers, add this URL with the **Streamable HTTP** transport: ```text https://celestia-mcp.noders.services/mcp ``` After connecting, ask the client to list five bonded Celestia validators and include their addresses. If the connection fails, check that the URL ends in `/mcp` and the client uses Streamable HTTP. See the [connection guide](https://noders.services/mainnet/celestia/mcp/) for client-specific setup and local installation options. ## Celenium paid API [Celenium's paid API](https://www.mppscan.com/server/ac886177d1fcc678779495d697f5a5000fca922337cb70c8bed1a5d182c2181a) provides REST access to indexed Celestia data, including blocks, transactions, blobs, namespaces, validators, rollups, and network statistics. It supports pay-per-request access through the Machine Payments Protocol (MPP), without an account or API key. Use an MPP-compatible client with `https://mpp.celenium.io`. The [OpenAPI specification](https://mpp.celenium.io/openapi.json) lists supported routes and payment requirements; the MPPscan listing includes an AgentCash setup command. Requests to paid routes without payment return HTTP `402 Payment Required`. --- Title: Node API URL: https://docs.celestia.org/build/rpc/node-api.md Source: app/build/rpc/node-api/page.mdx --- # Node API The Celestia Node API is the collection of RPC methods that can be used to interact with the services provided by Celestia data availability nodes. Node API uses auth tokens to control access to this API. ## Fibre on Mocha Select `v0.34.3-mocha` in the version selector below for the released Fibre API, or download its [OpenRPC specification](/specs/openrpc-v0.34.3-mocha.json). The [Mocha Fibre walkthrough](/build/post-retrieve-blob/fibre) covers node setup, escrow funding, submission and retrieval, including tested request encodings and the JSON-RPC size limit. The Mainnet Beta `v0.34.3` specification does not include Fibre. The Mocha specification also includes `blob.SubscribeFromStartHeight`, which replays blobs for a namespace from a start height, then streams new blobs. ## celestia-node v0.31.3 breaking changes Starting with celestia-node v0.31.3: - The `fraud` RPC namespace was removed. Calls to `fraud.Get` and `fraud.Subscribe` are no longer supported. - The `type` field returned by `node.Info` is a string such as `"Bridge"` or `"Light"` instead of an integer. - RPC request bodies are limited to 16 MiB. Larger requests are rejected. - In the Go API, `blob.Commitment.String()` returns a hexadecimal string instead of raw bytes. This does not change the JSON encoding of commitment fields returned by RPC methods. See the [celestia-node v0.31.3 release notes](https://github.com/celestiaorg/celestia-node/releases/tag/v0.31.3) for the complete list of changes. --- Title: Select a Celestia account in integrations URL: https://docs.celestia.org/build/stacks/account-selection.md Source: app/build/stacks/account-selection/page.mdx --- # Select a Celestia account in integrations ## Overview One DA node can submit blobs for multiple execution environments, but each blob submission still needs a specific Celestia signer. Use the OpenRPC options on `blob.Submit` to select the account per request. ## OpenRPC methods to use - `blob.Submit(blobs, options)`: `options.key_name` or `options.signer_address` selects the signer for that submission. - `state.BalanceForAddress(addr)`: checks the balance for the selected signer before submission. - `state.AccountAddress()`: returns the node's default signer, useful for fallback behavior. Both account selectors refer to a key that is already available in the Celestia node's keyring. `signer_address` does not provide an external signer. If both `key_name` and `signer_address` are set, `signer_address` takes precedence. If neither is set, the node uses its default signer. ## JSON-RPC examples Submit using a key name: ```json { "jsonrpc": "2.0", "id": 1, "method": "blob.Submit", "params": [ [ { "namespace": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAMJ/xGlNMdE=", "data": "aGVsbG8gY2VsZXN0aWE=", "share_version": 0 } ], { "key_name": "rollup-a" } ] } ``` Submit using an explicit signer address: ```json { "jsonrpc": "2.0", "id": 1, "method": "blob.Submit", "params": [ [ { "namespace": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAMJ/xGlNMdE=", "data": "aGVsbG8gY2VsZXN0aWE=", "share_version": 0 } ], { "signer_address": "celestia1..." } ] } ``` Pre-flight balance check for a signer: ```json { "jsonrpc": "2.0", "id": 1, "method": "state.BalanceForAddress", "params": ["celestia1..."] } ``` ## Integration notes Not every integration forwards `blob.Submit` options. Use the configuration supported by the integration: | Integration | How to select the Celestia account | | --- | --- | | Direct Node API client | Pass `key_name` or `signer_address` in the `blob.Submit` options. | | OP Stack (`op-alt-da`) | The DA server signs submissions directly. Set `key_name` under `[celestia.signer.local]` in the config file or use `--celestia.tx-client.key-name`. This selects one signer for the DA server, not a signer per Node API request. | | Arbitrum (`nitro-das-celestia`) | The sidecar does not currently set a signer in `blob.Submit` options, so the Celestia node's default signer is used. Start the node with `--keyring.keyname` to select it. | | Rollkit / ev-node | Set `--evnode.da.signing_addresses` to a comma-separated list of funded addresses in the Celestia node's keyring. ev-node rotates through the addresses for submissions. | RollApps and Sovereign SDK deployments can use different Celestia DA adapters. Check whether the adapter forwards `blob.Submit` options. If it does not, configure the signer in the adapter or use the Celestia node's default signer. ## Key management and node defaults If your integration uses only the node default signer, set that default account at node startup: ```bash celestia start --p2p.network --keyring.keyname ``` For wallet/key setup, see [Create a wallet with celestia-node](/operate/keys-wallets/celestia-node-key). --- Title: Arbitrum Nitro with Celestia DA URL: https://docs.celestia.org/build/stacks/nitro-das-server.md Source: app/build/stacks/nitro-das-server/page.mdx --- # Arbitrum Nitro with Celestia DA ## Overview The Arbitrum Nitro integration with Celestia enables Orbit chains to use Celestia for data availability instead of Arbitrum AnyTrust. The implementation uses a sidecar architecture where a separate `celestia-server` handles Celestia-specific operations via RPC. ## How it works Nitro's batch poster coordinates with the Celestia DAS server to store batch data: 1. **Batch posting**: The [`MaybePostSequencerBatch`](https://github.com/celestiaorg/nitro/blob/v3.6.8/arbnode/batch_poster.go#L1675) method checks if a DAS writer is configured and acquires a lock before posting 2. **Data storage**: The DAS writer calls the Celestia server's [`Store`](https://github.com/celestiaorg/nitro-das-celestia/blob/main/daserver/celestia.go#L302) method, which: - Creates a blob from the batch data - Submits it to Celestia with retry logic and gas price adjustment - Returns a `BlobPointer` containing block height, share indices, and data commitments 3. **Verification dependency**: The dispute-verification design uses Blobstream (default: SP1 Blobstream) to confirm batch availability on Celestia through the hash oracle trick. > **Blobstream service status:** As of September 2026, the Succinct-operated SP1 Blobstream deployments are no longer maintained and do not receive new commitments. Do not rely on them for new batch commitments. Establish a working Blobstream verification path before relying on this integration for disputes. ## Key features - **Sidecar architecture**: Processing logic handled by separate `celestia-server`, keeping Nitro nodes lightweight - **Fallback support**: Native fallback mechanism with configurable `da-preference` parameter (e.g., `["celestia", "anytrust"]`) - **Preimage oracle**: Validators populate preimage mappings with Celestia hashes for fraud proof support - **Robust submission**: Automatic retry with gas price adjustment for network congestion ## Resources - [Nitro fork repository](https://github.com/celestiaorg/nitro) - [Celestia DAS server](https://github.com/celestiaorg/nitro-das-celestia) - [Select a Celestia account in integrations](/build/stacks/account-selection) --- Title: How to run op-alt-da with AWS KMS URL: https://docs.celestia.org/build/stacks/op-alt-da/aws-kms-guide.md Source: app/build/stacks/op-alt-da/aws-kms-guide/page.mdx --- # How to run op-alt-da with AWS KMS ## Overview This guide walks through running [op-alt-da](https://github.com/celestiaorg/op-alt-da) (da-server) using a Celestia key stored in Amazon Web Services (AWS) key management service (KMS). You will use the localstack, a mock of AWS, to learn how to run the da-server. Once you've done this, you can log in to AWS and use your private key in [prod](#production-aws). ## Prerequisites - Docker - Go 1.21+ - A Celestia RPC endpoint from [Quicknode](https://quicknode.com/) ## Getting started ## Setup environment 1. Install awscli: ```bash brew install awscli ``` 2. Clone and build op-alt-da ([v0.12.0](https://github.com/celestiaorg/op-alt-da/releases/tag/v0.12.0)+): ```bash git clone https://github.com/celestiaorg/op-alt-da.git && cd op-alt-da make ``` ## Localstack 1. Set mock AWS credentials (required even for localstack): ```bash export AWS_ACCESS_KEY_ID=test export AWS_SECRET_ACCESS_KEY=test export AWS_DEFAULT_REGION=us-east-1 ``` 2. Start localstack with KMS enabled: ```bash docker run -d \ --name localstack \ -p 4566:4566 \ -e SERVICES=kms \ localstack/localstack ``` 3. Verify it's running: ```bash aws --endpoint-url=http://localhost:4566 kms list-keys # should return: { "Keys": [] } ``` ## Create KMS key Create a KMS key and alias: ```bash KEY_ID=$(aws --endpoint-url=http://localhost:4566 kms create-key \ --key-spec ECC_SECG_P256K1 \ --key-usage SIGN_VERIFY \ --query 'KeyMetadata.KeyId' --output text) aws --endpoint-url=http://localhost:4566 kms create-alias \ --alias-name alias/op-alt-da/celestia_key --target-key-id $KEY_ID ``` ## Configure op-alt-da 1. Copy config example into `config.toml`: ```bash cp config.toml.example config.toml ``` 2. Edit `config.toml` with the configs you gathered in the setup: ```toml [celestia] namespace = "000000000000000000000000000000000000000000000000000000acfe" keyring_backend = "awskms" default_key_name = "alias/op-alt-da/celestia_key" bridge_addr = "https://your-endpoint.celestia-mocha.quiknode.pro/your-token/" bridge_auth_token = "" bridge_tls_enabled = true core_grpc_addr = "your-endpoint.celestia-mocha.quiknode.pro:9090" core_grpc_auth_token = "your-token" core_grpc_tls_enabled = true [celestia.awskms] region = "us-east-1" endpoint = "http://localhost:4566" ``` Note: In v0.12.0+, the `default_key_name` must include the full alias path (e.g., `alias/op-alt-da/celestia_key`). ## Run the DA server 1. Run the op-alt-da server: ```bash AWS_ACCESS_KEY_ID=test AWS_SECRET_ACCESS_KEY=test AWS_DEFAULT_REGION=us-east-1 ./bin/da-server -config config.toml ``` Where this is what the successful start looks like: ```bash INFO [01-20|14:53:56.130] Initializing Stateless Alt-DA server... INFO [01-20|14:53:56.131] Using celestia storage url=https://your-endpoint.celestia-mocha.quiknode.pro/your-token/ INFO [01-20|14:53:56.179] Immediate submission mode (default, no queue) INFO [01-20|14:53:56.992] Starting HTTP server addr=127.0.0.1:3100 INFO [01-20|14:53:56.992] Starting metrics server addr=:6060 INFO [01-20|14:53:57.004] Started DA Server ``` 2. Test a POST request to get your Celestia address: ```bash curl -s -X POST http://127.0.0.1:3100/put \ -H "Content-Type: application/octet-stream" \ -d "hello celestia" -o /dev/null ``` The first request will fail because the account has no funds. Check the server logs for the error message which reveals your Celestia address: ``` submission failed: account for signer celestia1rwuklcs36jm6wqxk8w9cx9vyja93856nz3sdlf not found ``` 3. Fund your address at the faucet: https://mocha.celenium.io/faucet Copy the `celestia1...` address from the error message and request testnet tokens. 4. Retry the POST request: ```bash curl -s -X POST http://127.0.0.1:3100/put \ -H "Content-Type: application/octet-stream" \ -d "hello celestia" -o /dev/null ``` A successful POST shows in the server logs: ```bash INFO [01-20|14:54:15.342] celestia: blob successfully submitted id=74a5940000000000677e645183667f4d9efe506226fd0dd0b70a4144c8fd05c0aa68407ccf886507 INFO [01-20|14:54:15.342] Blob submitted successfully commitment=010c74a5940000000000677e645183667f4d9efe506226fd0dd0b70a4144c8fd05c0aa68407ccf886507 size=14 duration=11.5436025s ``` Check your transaction on [Celenium](https://mocha.celenium.io) by navigating to `https://mocha.celenium.io/address/YOUR_CELESTIA_ADDRESS`. 5. Verify your key and alias: ```bash AWS_ACCESS_KEY_ID=test AWS_SECRET_ACCESS_KEY=test AWS_DEFAULT_REGION=us-east-1 aws --endpoint-url=http://localhost:4566 kms list-aliases ``` You should see your alias pointing to the key: ```bash { "Aliases": [ { "AliasName": "alias/op-alt-da/celestia_key", "AliasArn": "arn:aws:kms:us-east-1:000000000000:alias/op-alt-da/celestia_key", "TargetKeyId": "79b26b15-0635-4b3c-aad0-0ab4406e6754" } ] } ``` Congratulations, you're set up! You should be able to see your blob has been posted successfully using op-alt-da and AWS KMS. Now you can run your OP Stack rollup with AWS KMS, using the Celestia key in AWS. ## Production (AWS) For production AWS KMS usage: 1. Create a KMS keypair in AWS with key spec `ECC_SECG_P256K1` and key usage `SIGN_VERIFY`. 2. Create an alias for your key (e.g., `alias/op-alt-da/my_celes_key`). Per AWS requirements, the alias name must start with `alias/`. 3. Configure your IAM policy with the minimum required permissions: ```json { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "kms:GetPublicKey", "kms:Sign" ], "Resource": "arn:aws:kms:REGION:ACCOUNT_ID:key/KEY_ID" } ] } ``` 4. Update your `config.toml`: ```toml [celestia] keyring_backend = "awskms" default_key_name = "alias/op-alt-da/my_celes_key" [celestia.awskms] region = "us-east-2" endpoint = "" ``` Note: Leave `endpoint` empty for production AWS. The `default_key_name` must include the full alias path (e.g., `alias/my_celes_key` or `alias/op-alt-da/my_celes_key`). --- Title: Introduction URL: https://docs.celestia.org/build/stacks/op-alt-da/introduction.md Source: app/build/stacks/op-alt-da/introduction/page.mdx --- # Introduction ## Overview The OP Stack integration with Celestia enables rollups to post transaction data to Celestia instead of Ethereum, while still settling on Ethereum. This reduces costs and improves scalability by using Celestia as a modular data availability layer. ## How it works The `op-batcher` component batches rollup blocks and submits them to Celestia rather than posting calldata to Ethereum: 1. **Data submission**: The batcher calls [`publishTxToL1`](https://github.com/ethereum-optimism/optimism/blob/develop/op-batcher/batcher/driver.go#L931) which retrieves batch data from the channel manager 2. **Celestia storage**: For Celestia-enabled chains, [`celestia_storage.Put`](https://github.com/celestiaorg/op-alt-da/blob/main/celestia_storage.go#L200) submits the blob to Celestia using a configured namespace 3. **Commitment recording**: A commitment identifier (version byte + blob ID) is generated and recorded on Ethereum 4. **Data retrieval**: When `op-node` needs data, it reads the commitment from Ethereum, then fetches the actual blob from Celestia ## Celestia fork differences The [Celestia fork](https://github.com/celestiaorg/optimism/blob/celestia-develop/op-batcher/batcher/driver.go#L1092) of OP Stack includes: - Direct blob submission to Celestia with namespace-based organization - Fallback mechanisms for DA failures (supporting both blob data and calldata alternatives) - Commitment-based references using Celestia block heights ## Resources - [op-alt-da repository](https://github.com/celestiaorg/op-alt-da) - [Celestia OP Stack fork](https://github.com/celestiaorg/optimism) - [Select a Celestia account in integrations](/build/stacks/account-selection) --- Title: Celestia docs URL: https://docs.celestia.org/index.md Source: app/page.mdx --- # Celestia docs Build with modular data availability. Celestia is a modular data availability network. Rollups publish transaction data to Celestia while choosing their own execution and settlement layers. Use these docs to learn how data availability works, post and retrieve blobs, and run a node on Mainnet Beta or the Mocha testnet. [Start building](/build/post-retrieve-blob/overview/) [Explore the API](/build/rpc/node-api/) [Learn](/learn/celestia-101/data-availability/): Understand modular blockchains and Celestia's architecture, including data availability sampling and how rollups use blobspace. [Build](/build/post-retrieve-blob/overview/): Post and retrieve your first blob with Go and Rust transaction clients. Follow the guides for signer setup, funding, and testnet examples. [Operate](/operate/getting-started/overview/): Choose a node type, check hardware requirements, and install Celestia software. Find guides for maintenance, monitoring, and troubleshooting. [Node API](/build/rpc/node-api/): Explore Celestia Node JSON-RPC methods, authentication, and client libraries. Download versioned OpenRPC specifications from the API reference. --- Title: Security and audits URL: https://docs.celestia.org/learn/audits.md Source: app/learn/audits/page.mdx --- # Security and audits ## Security disclosures The security disclosure contact is [security@celestia.org](mailto:security@celestia.org). Do not report vulnerabilities in public issues or discussions. Follow the [Celestia security policy](https://github.com/celestiaorg/.github/blob/main/SECURITY.md): submit a private security advisory in the affected repository, or email the security disclosure contact if private reporting is unavailable. ## Audit reports This page provides a comprehensive list of audits conducted on various Celestia software, including OP Stack, Nitro, celestia-app, Blobstream, and more. Each audit is linked to its respective report. | Software | Auditor | Link | | -------------------------- | ---------------- | -------------------------------------------------------------------------------------------------------------------------- | | OP Stack | OtterSec | [Link](/audits/Celestia_OP_Stack_Audit.pdf) | | Nitro | OtterSec | [Link](https://github.com/celestiaorg/nitro/blob/celestia-v2.3.3/audits/celestia/arbitrum_nitro_celestia_audit_report.pdf) | | v2 celestia-app Lemongrass | Informal Systems | [Link](https://github.com/celestiaorg/celestia-app/blob/main/docs/audit/informal-systems-v2.pdf) | | v3 celestia-app | Informal Systems | [Link](https://github.com/celestiaorg/celestia-app/blob/main/docs/audit/informal-systems-authored-blobs.pdf) | | Blobstream SP1 | OtterSec | [Link](/audits/SP1_Blobstream_Ottersec_Audit.pdf) | | Blobstream SP1 | Multiple | [Link](https://github.com/succinctlabs/sp1/tree/dev/audits) | | Blobstream X | Informal Systems | [Link](/audits/Blobstream_X-Informal_Systems_Audit.pdf) | | Blobstream X | OtterSec | [Link](/audits/Blobstream_X-OtterSec_Audit.pdf) | | Blobstream X | Veridise | [Link](/audits/Blobstream_X-Veridise_Audit.pdf) | | Blobstream X | Zellic | [Link](/audits/Blobstream_X-Zellic_Audit.pdf) | | Shwap | OtterSec | [Link](/audits/celestia_shwap_audit_final.pdf) | | High throughput recovery | Informal Systems | [Link](https://github.com/celestiaorg/celestia-app/blob/main/docs/audit/informal-systems-recovery.pdf) | --- Title: Blobstream (legacy) URL: https://docs.celestia.org/learn/blobstream.md Source: app/learn/blobstream/page.mdx --- # Blobstream (legacy) Blobstream was a data availability attestation bridge that let EVM chains verify that data was published to Celestia. It relayed commitments to Celestia data roots to a smart contract on the target EVM chain, where rollup contracts could verify inclusion proofs against them. > **Legacy notice:** As of September 2026, the Succinct-operated SP1 Blobstream deployments are no longer maintained and do not receive new commitments, and Celenium no longer offers its Blobstream explorer. The integration and operator guides that previously lived in these docs have been removed. ## What remains - [Blobstream proof queries (legacy)](/build/blobstream/proof-queries) documents how to query inclusion proofs from a Celestia consensus node and how they map to the Blobstream contract format. - [Audits](/learn/audits) lists the historical Blobstream X and SP1 Blobstream audit reports. - The [blobstream-contracts](https://github.com/celestiaorg/blobstream-contracts) and [sp1-blobstream](https://github.com/succinctlabs/sp1-blobstream) repositories remain available on GitHub. If you depend on Blobstream for dispute verification, such as with [Arbitrum Nitro with Celestia DA](/build/stacks/nitro-das-server), you must operate or source your own Blobstream verification path. --- Title: Data availability FAQ URL: https://docs.celestia.org/learn/celestia-101/data-availability-faq.md Source: app/learn/celestia-101/data-availability-faq/page.mdx --- # Data availability FAQ # What is data availability? Data availability is about proving that a block's transactions have been published to the network. In most chains this means downloading all transaction data for a new block; in Celestia, light nodes can answer this question via DAS without full downloads. ![Data availability](/img/learn/data-availability-faq/Data-availability.png) ## What is the data availability problem? If a block producer withholds data for a proposed block (a data withholding attack), other nodes cannot update state or verify the chain. The risk varies by architecture—for example, rollups and validiums are especially sensitive. ## How do nodes verify data availability in Celestia? Full nodes can download entire blocks as usual. Light nodes leverage DAS: they request random shares with Merkle proofs from the extended data matrix. See [Data availability sampling](#data-availability-sampling-das) for details. ## What is data availability sampling? DAS lets light nodes make repeated random sampling requests for small portions of a block. As more samples succeed, confidence that the full block is available rises (e.g., to 99%+). A simple analogy is coin flips: enough successful flips (samples) give high confidence the data exists. ## What security assumptions does DAS rely on? - Enough light nodes sample for the given block size so an honest bridge node can reconstruct the full block from their collected shares. - Light nodes connect to at least one honest bridge node to receive fraud proofs for incorrectly erasure-coded blocks; eclipse attacks can break this assumption. ## Why is block reconstruction necessary for security? Blocks are erasure coded; malicious encoders could extend data incorrectly. Bridge nodes need the full block to produce fraud proofs of bad encoding. If only light nodes receive data and bridge nodes cannot reconstruct the block, the network could miss invalid encoding. ## What is data storage and how is it different? Data storage concerns keeping and retrieving historical transaction data. The security assumption for storage is 1-of-N honesty—only one honest keeper of history is needed—while data availability is about new blocks being publishable and verifiable. ![Data storage](/img/learn/data-availability-faq/Data-storage.png) ## What problems arise around data storage? If historical data cannot be retrieved, users may lose access to transaction history and nodes cannot sync from genesis. This is a retrieval problem, not an availability problem. ## Where does blockchain state fit into this? State (balances, contract storage, validator set) is a snapshot derived from transaction data. Its growth poses different challenges than DA or data retrieval. ## Why doesn’t Celestia incentivize storing historical data? Guaranteeing permanent storage is not the DA layer’s role, and storage needs only 1-of-N honest providers. Celestia focuses on securely publishing data; third parties store history based on their incentives. ## Who might store historical data? - Block explorers serving past transactions - Indexers with query APIs - Applications or rollups needing history for processes - Users who want their own transaction history ## How can chains improve data retrievability? - Reward nodes for storing and serving data (e.g., storage networks like [Filecoin](https://filecoin.io)). - Publish transaction data to an incentivized storage layer. - Offer paid archival access or snapshots so others can sync from known good data. --- Title: Celestia's data availability layer URL: https://docs.celestia.org/learn/celestia-101/data-availability.md Source: app/learn/celestia-101/data-availability/page.mdx --- # Celestia's data availability layer Data availability (DA) answers a simple question: **has this block's data been published and can it be downloaded? In other words, is the data available?** When a node receives a new block, it must be able to retrieve the associated transaction data; otherwise, the chain can stall or be exploited. Celestia provides a modular DA layer so light nodes can verify availability efficiently without downloading whole blocks. ## tl;dr 1. Celestia is a modular data availability network: it orders blobs and keeps them available while execution and settlement live on layers above. 2. It scales by decoupling execution from consensus and using data availability sampling (DAS) so light nodes can verify availability without downloading whole blocks; more light nodes sampling safely unlocks larger block sizes. 3. Namespaced Merkle trees (NMTs) let each app fetch only its own namespaced data and prove availability. 4. Block producers erasure-code blobs into a $2k \times 2k$ matrix, commit to every row and column, and put that root in the header. 5. Light nodes sample within a rolling window; archival nodes (or providers) keep older data retrievable. Celestia is a data availability (DA) layer that provides a scalable solution to the [data availability problem](https://coinmarketcap.com/academy/article/what-is-data-availability). Due to the permissionless nature of the blockchain networks, a DA layer must provide a mechanism for the execution and settlement layers to check in a trust-minimized way whether transaction data is indeed available. Two key features of Celestia's DA layer are [data availability sampling](https://blog.celestia.org/celestia-mvp-release-data-availability-sampling-light-clients) (DAS) and [Namespaced Merkle trees](https://github.com/celestiaorg/nmt) (NMTs). Both features are novel blockchain scaling solutions: DAS enables light nodes to verify data availability without needing to download an entire block; NMTs enable execution and settlement layers on Celestia to download transactions that are only relevant to them. ## Data availability sampling (DAS) In general, light nodes download only block headers that contain commitments (_i.e._, Merkle roots) of the block data (_i.e._, the list of transactions). To make DAS possible, Celestia uses a 2-dimensional Reed-Solomon encoding scheme to encode the block data: every block data is split into $k \times k$ shares, arranged in a $k \times k$ matrix, and extended with parity data into a $2k \times 2k$ extended matrix by applying multiple times Reed-Solomon encoding. Then, $4k$ separate Merkle roots are computed for the rows and columns of the extended matrix; the Merkle root of these Merkle roots is used as the block data commitment in the block header. ![2D Reed-Soloman (RS) Encoding](/img/learn/reed-solomon-encoding.png) To verify that the data is available, Celestia light nodes are sampling the $2k \times 2k$ data shares. Every light node randomly chooses a set of unique coordinates in the extended matrix and queries bridge nodes for the data shares and the corresponding Merkle proofs at those coordinates. If light nodes receive a valid response for each sampling query, then there is a [high probability guarantee](https://github.com/celestiaorg/celestia-node/issues/805#issuecomment-1150081075) that the whole block's data is available. Additionally, every received data share with a correct Merkle proof is gossiped to the network. As a result, as long as the Celestia light nodes are sampling together enough data shares (_i.e._, at least $k \times k$ unique shares), the full block can be recovered by honest bridge nodes. For more details on DAS, take a look at the [original paper](https://arxiv.org/abs/1809.09044). ### Scalability DAS enables Celestia to scale the DA layer. DAS can be performed by resource-limited light nodes since each light node only samples a small portion of the block data. The more light nodes there are in the network, the more data they can collectively download and store. This means that increasing the number of light nodes performing DAS allows for larger blocks (_i.e._, with more transactions), while still keeping DAS feasible for resource-limited light nodes. However, in order to validate block headers, Celestia light nodes need to download the $4k$ intermediate Merkle roots. For a block data size of $n^2$ bytes, this means that every light node must download $O(n)$ bytes. Therefore, any improvement in the bandwidth capacity of Celestia light nodes has a quadratic effect on the throughput of Celestia's DA layer. ### Fraud proofs of incorrectly extended data The requirement of downloading the $4k$ intermediate Merkle roots is a consequence of using a 2-dimensional Reed-Solomon encoding scheme. Alternatively, DAS could be designed with a standard (_i.e._, 1-dimensional) Reed-Solomon encoding, where the original data is split into $k$ shares and extended with $k$ additional shares of parity data. Since the block data commitment is the Merkle root of the $2k$ resulting data shares, light nodes no longer need to download $O(n)$ bytes to validate block headers. The downside of the standard Reed-Solomon encoding is dealing with malicious block producers that generate the extended data incorrectly. This is possible as **Celestia does not require a majority of the consensus (_i.e._, block producers) to be honest to guarantee data availability.** Thus, if the extended data is invalid, the original data might not be recoverable, even if the light nodes are sampling sufficient unique shares (_i.e._, at least $k$ for a standard encoding and $k \times k$ for a 2-dimensional encoding). As a solution, _Fraud Proofs of Incorrectly Generated Extended Data_ enable light nodes to reject blocks with invalid extended data. Such proofs require reconstructing the encoding and verifying the mismatch. With standard Reed-Solomon encoding, this entails downloading the original data, _i.e._, _n²_ bytes. Contrastingly, with 2-dimensional Reed-Solomon encoding, only $O(n)$ bytes are required as it is sufficient to verify only one row or one column of the extended matrix. ## Namespaced Merkle trees (NMTs) Celestia partitions the block data into multiple namespaces, one for every application (e.g., rollup) using the DA layer. As a result, every application needs to download only its own data and can ignore the data of other applications. For this to work, the DA layer must be able to prove that the provided data is complete, _i.e._, all the data for a given namespace is returned. To this end, Celestia is using Namespaced Merkle trees (NMTs). An NMT is a Merkle tree with the leaves ordered by the namespace identifiers and the hash function modified so that every node in the tree includes the range of namespaces of all its descendants. The following figure shows an example of an NMT with height three (_i.e._, eight data shares). The data is partitioned into three namespaces. ![Namespaced Merkle Tree](/img/learn/nmt.png) When an application requests the data for namespace 2, the DA layer must provide the data shares `D3`, `D4`, `D5`, and `D6` and the nodes `N2`, `N8` and `N7` as proof (note that the application already has the root `N14` from the block header). As a result, the application is able to check that the provided data is part of the block data. Furthermore, the application can verify that all the data for namespace 2 was provided. If the DA layer provides for example only the data shares `D4` and `D5`, it must also provide nodes `N12` and `N11` as proofs. However, the application can identify that the data is incomplete by checking the namespace range of the two nodes, _i.e._, both `N12` and `N11` have descendants part of namespace 2. For more details on NMTs, refer to the [original paper](https://arxiv.org/abs/1905.09274). ## Building a PoS blockchain for DA ### Providing data availability The Celestia DA layer consists of a PoS blockchain. Celestia is dubbing this blockchain as the [celestia-app](https://github.com/celestiaorg/celestia-app), an application that provides transactions to facilitate the DA layer and is built using [Cosmos SDK](https://docs.cosmos.network/sdk/v0.53). The following figure shows the main components of celestia-app. ![Main components of celestia-app](/img/learn/celestia-app.png) celestia-app is built on top of [celestia-core](https://github.com/celestiaorg/celestia-core), a modified version of the [Tendermint consensus algorithm](https://arxiv.org/abs/1807.04938). Among the more important changes to vanilla Tendermint, celestia-core: - Enables the erasure coding of block data (using the [2-dimensional Reed-Solomon encoding scheme](https://github.com/celestiaorg/rsmt2d)). - Replaces the regular Merkle tree used by Tendermint to store block data with a [Namespaced Merkle tree](https://github.com/celestiaorg/nmt) that enables the above layers (_i.e._, execution and settlement) to only download the needed data (for more details, see the section below describing use cases). For more details on the changes to Tendermint, take a look at the [ADRs](https://github.com/celestiaorg/celestia-core/tree/v0.34.x-celestia/docs/celestia-architecture). Notice that celestia-core nodes are still using the Tendermint p2p network. Similarly to Tendermint, celestia-core is connected to the application layer (_i.e._, the state machine) by [ABCI++](https://github.com/tendermint/tendermint/tree/master/spec/abci%2B%2B), a major evolution of [ABCI](https://github.com/tendermint/tendermint/tree/master/spec/abci) (Application Blockchain Interface). The celestia-app state machine is necessary to execute the PoS logic and to enable the governance of the DA layer. However, the celestia-app is data-agnostic -- the state machine neither validates nor stores the data that is made available by the celestia-app. ## Monolithic vs. modular blockchains Blockchains instantiate [replicated state machines](https://dl.acm.org/doi/abs/10.1145/98163.98167): the nodes in a permissionless distributed network apply an ordered sequence of deterministic transactions to an initial state resulting in a common final state. In other words, this means that nodes in a network all follow the same set of rules (_i.e._, an ordered sequence of transactions) to go from a starting point (_i.e._, an initial state) to an ending point (_i.e._, a common final state). This process ensures that all nodes in the network agree on the final state of the blockchain, even though they operate independently. This means blockchains require the following four functions: - **Execution** entails executing transactions that update the state correctly. Thus, execution must ensure that only valid transactions are executed, _i.e._, transactions that result in valid state machine transitions. - **Settlement** entails an environment for execution layers to verify proofs, resolve fraud disputes, and bridge between other execution layers. - **Consensus** entails agreeing on the order of the transactions. - **Data Availability** (DA) entails making the transaction data available. Note that execution, settlement, and consensus require DA. Traditional blockchains, _i.e._ _monolithic blockchains_, implement all four functions together in a single base consensus layer. The problem with monolithic blockchains is that the consensus layer must perform numerous different tasks, and it cannot be optimized for only one of these functions. As a result, the monolithic paradigm limits the throughput of the system. ![Modular VS Monolithic](/img/learn/monolithic-modular.png) As a solution, modular blockchains decouple these functions among multiple specialized layers as part of a modular stack. Due to the flexibility that specialization provides, there are many possibilities in which that stack can be arranged. For example, one such arrangement is the separation of the four functions into three specialized layers. The base layer consists of DA and consensus and thus, is referred to as the Consensus and DA layer (or for brevity, the DA layer), while both settlement and execution are moved on top in their own layers. As a result, every layer can be specialized to optimally perform only its function, and thus, increase the throughput of the system. Furthermore, this modular paradigm enables multiple execution layers, _i.e._, [rollups](https://vitalik.eth.limo/general/2021/01/05/rollup.html), to use the same settlement and DA layers. --- Title: Data, dashboards, and analytics URL: https://docs.celestia.org/learn/celestia-101/resources.md Source: app/learn/celestia-101/resources/page.mdx --- # Data, dashboards, and analytics A collection of useful tools, dashboards, and analytics platforms for exploring the Celestia network. ## Useful links 1. Learn category of celestia.org: https://celestia.org/learn/ 2. Celestia glossary: https://celestia.org/glossary/ 3. Celestia-app specifications: https://celestiaorg.github.io/celestia-app/ 4. Awesome-celestia repo: https://github.com/celestiaorg/awesome-celestia/ ## Data analytics & dashboards | Resource | Description | URL | | ----------------- | ------------------------------------------------------------ | ------------------------------------------------------------------------------ | | **Celenium** | Blockchain explorer and analytics platform for Celestia | [celenium.io](https://celenium.io/) | | **Celestia Data** | Comprehensive analytics and metrics for the Celestia network | [celestiadata.com](https://celestiadata.com/) | | **L2 Beat** | Data availability tracking and metrics by L2BEAT | [l2beat.com](https://l2beat.com/data-availability/projects/celestia/no-bridge) | | **ProbeLab** | Network monitoring and topology analytics for Celestia | [probelab.io](https://probelab.io/celestia/) | ## Bridge & node data | Resource | Description | URL | | ------------------------------ | --------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- | | **Bridge node data dashboard** | Looker Studio dashboard for Celestia bridge metrics | [View dashboard](https://lookerstudio.google.com/u/0/reporting/73fc0733-5f3e-4a85-be1f-081f99991f4c/page/Tn17D) | ## Research & analytics | Resource | Description | URL | | ------------------------------ | --------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- | | **Blockworks research (paid)** | In-depth analytics and research on TIA and the Celestia network | [View analytics](https://app.blockworks.com/analytics/celestia) | | **Numia blocks dashboard** | Blocks analytics dashboard | [View dashboard](https://lookerstudio.google.com/u/0/reporting/6d5530fd-4115-4951-8a79-644842f6a2b3/page/Tn17D) | | **Numia rollups dashboard** | Rollups analytics dashboard | [View dashboard](https://lookerstudio.google.com/u/0/reporting/8853db32-fe0b-4a39-b4d7-3b9efd9e5226/page/p_da0hhwxfjd) | ## Rollup tracking | Resource | Description | URL | | -------------- | --------------------------------------- | -------------------------------- | | **rollup.wtf** | Rollup ecosystem tracking and analytics | [rollup.wtf](https://rollup.wtf) | --- Title: Data retrievability and pruning URL: https://docs.celestia.org/learn/celestia-101/retrievability.md Source: app/learn/celestia-101/retrievability/page.mdx --- # Data retrievability and pruning The purpose of data availability layers such as Celestia is to ensure that block data is provably published, so that applications and rollups can know what the state of their chain is, and store that data. Once the data is published, data availability layers [do not inherently guarantee that historical data will be permanently stored](https://notes.ethereum.org/@vbuterin/proto_danksharding_faq#If-data-is-deleted-after-30-days-how-would-users-access-older-blobs) and remain retrievable. In this document, we discuss the state of data retrievability and pruning in Celestia, as well as some tips for rollup developers in order to ensure that syncing new rollup nodes is possible. ## Data retrievability and pruning in celestia-node As of version v6 of celestia-app, celestia-node has implemented a light node sampling window of 7 days, as specified in [CIP-36](https://github.com/celestiaorg/CIPs/blob/main/cips/cip-036.md). Light nodes now only sample blocks within a 7-day window instead of sampling all blocks from genesis. This change introduces the concept of pruning to celestia-node, where data outside of the 7-day window may not be stored by light nodes, marking a significant update in how data retrievability and storage are managed within the network. Data blobs older than the recency window will be pruned by default on light nodes, but will continue to be stored by archival nodes that do not prune data. Light nodes will be able to query historic blob data in namespaces from archival nodes, as long as archival nodes exist on the public network. ## Suggested practices for rollups Rollups may need to access historic data in order to allow new rollup nodes to reconstruct the latest state by replaying historical blocks. Once data has been published on Celestia and guaranteed to have been made available, rollups and applications are responsible for storing their historical data. While it is possible to continue to do this by using the `GetAll` API method in celestia-node on historic blocks as long as archival nodes exist on the public Celestia network, rollup developers should not rely on this as the only method to access historical data, as archival nodes serving requests for historical data for free is not guaranteed. Below are some other suggested methods to access historical data. - **Use professional archival node or data providers.** It is expected that professional infrastructure providers will provide paid access to archival nodes, where historical data can be retrieved, for example using the `GetAll` API method. Providers like Quicknode offer archival node services that maintain complete historical data, ensuring reliable access to past transactions and state. This provides better guarantees than solely relying on free archival nodes on the public Celestia network. For a list of available providers, see the [network's](/operate/networks/mainnet-beta) page, and for specific archival node endpoints, refer to the [archival DA RPC endpoints](/operate/networks/mainnet-beta#archival-da-rpc-endpoints) section. - **Share snapshots of rollup nodes.** Rollups could share snapshots of their data directories which can be downloaded manually by users bootstrapping new nodes. These snapshots could contain the latest state of the rollup, and/or all the historical blocks. - **Add peer-to-peer support for historical block sync.** A less manual version of sharing snapshots, where rollup nodes could implement built-in support for block sync, where rollup nodes download historical block data from each other over a peer-to-peer network. - [**Namespace pinning.**](https://github.com/celestiaorg/celestia-node/issues/2830) In the future, celestia-node is expected to allow nodes to choose to "pin" data from selected namespaces that they wish to store and make available for other nodes. This will allow rollup nodes to be responsible for storing their data, without needing to implement their own peer-to-peer historical block sync mechanism. --- Title: The lifecycle of a celestia-app transaction URL: https://docs.celestia.org/learn/celestia-101/transaction-lifecycle.md Source: app/learn/celestia-101/transaction-lifecycle/page.mdx --- # The lifecycle of a celestia-app transaction Users request the celestia-app to make data available by sending `PayForBlobs` transactions. Every such transaction consists of the identity of the sender, the data to be made available, also referred to as the message, the data size, the namespace, and a signature. Every block producer batches multiple `PayForBlobs` transactions into a block. Before proposing the block though, the producer passes it to the state machine via ABCI++, where each `PayForBlobs` transaction is split into a namespaced message (denoted by `Msg` in the figure below), i.e., the data together with the namespace ID, and an executable transaction (denoted by `e-Tx` in the figure below) that does not contain the data, but only a commitment that can be used at a later time to prove that the data was indeed made available. Thus, the block data consists of data partitioned into namespaces and executable transactions. Note that only these transactions are executed by the Celestia state machine once the block is committed. ![Lifecycle of a celestia-app Transaction](/img/learn/tx-lifecycle.png) Next, the block producer adds to the block header a commitment of the block data. As [described in the "Celestia's data availability layer" page](/learn/celestia-101/data-availability), the commitment is the Merkle root of the $4k$ intermediate Merkle roots (i.e., one for each row and column of the extended matrix). To compute this commitment, the block producer performs the following operations: - It splits the executable transactions and the namespaced data into shares. Every share consists of some bytes prefixed by a namespace. To this end, the executable transactions are associated with a reserved namespace. - It arranges these shares into a square matrix (row-wise). Note that the shares are padded to the next power of two. The outcome square of size $k \times k$ is referred to as the original data. - It extends the original data to a $2k \times 2k$ square matrix using the 2-dimensional Reed-Solomon encoding scheme described above. The extended shares (i.e., containing erasure data) are associated with another reserved namespace. - It computes a commitment for every row and column of the extended matrix using the NMTs described above. Thus, the commitment of the block data is the root of a Merkle tree with the leaves the roots of a forest of Namespaced Merkle subtrees, one for every row and column of the extended matrix. ## Checking data availability ![DA network](/img/learn/consensus-da.png) To enhance connectivity, the celestia-node augments the celestia-app with a separate libp2p network, _i.e._, the so-called _DA network_, that serves DAS requests. Light nodes connect to a celestia-node in the DA network, listen to extended block headers (i.e., the block headers together with the relevant DA metadata, such as the $4k$ intermediate Merkle roots), and perform DAS on the received headers (i.e., ask for random data shares). Note that although it is recommended, performing DAS is optional -- light nodes could just trust that the data corresponding to the commitments in the block headers was indeed made available by the Celestia DA layer. In addition, light nodes can also submit transactions to the celestia-app, i.e., `PayForBlobs` transactions. While performing DAS for a block header, every light node queries Celestia Nodes for a number of random data shares from the extended matrix and the corresponding Merkle proofs. If all the queries are successful, then the light node accepts the block header as valid (from a DA perspective). If at least one of the queries fails (i.e., either the data share is not received or the Merkle proof is invalid), then the light node rejects the block header and tries again later. The retrial is necessary to deal with false negatives, i.e., block headers being rejected although the block data is available. This may happen due to network congestion for example. Alternatively, light nodes may accept a block header although the data is not available, i.e., a _false positive_. This is possible since the soundness property (i.e., if an honest light node accepts a block as available, then at least one honest bridge node will eventually have the entire block data) is probabilistically guaranteed (for more details, take a look at the [original paper](https://arxiv.org/abs/1809.09044)). By fine tuning Celestia's parameters (e.g., the number of data shares sampled by each light node) the likelihood of false positives can be sufficiently reduced such that block producers have no incentive to withhold the block data. --- Title: Celestia.org Code of Conduct URL: https://docs.celestia.org/learn/code-of-conduct.md Source: app/learn/code-of-conduct/page.mdx --- # Celestia.org Code of Conduct ## Our Pledge We as Celestia.org members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, caste, color, religion, or sexual identity and orientation. We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community. ## Our Standards Examples of behavior that contributes to a positive environment for our community include: - Demonstrating empathy and kindness toward other people - Being respectful of differing opinions, viewpoints, and experiences - Giving and gracefully accepting constructive feedback - Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience - Focusing on what is best not just for us as individuals, but for the overall community - Contributing to conversations about Celestia’s technology and ecosystem Examples of unacceptable behavior include: - The use of sexualized language or imagery, and sexual attention or advances of any kind - Trolling, insulting or derogatory comments, and personal or political attacks - Public or private harassment - Publishing others' private information, such as a physical or email address, without their explicit permission - Focusing on the prices of digital assets or tokens, or where they can be purchased - Other conduct which could reasonably be considered inappropriate in a professional setting ## Enforcement Responsibilities Community leaders are responsible for clarifying and enforcing our standards of acceptable behavior and will take appropriate and fair corrective action in response to any behavior that they deem inappropriate, threatening, offensive, or harmful. Community leaders have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, and will communicate reasons for moderation decisions when appropriate. ## Scope This Code of Conduct applies within all community spaces, and also applies when an individual is officially representing the community in public spaces. Examples of representing our community include using an official e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. ## Enforcement Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders responsible for enforcement at Celestia.org Discord. All complaints will be reviewed and investigated promptly and fairly. All community leaders are obligated to respect the privacy and security of the reporter of any incident. ## Enforcement Guidelines Community leaders will follow these Community Impact Guidelines in determining the consequences for any action they deem in violation of this Code of Conduct: ### 1. Correction **Community Impact**: Use of inappropriate language or other behavior deemed unprofessional or unwelcome in the community. **Consequence**: A private, written warning from community leaders, providing clarity around the nature of the violation and an explanation of why the behavior was inappropriate. A public apology may be requested. ### 2. Warning **Community Impact**: A violation through a single incident or series of actions. **Consequence**: A warning with consequences for continued behavior. No interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, for a specified period of time. This includes avoiding interactions in community spaces as well as external channels like social media. Violating these terms may lead to a temporary or permanent ban. ### 3. Temporary Ban **Community Impact**: A serious violation of community standards, including sustained inappropriate behavior. **Consequence**: A temporary ban from any sort of interaction or public communication with the community for a specified period of time. No public or private interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, is allowed during this period. Violating these terms may lead to a permanent ban. ### 4. Permanent Ban **Community Impact**: Demonstrating a pattern of violation of community standards, including sustained inappropriate behavior, harassment of an individual, or aggression toward or disparagement of classes of individuals. **Consequence**: A permanent ban from any sort of public interaction within the community. ## Attribution This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 2.1, available at [https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1]. Community Impact Guidelines were inspired by [Mozilla's code of conduct enforcement ladder][Mozilla CoC]. For answers to common questions about this code of conduct, see the FAQ at [https://www.contributor-covenant.org/faq][FAQ]. Translations are available at [https://www.contributor-covenant.org/translations][translations]. [homepage]: https://www.contributor-covenant.org [v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html [Mozilla CoC]: https://github.com/mozilla/diversity [FAQ]: https://www.contributor-covenant.org/faq [translations]: https://www.contributor-covenant.org/translations --- Title: Using Hyperlane with Celestia URL: https://docs.celestia.org/learn/features/bridging/hyperlane.md Source: app/learn/features/bridging/hyperlane/page.mdx --- # Using Hyperlane with Celestia ## Live bridge - [Hyperlane Nexus UI](https://nexus.hyperlane.xyz/?origin=celestia&token=TIA&destination=base) ## Summary [Hyperlane](https://hyperlane.xyz/) is a permissionless interoperability layer that lets blockchains send messages and trigger actions on one another. Along with [IBC](/learn/features/bridging/ibc), it is one of the standards used on Celestia for cross-chain asset transfers and messages. You can use Hyperlane to bridge TIA between Celestia and other EVM-compatible chains, as well as send arbitrary cross-chain messages. ## How bridging works ```mermaid flowchart LR %% --- Chain A --- subgraph ChainA["Chain A"] A_App["Application"] A_Mailbox["Mailbox Contract"] A_ISM["Interchain Security Module"] end %% --- Chain B --- subgraph ChainB["Chain B"] B_App["Application"] B_Mailbox["Mailbox Contract"] B_ISM["Interchain Security Module"] end %% Internal flows (Chain A) A_App --> A_Mailbox A_Mailbox --> A_ISM A_ISM -->|Verify Message| A_Mailbox %% Internal flows (Chain B) B_App --> B_Mailbox B_Mailbox --> B_ISM B_ISM -->|Verify Message| B_Mailbox %% Cross-chain relayer messages A_Mailbox <-->|Relayers
Messages + Proofs| B_Mailbox ``` - **Mailbox** — the core contract on each chain that dispatches and processes messages. - **Relayer** — an off-chain program that delivers messages and metadata between blockchains. - **Interchain Security Module (ISM)** — a modular security component that verifies messages before they're processed on the destination chain. **Bridging flow** 1. **Source chain** — the application sends a message to the Mailbox contract, which emits an event and stores a commitment. 2. **Relayer** — an offchain relayer observes the source chain, reads the message event, and fetches the necessary metadata and proofs. 3. **Relayer → destination** — the relayer submits the message plus metadata to the destination Mailbox contract. 4. **Destination chain** — the ISM verifies the message using the provided metadata (proofs, signatures, etc.), and if valid, the Mailbox delivers the message to the recipient application. 5. **Recipient application** — the destination application receives and processes the message (for example, mints tokens, executes a function call, etc.). --- Title: Using IBC with Celestia URL: https://docs.celestia.org/learn/features/bridging/ibc.md Source: app/learn/features/bridging/ibc/page.mdx --- # Using IBC with Celestia ## Live IBC channels - [Mocha testnet](https://www.mintscan.io/celestia-testnet/relayers/) - [Mainnet](https://www.mintscan.io/celestia/relayers/) ## Summary [IBC (Inter-Blockchain Communication)](https://ibcprotocol.dev/) is a protocol for authenticated, permissionless message passing between blockchains. Along with [Hyperlane](/learn/features/bridging/hyperlane), it is one of the standards used on Celestia for cross-chain asset transfers and messages. You can use IBC to bridge assets between Celestia-native chains along with other chains. Celestia uses relayers to forward packets between chains. Relayers are processes that can be run by anyone which constantly scan for outbound packets on one chain and submits these packets alongside corresponding proofs on the destination chain. This doc covers using IBC to bridge assets; see also [how to run a relayer](/operate/data-availability/ibc-relayer). ## How bridging works ```mermaid flowchart LR %% --- Chain A --- subgraph ChainA["Chain A"] A_App["Application"] A_Router["Router (Core)"] A_Light["Light Client of Chain B"] end %% --- Chain B --- subgraph ChainB["Chain B"] B_App["Application"] B_Router["Router (Core)"] B_Light["Light Client of Chain A"] end %% Internal flows (Chain A) A_App --> A_Router A_Router --> A_Light A_Router -->|Verify Membership / Verify Non-Membership| A_Light %% Internal flows (Chain B) B_App --> B_Router B_Router --> B_Light B_Router -->|Verify Membership / Verify Non-Membership| B_Light %% Cross-chain relayer packets A_Router <-->|Relayers
Data Packets| B_Router ``` - **Light client** — a lightweight representation of a destination chain that lives within the state machine of a source chain. - **Relayer** — an off-chain program that facilitates communication between independent blockchains. - **Router** — a component in the that connects two blockchains, handles packet routing between applications, and manages the verification of cross-chain data. **Bridging flow** 1. **Source chain** — the source router (onchain module) escrows or burns the tokens, builds a packet (payload + seq + timeout), and stores a packet commitment (hash) in state. 2. **Relayer** — an offchain relayer observes the source, reads the packet and the packet-commitment, and fetches a proof of that commitment from the source chain. 3. **Relayer → destination** — the relayer submits the packet plus the commitment proof to the destination router. 4. **Destination chain** — the destination’s light client verifies the commitment proof and, if valid, the destination router processes the packet (for example mints or credits) and writes an acknowledgement commitment. 5. **Relayer → Source** — the relayer fetches the acknowledgement and submits the acknowledgement proof back to the source chain. 6. **Source chain** — the source’s light client verifies the acknowledgement proof and the source router finalizes the transfer (releases escrow or marks the packet complete); if the timeout elapsed first, the source router executes refund logic. --- Title: Private Blockspace URL: https://docs.celestia.org/learn/features/private-blockspace.md Source: app/learn/features/private-blockspace/page.mdx --- # Private Blockspace Private Blockspace lets applications publish **encrypted state to Celestia** while still making it **publicly accountable**. Networks can keep sensitive data—like balances, positions, liquidations, and routing logic—confidential, without pushing trust back onto offchain operators. Anyone can verify that encrypted data is **available and properly committed to**, while only authorized parties can decrypt the underlying contents. Private Blockspace is built for systems where **privacy is required** and **verifiability is non-negotiable**. ## How it works Private Blockspace is implemented as a lightweight **Private Blockspace Proxy** that sits between your application and Celestia’s data availability layer: 1. **Submit**: Your app sends blobs to the proxy. The proxy encrypts the data, generates a zkVM proof (**Verifiable Encryption**), and publishes the encrypted blob to Celestia. 2. **Retrieve**: Your app fetches blobs through the proxy. The proxy retrieves encrypted data from Celestia and attempts to decrypt it using the configured key material. 3. **Verify**: Anyone can verify that the encrypted data is available on Celestia and that protocol-defined commitments about the plaintext hold—without revealing the plaintext itself. ## Use cases Private Blockspace is designed for applications that need private execution or private state while preserving public guarantees. Here are a few novel use cases it can be applied to: - **Accountable offchain exchanges**: Keep exchange state private while making availability and commitments publicly verifiable. - **Trust-minimized data marketplaces**: Sellers can publish verifiably encrypted data to Celestia so buyers can verify availability and integrity before payment—without relying on intermediaries. ## Get started - [About Private Blockspace](/build/private-blockspace/about): Architecture and technical details - [Quickstart guide](/build/private-blockspace/quickstart): Run it locally and submit encrypted blobs - [Private Blockspace Proxy](https://github.com/celestiaorg/private-blockspace-proxy/): Source code and implementation details --- Title: Overview of TIA URL: https://docs.celestia.org/learn/TIA/overview.md Source: app/learn/TIA/overview/page.mdx --- # Overview of TIA ## TIA at a glance | Property | Details | | ----------------------- | ------------------------------------------------------------------------------------------------ | | Abbreviation | TIA | | Total supply at genesis | 1,000,000,000 TIA | | Inflation schedule | 8% in the first year, decreasing 10% per year until reaching an inflation floor of 1.5% annually | | Decimals | 6 | | Conversion | 1 uTIA = 1 TIA × 10⁻⁶ | ## Role of TIA ### Paying for blobspace Celestia’s native asset, TIA, is an essential part of how developers build on the first modular blockchain network. To use Celestia for data availability, rollup developers submit PayForBlobs transactions on the network for a fee, denominated in TIA. ### Bootstrapping new rollups A core part of the Celestia vision is that deploying a blockchain should be as easy as deploying a smart contract. In the modular era, developers no longer need to issue a token to launch their own blockchain. Similarly to ETH on Ethereum-based rollups, developers may opt to bootstrap their chain quickly by using TIA as a gas token and currency, in addition to paying for data availability. In this mode, developers can focus on creating their application or execution layer, instead of issuing a token right away. ### Proof-of-stake As a permissionless network built with Cosmos SDK, Celestia uses proof-of-stake to secure its own consensus. Like in other Cosmos networks, any user can help secure the network by delegating their TIA to a Celestia validator for a portion of their validator’s staking rewards. Learn [how proof-of-stake works in Cosmos](https://docs.cosmos.network/sdk/v0.53/build/modules/staking). ### Decentralised governance TIA staking also allows the community to play a critical role in decentralised governance over key parts of Celestia, such as voting on network parameters through governance proposals, and governing the community pool, which receives 2% of block rewards. Learn more about [Celestia’s decentralised governance model](/learn/TIA/staking-governance-supply#decentralised-governance). ### Denominations #### TIA: display token TIA is the [`DisplayDenom`](https://github.com/celestiaorg/celestia-app/blob/ada77509d7fdedf2a3e3400b720549365851454c/app/app.go#L110-L111) that you will typically see in wallets and user interfaces. #### utia: staking denomination `utia` is the [`BondDenom`](https://github.com/celestiaorg/celestia-app/blob/ada77509d7fdedf2a3e3400b720549365851454c/pkg/appconsts/global_consts.go#L75-L76) and stands for "micro TIA", with 1 TIA = 1,000,000 `utia`. This is the native staking denomination. In staking operations or transactions, if no denomination is specified, `utia` is assumed. #### microtia: staking denomination alias `microtia` is the [`BondDenomAlias`](https://github.com/celestiaorg/celestia-app/blob/ada77509d7fdedf2a3e3400b720549365851454c/app/app.go#L108-L109), an alias for `utia`. --- Title: Paying for blobspace URL: https://docs.celestia.org/learn/TIA/paying-for-blobspace.md Source: app/learn/TIA/paying-for-blobspace/page.mdx --- # Paying for blobspace ## PayForBlobs transactions To publish data on Celestia, developers can submit `PayForBlobs` transactions. A `PayForBlobs` transaction consists of the identity of the sender, the data to be made available, the data size, the namespace, and a signature. Each `PayForBlobs` transaction is split into two parts: the blob or blobs which include the data to be made available along with the namespace, and the executable payment transaction which includes a commitment to the data. Both the blobs and executable payment transactions are put into the block within the appropriate namespace. The block data is extended using erasure coding and then Merkelized into a data root commitment included in the block header. ![Lifecycle of a celestia-app Transaction](/img/learn/tx-lifecycle.png) See [the detailed life cycle of a Celestia transaction](/learn/celestia-101/transaction-lifecycle). Learn how to [submit data to Celestia’s data availability layer](/learn/TIA/submit-data). ## Fee market overview Celestia uses a standard gas-price prioritised mempool. This means that transactions with higher fees will be prioritised by validators. Fees are comprised of a flat fee per transaction and then a variable fee based on the size of each blob in the transaction. Understand how fees are calculated on Celestia in [the overview on submitting PFB transactions](/learn/TIA/submit-data). --- Title: Staking, governance, & supply URL: https://docs.celestia.org/learn/TIA/staking-governance-supply.md Source: app/learn/TIA/staking-governance-supply/page.mdx --- # Staking, governance, & supply ## Proof-of-stake on Celestia Celestia is a proof-of-stake blockchain based on CometBFT and the Cosmos SDK. Celestia supports in-protocol delegation and will start with an initial validator set of 100. Staking TIA as a validator or delegator enables you to earn staking rewards from the network. Validators charge a fee to delegators which gives them a percentage of staking rewards. Learn [how proof of stake works on Cosmos SDK chains like Celestia](https://docs.cosmos.network/sdk/v0.53/build/modules/staking). | Consensus mechanism | Proof-of-stake | | -------------------- | -------------- | | Blockchain framework | Cosmos SDK | | Validator set size | 100 | | Delegation support | Yes | Learn how to [stake on your own at the community dashboards](/learn/TIA/staking). ## Inflation TIA inflation started at 8% annually. 1. Initially, it was set to decrease by 10% every year until reaching a long-term issuance rate of 1.5%. 2. With the v4 Lotus upgrade ([CIP-29](https://cips.celestia.org/cip-029.html)) in July 2025, the inflation rate dropped from ~7.2% to ~5.0% and was set to continue decreasing by 6.7% every year until it stabilized at 1.5%. 3. With the v6 ([CIP-41](https://cips.celestia.org/cip-041.html#inflation-schedule-over-time)) upgrade in November 2025, the inflation rate again dropped to ~2.5% and will continue to decrease by 6.7% every year until it stabilizes at 1.5%. The diagram below illustrates both the initial inflation rates and those after the v6 upgrade. ![inflation diagram](/img/learn/TIA_inflation_post-cip41.jpg) For an in-depth understanding, refer to [ADR019](https://github.com/celestiaorg/celestia-app/blob/main/docs/architecture/adr-019-strict-inflation-schedule.md). ## Decentralised governance ### Network parameters TIA holders (not just stakers) can propose and vote on governance proposals to change a subset of network parameters. To learn more, see a [complete list of both the changeable and non-changeable parameters and their values](https://celestiaorg.github.io/celestia-app/parameters_v6.html). Additionally, learn how to [submit and vote on governance proposals](/operate/consensus-validators/cli-reference#governance). ### Community pool Starting at genesis, Celestia’s [community pool](https://docs.cosmos.network/sdk/v0.53/build/modules/distribution) receives 2% of all Celestia block rewards. TIA stakers may vote to fund ecosystem initiatives as in many other Cosmos SDK chains. Learn how to [submit a governance proposal to spend community pool funds](/operate/consensus-validators/cli-reference#community-pool). ## TIA allocation at genesis Celestia will have a total supply of 1,000,000,000 TIA at genesis, split across five categories described in the chart and table below. ![allocation diagram](/img/learn/Celestia_TIA_Allocation_at_Genesis.png) | Category | Description | % | | ------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------ | | Public Allocation | Genesis Drop and Incentivized Testnet: 7.41%
Future initiatives: 12.59% | 20.00% | | R&D & Ecosystem | Tokens allocated to the Celestia Foundation and core devs for research, development, and ecosystem initiatives including:
- Protocol maintenance and development
- Programs for rollup developers, infrastructure, and node operators | 26.79% | | Early Backers: Series A&B | Early supporters of Celestia | 19.67% | | Early Backers: Seed | Early supporters of Celestia | 15.90% | | Initial Core Contributors | Members of Celestia Labs, the first core contributor to Celestia | 17.64% | ### Unlocks Celestia’s 1 billion TIA supply at genesis will be subject to several different unlock schedules. All tokens, locked or unlocked, may be staked, but staking rewards are unlocked upon receipt and will add to the circulating supply. **Circulating supply** is defined as the amount of TIA tokens in general circulation without onchain transfer restrictions. **Available supply** is defined as the amount of TIA tokens that are either part of the circulating supply or are unlocked but subject to some form of governance to determine when the tokens are allocated. This includes the unlocked portion of the R&D & Ecosystem tokens and the tokens set aside for future initiatives. _The definitions for circulating and available supply were adapted from [Optimism’s definitions](https://community.optimism.io/docs/governance/allocations/#token-distribution-details)._ ![supply diagram](/img/learn/Celestia_TIA_Available_Supply.png) Unlock schedule by category is described in the table below. _Note: Due to 2024 being a leap year, the yearly unlock intervals will occur on October 30th of each year. For example, unlocks at year 1 will occur on October 30, 2024._ | Category | Unlock Schedule | | ------------------------- | ------------------------------------------------------------------------------------------- | | Public Allocation | Fully unlocked at launch. | | R&D & Ecosystem | 25.00% unlocked at launch.
Remaining 75.00% unlocks continuously from year 1 to year 4. | | Initial Core Contributors | 33.33% unlocked at year 1.
Remaining 66.67% unlocks continuously from year 1 to year 3. | | Early Backers: Seed | 33.33% unlocked at year 1.
Remaining 66.67% unlocks continuously from year 1 to year 2. | | Early Backers: Series A&B | 33.33% unlocked at year 1.
Remaining 66.67% unlocks continuously from year 1 to year 2. | --- Title: Staking on Celestia URL: https://docs.celestia.org/learn/TIA/staking.md Source: app/learn/TIA/staking/page.mdx --- # Staking on Celestia Engage with the Celestia network at a deeper level through staking. An essential mechanism to a proof-of-stake network, users can secure the network by delegating to a validator and receive a share of its staking rewards. As of [CIP-30](https://cips.celestia.org/cip-030.html), when delegators modify their staking positions (_e.g._, redelegate or undelegate), the distribution no longer auto-claim rewards on delegation-share changes. Instead, rewards are accrued until the user calls `MsgWithdrawDelegatorReward`. ## Mainnet Beta Currently, the following staking interfaces exist for the Mainnet Beta. Just connect your wallet to get started! - [https://wallet.keplr.app/chains/celestia?tab=staking](https://wallet.keplr.app/chains/celestia?tab=staking) - [https://alphab.ai/s/m/celestia/](https://alphab.ai/s/m/celestia/) ## Mocha testnet Currently, the following staking interfaces exist for the Mocha testnet. Just connect your wallet to get started! - [https://testnet.keplr.app/chains/celestia-mocha-testnet](https://testnet.keplr.app/chains/celestia-mocha-testnet) - [https://explorer.kjnodes.com/celestia-testnet](https://explorer.kjnodes.com/celestia-testnet) - [https://alphab.ai/s/t/celestia-mocha-4/](https://alphab.ai/s/t/celestia-mocha-4/) --- Title: Submitting data blobs to Celestia URL: https://docs.celestia.org/learn/TIA/submit-data.md Source: app/learn/TIA/submit-data/page.mdx --- # Submitting data blobs to Celestia To submit data to Celestia, users submit blob transactions (`BlobTx`). Blob transactions contain two components, a standard Cosmos-SDK transaction called `MsgPayForBlobs` and one or more `Blob`s of data. ## Maximum blob size As of **v6**, the maximum transaction size on all networks is **8 MiB (8,388,608 bytes)**. This cap applies to the _entire_ transaction—including the PFB, all blobs, and overhead—so the maximum total blob size is slightly smaller than 8 MiB. The _exact_ maximum total blob size in a transaction depends on: - the number of shares available after accounting for the PFB transaction, - the share version and layout rules, - and the fact that the **first sparse share has 478 bytes**, while **all subsequent sparse shares have 482 bytes**. The current max square size on Mocha and Mainnet Beta is 32 MiB. Under v6 and future upgrades, networks will use larger square sizes, so the absolute maximum blob capacity per transaction will increase correspondingly—up to the global **8 MiB transaction size limit**, which is now the binding constraint. See the [Mainnet Beta page under “Transaction size limit”](/operate/networks/mainnet-beta#transaction-size-limit) for details. ## Fee market and mempool Celestia makes use of a standard gas-priced prioritized mempool. By default, transactions with gas prices higher than that of other transactions in the mempool will be prioritized by validators. ### Fee estimation Celestia-node provides flexible fee estimation options for submitting transactions: 1. **Default estimation**: By default, fee estimation relies on the consensus node to which the node is connected. 2. **Third-party estimation**: Users can specify a separate endpoint for fee estimation using the `--core.estimator.address` flag in the CLI. This allows using a dedicated service for fee estimation. 3. **Maximum gas price**: Users can set a maximum gas price they're willing to pay for transactions using the `--max.gas.price` flag. If the estimated gas price exceeds this maximum, the transaction will not be submitted. The default maximum is set to 100 times the minimum gas price (0.2 TIA). - PayForBlobs (PFB) transactions: Only the gas price (cost per unit) is dynamically estimated. The gas usage (number of units) uses a fixed calculation method. - All other transactions: Both gas price and gas usage are dynamically estimated. When using third-party estimation, the consensus endpoint must be running celestia-app v3.8.1 or higher. ### Fees and gas limits As of version v1.0.0 of the application (celestia-app), there is no protocol enforced minimum fee (similar to EIP-1559 in Ethereum). Instead, each consensus node running a mempool uses a locally configured gas price threshold that must be met in order for that node to accept a transaction, either directly from a user or gossiped from another node, into its mempool. As of version v1.0.0 of the application (celestia-app), gas is not refunded. Instead, transaction fees are deducted by a flat fee, originally specified by the user in their tx (where fees = gasLimit \* gasPrice). This means that users should use an accurate gas limit value if they do not wish to overpay. Under the hood, fees are currently handled by specifying and deducting a flat fee. However gas price is often specified by users instead of calculating the flat fee from the gas used and the gas price. Since the state machine does not refund users for unused gas, gas price is calculated by dividing the total fee by the gas limit. #### Estimating PFB gas Generally, the gas used by a PFB transaction involves a static fixed cost and a dynamic cost based on the size of each blob in the transaction. For a general use case of a normal account submitting a PFB, the static costs can be treated as such. However, due to the description above of how gas works in the Cosmos-SDK this is not always the case. Notably, if a vesting account or the `feegrant` modules are used, then these static costs change. The fixed cost is an approximation of the gas consumed by operations outside the function `GasToConsume` (for example, signature verification, tx size, read access to accounts), which has a default value of 65,000 gas. The first transaction sent by an account (sequence number == 0) has an additional one time gas cost of 10,000 gas. If this is the case, this should be accounted for. Each blob in the PFB contributes to the total gas cost based on its size. The function `GasToConsume` calculates the total gas consumed by all the blobs involved in a PFB, where each blob's gas cost is computed by first determining how many shares are needed to store the blob size. Then, it computes the product of the number of shares, the number of bytes per share, and the `gasPerByte` parameter. Finally, it adds a static amount per blob. The [`blob.GasPerBlobByte`](https://github.com/celestiaorg/celestia-app/blob/29906a468910184f221b42be0a15898722a2b08f/specs/src/parameters_v6.md?plain=1#L33) and [`auth.TxSizeCostPerByte`](https://github.com/celestiaorg/celestia-app/blob/29906a468910184f221b42be0a15898722a2b08f/specs/src/parameters_v6.md?plain=1#L31) are parameters that could potentially be adjusted through the system's governance mechanisms. Hence, actual costs may vary depending on the current state of these parameters. #### Gas fee calculation The total fee for a transaction is calculated as the product of the gas limit for the transaction and the gas price set by the user: $$ \text{Total Fee} = \text{Gas Limit} \times \text{Gas Price} $$ The gas limit for a transaction is the maximum amount of gas that a user is willing to spend on a transaction. It is determined by both a static fixed cost (FC) and a variable dynamic cost based on the size of each blob involved in the transaction: $$ \text{Gas Limit} = FC + \sum_{i=1}^{n} \text{SSN}(B_i) \times SS \times GCPBB $$ Where: - $FC$ = Fixed Cost, is a static value (65,000 gas) - $\sum_{i=1}^{n} \text{SSN}(B_i)$ = SparseSharesNeeded for the ith Blob, is the number of shares needed for the ith blob in the transaction - $SS$ = Share Size, is the size of each share - $GCPBB$ = Gas Cost Per Blob Byte, is a parameter that could potentially be adjusted through the system's governance mechanisms. The gas fee is set by the user when they submit a transaction. The fee is often specified by users directly. The total cost for the transaction is then calculated as the product of the estimated gas limit and the gas price. Since the state machine does not refund users for unused gas, it's important for users to estimate the gas limit accurately to avoid overpaying. For more details on how gas is calculated per blob, refer to the [`PayForBlobs` function](https://github.com/celestiaorg/celestia-app/blob/32d247971386c1944d44bec1faeb000b1ff1dd51/x/blob/keeper/keeper.go#L53) that consumes gas based on the blob sizes. This function uses the [`GasToConsume` function](https://github.com/celestiaorg/celestia-app/blob/32d247971386c1944d44bec1faeb000b1ff1dd51/x/blob/types/payforblob.go#L157-L167) to calculate the extra gas charged to pay for a set of blobs in a `MsgPayForBlobs` transaction. This function calculates the total shares used by all blobs and multiplies it by the `ShareSize` and `gasPerByte` to get the total gas to consume. For estimating the total gas required for a set of blobs, refer to the [`EstimateGas` function](https://github.com/celestiaorg/celestia-app/blob/32d247971386c1944d44bec1faeb000b1ff1dd51/x/blob/types/payforblob.go#L169-L181). This function estimates the gas based on a linear model that is dependent on the governance parameters: `gasPerByte` and `txSizeCost`. It assumes other variables are constant, including the assumption that the `MsgPayForBlobs` is the only message in the transaction. The `DefaultEstimateGas` function runs `EstimateGas` with the system defaults. #### Estimating gas programmatically Users can estimate an efficient gas limit by using this function: ```go import ( blobtypes "github.com/celestiaorg/celestia-app/x/blob/types" ) gasLimit := blobtypes.DefaultEstimateGas([]uint32{uint32(sizeOfDataInBytes)}) ``` If using a celestia-node light client, then this function is automatically called for you when submitting a blob. This function works by breaking down the components of calculating gas for a blob transaction. These components consist of a flat costs for all PFBs, the size of each blob and how many shares each uses and the parameter for gas used per byte. More information about how gas is used can be found in the [gas specs](https://github.com/celestiaorg/celestia-app/blob/d17e231ae3a0150b50a1854f3e9a268c34502b6b/specs/src/specs/resource_pricing.md) and the exact formula can be found in the [blob module](https://github.com/celestiaorg/celestia-app/blob/d17e231ae3a0150b50a1854f3e9a268c34502b6b/x/blob/types/payforblob.go#L157-L181). ## Transaction submission strategies Celestia-node offers three transaction submission modes, controlled by the `TxWorkerAccounts` configuration parameter in your node's state config in `config.toml`. Each mode has different throughput characteristics and ordering guarantees. ### Default behavior (TxWorkerAccounts = 0) By default, `TxWorkerAccounts` is set to `0`, which means queued submission is disabled. All PayForBlobs transactions are submitted immediately to the mempool without waiting for confirmations. This is the same behavior as versions before queued submission was introduced. The mempool maintains a fork of the canonical state each block, updating the sequence number (nonce) for each account that submits a transaction. If you wish to submit multiple transactions from the same account in quick succession, you must specify the nonce manually. Otherwise, subsequent transactions will not be accepted until the first transaction is reaped from the mempool (included in a block) or dropped after timing out. By default, nodes will drop a transaction if it does not get included in 12 blocks (roughly 72 seconds). At this point, you must resubmit your transaction if you want it to eventually be included. As of v1.0.0 of celestia-app, you cannot replace an existing transaction with a higher-fee version. You must wait 5 blocks from the original submission time and then resubmit the transaction. ### Synchronous submission (TxWorkerAccounts = 1) Setting `TxWorkerAccounts` to `1` enables synchronous, queued transaction submission: ```toml [State] TxWorkerAccounts = 1 ``` Characteristics: - Each transaction queues until the previous one is confirmed - Preserves strict ordering of transactions - Avoids sequence mismatch errors - Throughput: approximately 1 PayForBlobs transaction every other block If you specify an account other than the default account in TxConfig, the queue is bypassed and transactions enter the mempool directly without waiting for confirmations. ### Parallel transaction submission (TxWorkerAccounts > 1) This feature is currently available on Mocha testnet. For high-throughput applications that do not require sequential transaction ordering, you can enable parallel transaction submission by setting `TxWorkerAccounts` to a value > 1: ```toml [State] DefaultKeyName = "my_celes_key" DefaultBackendName = "test" TxWorkerAccounts = 8 ``` #### How it works: `TxWorkerAccounts` defines how many parallel lanes the node will initialize for submitting transactions. These lanes are implemented as subaccounts that are automatically: 1. Created and derived from your default account 2. Funded by your default account 3. Added to your node's keyring This bypasses account sequence limits and enables significantly higher throughput. Example: TxWorkerAccounts = 8 creates 7 subaccounts plus your 1 default account, allowing at least 8 PayForBlobs transactions per block. #### Important considerations Parallel submission is not suitable for implementations that require sequential transaction ordering. Only use this mode for unordered transaction workflows where your system requires a single signer, a.k.a. authored blobs. #### Key points to understand: - Account opacity: You will not know which subaccount signed which blob. Subaccounts are managed automatically by the node. - Default account only: Parallel submission only works with your node's default account. If you specify a different account in TxConfig, parallel submission is bypassed. - Blob retrieval: Since you don't know which account submitted each blob, retrieve your blobs using namespace, height, and commitment. ### Retrieving blobs submitted via parallel lanes When using parallel submission, retrieve your blobs using the following RPC methods from the [Node API `blob` section](/build/rpc/node-api/): - [`blob.Get`](/build/rpc/node-api/#blob) - Get blob by namespace and commitment - [`blob.GetProof`](/build/rpc/node-api/#blob) - Get inclusion proof by height, namespace, and commitment - [`blob.GetCommitmentProof`](/build/rpc/node-api/#blob) - Get commitment proof by height, namespace, and share commitment Example using blob.Get: ```bash celestia blob get ``` You should store the namespace, height, and commitment from your submission response to retrieve blobs later. ## API Users can currently create and submit `BlobTx`s in six ways. ### The celestia-app consensus node CLI ```bash celestia-appd tx blob PayForBlobs [flags] ``` ### The celestia-node light node CLI Using `blob.Submit`: ```bash celestia blob submit [flags] ``` For hex-encoded data, include the `0x` prefix: `0x676d` submits the text `gm`. On builds containing the blob submission fix in celestia-node #5262, data without that prefix is literal text, even if it looks like hex: `cafe` submits `cafe`. Use explicit `0x`-prefixed hex data for compatibility with earlier builds. The namespace remains hex-encoded. Available flags: - `--core.estimator.address string`: Specifies the endpoint of the third-party service for gas price and gas estimation. Format: `
:`. If not provided, the default connection to the consensus node will be used. - `--max.gas.price`: Sets the maximum gas price you're willing to pay for the transaction. If the estimated gas price exceeds this value, the transaction will not be submitted. Default is 0.2 TIA (100x the minimum gas price). Learn more in the [light node tutorial](/operate/data-availability/light-node/quickstart). ### The celestia-node API golang client See the [golang client tutorial](/build/post-retrieve-blob/client/go). ### The celestia-node API Rust client See the [Rust client tutorial](/build/post-retrieve-blob/client/rust). ### RPC to a celestia-node With the JSON-RPC API, encode blob `data` as base64, rather than using the CLI data argument format. For example, the text `gm` is `"Z20="` in a JSON-RPC blob's `data` field. The CLI prefix change does not change this encoding. Submit data using the following methods: - [`blob.Submit`](/build/rpc/node-api/#blob.Submit) - [`state.SubmitPayForBlob`](/build/rpc/node-api/#state.SubmitPayForBlob) Learn more in the [Node API docs](/build/rpc/node-api/). ### Post a blob directly from Celenium Celenium provides a user-friendly interface to view and interact with data on Celestia, and allows for submitting blobs directly from the explorer interface. To submit a blob from Celenium, follow these steps: 1. Navigate to the [Celenium explorer](https://celenium.io) and connect your wallet. 2. Click on the terminal button in the top right corner of the screen and select the "Submit data blob" option. 3. Next, ensure the file you are submitting is in a supported format and upload it. 4. In the "Namespace" field, input the namespace you want to use for the blob in hex format. 5. Finally, click on the "Continue" button to submit your blob, then approve the transaction in your wallet. Once the blob is submitted, you will see its hash on the screen. You can also use Celenium’s search bar to search for the blob's hash and view its details. --- Title: Helpful CLI commands URL: https://docs.celestia.org/operate/consensus-validators/cli-reference.md Source: app/operate/consensus-validators/cli-reference/page.mdx --- # Helpful CLI commands View all options: ```console $ celestia-appd --help Start celestia-app Usage: celestia-appd [command] Available Commands: add-genesis-account Add a genesis account to genesis.json collect-gentxs Collect genesis txs and output a genesis.json file config Create or query an application CLI configuration file debug Tool for helping with debugging your application export Export state to JSON gentx Generate a genesis tx carrying a self delegation help Help about any command init Initialize private validator, p2p, genesis, and application configuration files keys Manage your application's keys migrate Migrate genesis to a specified target version query Querying subcommands rollback rollback cosmos-sdk and tendermint state by one height start Run the full node status Query remote node for status tendermint Tendermint subcommands tx Transactions subcommands validate-genesis validates the genesis file at the default location or at the location passed as an arg version Print the application binary version information ``` ## Updating node configuration The `celestia-appd update-config` command is deprecated as of v9. Required configuration values are now enforced by the binary at startup, so do not add this command to new node initialisation or upgrade procedures. It currently prints a deprecation warning and will be removed in a future release. See the [celestia-app v9 release notes](https://github.com/celestiaorg/celestia-app/blob/v9.0.4/docs/release-notes/release-notes.md#update-config-command-deprecated) for details. ## Creating a wallet ```sh celestia-appd config keyring-backend ``` `keyring-backend` configures the keyring's backend, where the keys are stored. Options are: `os|file|kwallet|pass|test|memory`. `test` keeps the key unencrypted on disk with no password, so reserve it for local development and testnets. See [create a wallet with celestia-app](/operate/keys-wallets/celestia-app-wallet) for a comparison of the backends. You can learn more on the [Cosmos documentation](https://docs.cosmos.network/sdk/v0.53/user/run-node/keyring) or [Go Package documentation](https://pkg.go.dev/github.com/cosmos/cosmos-sdk/crypto/keyring). ## Key management ```sh # listing keys celestia-appd keys list # adding keys celestia-appd keys add # deleting keys celestia-appd keys delete # renaming keys celestia-appd keys rename ``` ### Importing and exporting keys Import an encrypted and ASCII-armored private key into the local keybase. ```sh celestia-appd keys import ``` Example usage: ```sh celestia-appd keys import amanda ./keyfile.txt ``` Export a private key from the local keyring in encrypted and ASCII-armored format: ```sh celestia-appd keys export # you will then be prompted to set a password for the encrypted private key: Enter passphrase to encrypt the exported key: ``` After you set a password, your encrypted key will be displayed. ## Querying subcommands Usage: ```sh celestia-appd query | # alias q celestia-appd q | ``` To see all options: ```sh celestia-appd q --help ``` ## Token management Get token balances: ```sh celestia-appd q bank balances
--node ``` Example usage: ```sh celestia-appd q bank balances celestia1czpgn3hdh9sodm06d5qk23xzgpq2uyc8ggdqgw \ --node https://public-endpoint.celestia-mocha.quiknode.pro ``` Transfer tokens from one wallet to another: ```sh celestia-appd tx bank send \ --node --chain-id ``` Example usage: ```sh celestia-appd tx bank send \ 19000000utia --node https://public-endpoint.celestia-mocha.quiknode.pro \ --chain-id mocha-5 ``` To see options: ```sh celestia-appd tx bank send --help ``` ## Governance Governance proposals on Celestia are limited as there are no text proposals, upgrades occur via social consensus, and some params are not modifiable. However, one can submit governance proposals to change certain parameters and spend community funds. More detailed information on this topic can be found in the [cosmos-sdk documentation for submitting proposals](https://docs.cosmos.network/sdk/v0.53/build/modules/gov), the list of [parameter defaults in the specs](https://github.com/celestiaorg/celestia-app/blob/0012451c4dc118767dd59bc8d341878b7a7cacdf/specs/src/specs/params.md), and the [x/paramfilter module specs](https://github.com/celestiaorg/celestia-app/tree/1570b3d4937ac4418b3ecf77365d47c5f094ad8f/x/paramfilter). Viewing the available proposals can be done with the query command: ```sh celestia-appd q gov proposals ``` There are four options when voting "yes", "no", "no_with_veto" and "abstain". The "no_with_veto" vote is different from the "no" vote in that the submitter of the proposer's deposit will get burned, and a minority of stake (1/3) can stop a proposal that might otherwise pass quorum. You can use those options to vote on a governance proposal with the following command: ```sh celestia-appd tx gov vote