Data availability flow¶
Data availability (DA) is the part of Myelin that proves a chunk payload is fetchable by anyone who needs to verify or dispute it. Without DA, the court path has nothing to replay.
This page walks the full DA flow: from chunk sealing to local store to external receipt to anchor package to L1 publication.
Why DA matters¶
Imagine a finalised Myelin block commits to a state root, but nobody can fetch the chunk payload that produced it. The state root alone isn't enough to dispute — the disputer needs to replay the chunk in a CKB-VM-style verifier and compare results.
DA is what makes "I can fetch the payload" a verifiable claim
instead of a hand-wave. The DA manifest is the receipt; the
SegmentProof is the cryptographic proof; the external DA receipt
is the operator attestation; the anchor package is the L1-anchored
proof-of-publication.
The DA ladder¶
local_only -> chunk sealed in local DA store
testnet_beta_ready -> + provider-signed external DA receipt
production_ready -> + production SLA: retention >= 30 days,
HTTPS retrieval endpoint, audit-log commitment
l1_da_published -> + DA anchor CellTx committed on CKB
%%{init: {
"theme": "base",
"themeVariables": {
"primaryColor": "#A5B4FC",
"primaryTextColor": "#1E293B",
"primaryBorderColor": "#4F46E5",
"lineColor": "#6366F1",
"secondaryColor": "#C7D2FE",
"tertiaryColor": "#C7D2FE"
}
}}%%
flowchart TB
L1["local_only<br/>(SegmentWriter seals the payload)"]:::r1
L2["testnet_beta_ready<br/>(provider signs receipt)"]:::r2
L3["production_ready<br/>(SLA fields bound)"]:::r3
L4["l1_da_published<br/>(anchor CellTx committed)"]:::r4
L1 --> L2 --> L3 --> L4
classDef r1 fill:#C7D2FE,stroke:#6366F1,color:#1E293B;
classDef r2 fill:#A5B4FC,stroke:#4F46E5,color:#1E293B;
classDef r3 fill:#C7D2FE,stroke:#7C3AED,color:#1E293B;
classDef r4 fill:#C7D2FE,stroke:#7C3AED,color:#1E293B;
The four levels are cumulative. production_ready implies
testnet_beta_ready implies local_only. l1_da_published is the
last step and is independent of the other three — it's a separate
claim that the L1 has seen an anchor CellTx.
The DA manifest¶
A DA manifest carries:
pub struct DaManifest {
pub schema_version: String,
pub session_id: [u8; 32],
pub chunk_index: u64,
pub payload_hash: [u8; 32],
pub segment_root: [u8; 32],
pub segment_proof: SegmentProof,
pub external_da_receipt: Option<ExternalDaReceipt>,
pub da_availability: DaAvailability,
pub l1_da_published: bool,
}
The payload_hash is the chunk payload's content hash. The
segment_root is the Merkle root of the segment tree the local
store maintains. The segment_proof proves the payload is in the
tree.
The flow¶
%%{init: {
"theme": "base",
"themeVariables": {
"primaryColor": "#A5B4FC",
"primaryTextColor": "#1E293B",
"primaryBorderColor": "#4F46E5",
"lineColor": "#6366F1",
"secondaryColor": "#C7D2FE",
"tertiaryColor": "#C7D2FE"
}
}}%%
flowchart LR
A["Chunk payload bytes"]:::in
B["SegmentWriter"]:::stage
C["DA store<br/>(local)"]:::store
D["DA manifest<br/>(+ SegmentProof)"]:::manifest
E["External DA receipt<br/>(provider signed)"]:::ext
F["DA manifest<br/>(availability level up)"]:::manifest2
G["Anchor package<br/>(CKB CellTx)"]:::pkg
H["L1 anchor CellTx<br/>(published)"]:::l1
A --> B
B --> C
B --> D
E --> F
D -.->|add receipt| F
F --> G --> H
classDef in fill:#C7D2FE,stroke:#6366F1,color:#1E293B;
classDef stage fill:#A5B4FC,stroke:#4F46E5,color:#1E293B;
classDef store fill:#C7D2FE,stroke:#6366F1,color:#1E293B;
classDef manifest fill:#C7D2FE,stroke:#4F46E5,color:#1E293B;
classDef manifest2 fill:#C7D2FE,stroke:#7C3AED,color:#1E293B;
classDef ext fill:#C7D2FE,stroke:#D97706,color:#1E293B;
classDef pkg fill:#C7D2FE,stroke:#4F46E5,color:#1E293B;
classDef l1 fill:#C7D2FE,stroke:#7C3AED,color:#1E293B;
Step 1 — Local sealing¶
cargo run -p myelin-cli -- session da-manifest \
--bundle reports/session-court-bundle.json \
--storage-dir reports/session-da-store \
--out reports/session-da-manifest.json
This:
- Reads
chunk_payloadfrom the court bundle. - Hashes it to
payload_hash. - Appends it to the segment tree via
SegmentWriter. - Computes the
segment_proof(Merkle sibling list) andsegment_root. - Emits the DA manifest with
da_availability = "local_only"andl1_da_published = false.
The local store can be reused across many chunks; the manifest
identifies its segment by payload_hash.
Step 2 — External DA receipt (optional)¶
For testnet_beta_ready, attach a provider-signed receipt:
cargo run -p myelin-cli -- session da-manifest \
--bundle reports/session-court-bundle.json \
--storage-dir reports/session-da-store \
--external-da-receipt reports/external-da-receipt.json \
--out reports/session-da-manifest.json
The receipt must use the schema myelin-external-da-receipt-v2,
bind to the same payload_hash and segment_root, and carry a
provider-recoverable secp256k1 signature over the receipt fields.
For production_ready, the receipt must additionally carry:
service_level = "production"
retention_window >= 30 days
retrieval_endpoint -> HTTPS URL with documented retrieval procedure
audit_log_commitment -> 32-byte commitment to the operator's audit log
These fields are hashed into the DA availability commitment.
Step 3 — Anchor package¶
cargo run -p myelin-cli -- session da-anchor-package \
--manifest reports/session-da-manifest.json \
--bundle reports/session-court-bundle.json \
--out reports/session-da-anchor-package.json
The anchor package converts the verified manifest into a deterministic CKB-compatible CellTx package:
- The package carries the Molecule-encoded CellTx bytes.
- The package carries the same CellTx commitments the session commit fixture advertised.
- The package includes the projection report.
It still keeps l1_da_publication_implemented = false. The anchor
package is the deterministic input to the L1 submission step; the
publication claim only flips when the CellTx is actually committed.
Step 4 — Submission to CKB¶
cargo run -p myelin-cli -- session submit-da-anchor-package \
--package reports/session-da-anchor-package.json \
--dry-run \
--out reports/session-da-anchor-submit.json
The submit-da-anchor-package step builds the CKB
send_transaction JSON-RPC request and (in dry-run mode) shows you
exactly what would be sent. Drop --dry-run to actually submit.
The full submission readiness chain runs after submission:
%%{init: {
"theme": "base",
"themeVariables": {
"primaryColor": "#A5B4FC",
"primaryTextColor": "#1E293B",
"primaryBorderColor": "#4F46E5",
"lineColor": "#6366F1",
"secondaryColor": "#C7D2FE",
"tertiaryColor": "#C7D2FE"
}
}}%%
flowchart LR
A["Submitted CellTx"]:::in
B["verify-submission-context<br/>(inputs live + deps available)"]:::step
C["verify-submission-economics<br/>(fee meets floor + rate policy)"]:::step
D["verify-submission-inclusion<br/>(get_transaction -> committed)"]:::step
E["verify-submission-stability<br/>(block hash unchanged)"]:::step
F["verify-submission-finality<br/>(confirmation depth reached)"]:::step
G["verify-submission-readiness<br/>(all five agree)"]:::step
A --> B --> C --> D --> E --> F --> G
classDef in fill:#C7D2FE,stroke:#6366F1,color:#1E293B;
classDef step fill:#A5B4FC,stroke:#4F46E5,color:#1E293B;
Only when all five steps agree on the same CKB transaction hash and
block identity does verify-submission-readiness emit
production_submission_ready = true.
Why each step exists¶
- Context — catches missing or spent input cells before live submission. Saves you from a wasted tx.
- Economics — verifies the implied fee meets the configured absolute floor, fee-rate policy, and (optional) maximum-fee policy. Saves you from overpaying or under-paying.
- Inclusion — confirms CKB
get_transactionreports the transaction ascommittedwith a real block hash. This is the first moment the L1 has actually seen your CellTx. - Stability — re-queries the committed transaction; requires block hash and block number to be unchanged. Detects reorgs.
- Finality — queries
get_tip_headerand requires the committed inclusion to reach the configured confirmation depth (default 6).
The chain is deliberately conservative: each step can be configured separately, and the final readiness report aggregates them.
The production boundary¶
Three things keep production_ready false until they're all
done:
- External DA production SLA receipt with retention ≥ 30 days, HTTPS endpoint, audit-log commitment.
- Canonical threshold-lock enforcement — verified authority Cell with the declared threshold-lock args.
- Deployed CKB court economics — checked mainnet deployment evidence for the court verifier.
If any one of these is missing, the readiness report lists it as a
production blocker. The submission can still go through — it just
can't claim production_ready.
Where to look next¶
- L1 / L2 / off-chain interactions — the bigger picture.
- Court path — how DA feeds the dispute resolution.
- Evidence paths — what the DA manifest actually proves.