What is CKB?¶
CKB is the base-layer proof-of-work blockchain of the Nervos network. What makes it different from most L1s is its state model: instead of accounts and contract storage, it uses Cells.
This page covers the Cell Model, the script system, and the parts of CKB's design that Myelin inherits.
[!NOTE] This page follows the official Nervos CKB documentation as its source of truth. See the CKB documentation map and the Cell Model reference for primary material.
The Cell Model¶
A Cell is the atomic unit of state. It is not an account, and it is not a smart-contract storage slot. It is closer to a UTXO, but it can carry arbitrary data and run scripts.
A Cell has four fields:
Cell {
capacity: u64, // storage + value budget (in shannons)
data: bytes, // arbitrary user data
lock: Script, // controls who can spend it
type_: Option<Script>, // optional: enforces state rules
}
The capacity field is interesting: it is both the value locked in
the Cell and the storage budget. You must reserve enough capacity to
cover the on-chain storage cost of data plus the cost of lock and
type scripts.
Transactions consume and create Cells¶
State changes happen by replacing Cells. A CKB transaction:
- Lists
inputs— OutPoints pointing to live Cells to consume. - Lists
outputs— new Cell definitions to create. - Carries
cell_deps— references to code Cells and dep groups. - Carries
witnesses— off-chain provided data (signatures, args).
%%{init: {
"theme": "base",
"themeVariables": {
"primaryColor": "#A5B4FC",
"primaryTextColor": "#1E293B",
"primaryBorderColor": "#4F46E5",
"lineColor": "#6366F1",
"secondaryColor": "#C7D2FE",
"tertiaryColor": "#C7D2FE"
}
}}%%
flowchart LR
A1["Cell A<br/>(live)"]:::live
A2["Cell B<br/>(live)"]:::live
A3["Cell C<br/>(live)"]:::live
TX["CKB Transaction<br/>inputs: A, B, C<br/>outputs: D, E"]:::tx
D["Cell D<br/>(new)"]:::new
E["Cell E<br/>(new)"]:::new
A1 -->|consume| TX
A2 -->|consume| TX
A3 -->|consume| TX
TX -->|create| D
TX -->|create| E
classDef live fill:#C7D2FE,stroke:#D97706,color:#1E293B;
classDef new fill:#A5B4FC,stroke:#4F46E5,color:#1E293B;
classDef tx fill:#C7D2FE,stroke:#7C3AED,color:#1E293B;
After the transaction is committed:
- A, B, C are dead (spent).
- D, E are live (newly created).
- There is no "in-place" state mutation; the world simply moved on.
Lock scripts vs type scripts¶
Two kinds of scripts can run on a Cell:
| Script | When it runs | What it checks |
|---|---|---|
| Lock script | When the Cell is consumed (spent) | "Is this transaction authorised to spend this Cell?" — typically signature verification. |
| Type script | When the transaction is committed, for every output Cell whose type matches |
"Does this Cell's data obey the schema defined by this script?" |
So a Cell with a lock but no type is a plain owned value/data Cell.
A Cell with both is a typed Cell: the type script enforces rules
across the set of Cells sharing that type, e.g. an xUDT Cell whose
balance and total supply are validated together.
[!TIP] Myelin inherits this distinction directly. Its scheduler and projection layer treat lock and type scripts as first-class, and each chunk's CellTx can carry both kinds.
Molecule serialization¶
CKB uses Molecule for all on-chain serialization. Molecule is a schemaless, deterministic, zero-copy binary format tied to a schema definition language.
Myelin uses the same format. Specifically:
OutPoint,Script,CellInput,CellOutput,CellDep, andCellTxuse CKB Molecule payload layouts.VersionedEnvelopeis a Molecule-compatible table.- The
LOAD_TRANSACTIONsyscall uses Molecule transaction bytes.
[!IMPORTANT] This is not a stylistic choice — it's the only way Myelin can produce a CellTx hash that equals the CKB transaction hash for the same bytes. That equality is what makes single-chunk court verification possible.
Why CKB doesn't have an account model¶
An account model says "this address has this balance, and this contract has this storage." A Cell model says "these live Cells exist right now; this transaction replaces some of them."
The Cell model is structurally better for:
- Parallel execution — independent Cell groups can be verified in parallel because they don't share mutable storage.
- Explicit dependencies — every read and every write is named up-front in the transaction, not implicit in storage access patterns.
- Native typed assets — xUDT, Spore, and any user-defined asset are just Cells with a type script.
Myelin keeps all three properties off-chain.
What Myelin takes from CKB¶
| CKB concept | Myelin equivalent |
|---|---|
| Cell | MyelinCellState.live_cells / created_cells |
| Transaction | CellTx (Molecule-encoded) |
| Block | MyelinBlock with state-root-before/after |
| Lock script | Script group in CellTx |
| Type script | Script group in CellTx |
| Witness | CellTx.witnesses[] |
| Cell dep | CellTx.cell_deps[] |
| Block hash | Deterministic canonical hash over header + commitments |
| Finality | Nakamoto PoW on L1, but Myelin uses static committee / Tendermint |
Myelin does not take: the PoW consensus, the RPC API, the node software, the address format, or the wallet format. Those are L1 concerns. Myelin only needs the parts that make off-chain Cell execution projectable to a CKB-VM-style verifier on the L1.