A Programming Idea on CKB —— Energize Data [1]

The way to program on Ethereum is to write contracts. The world state of Ethereum consists of a collection of accounts, and contract is one of these accounts.

To develop contract, things a developer need to do are:

  1. define the data-structure as state
  2. define the methods that updates state
  3. define the events(logs) for methods

In circumstance of CKB (Common Knowledge Base), which is a multi-asset, store of value blockchain, the world state consists of a collection of cells. Cells are the primary state storage units in CKB, and state in cells are verified by global consensus. State in CKB is a first-class citizen, states are included in transactions and blocks and synchronized directly among nodes.

Instead of writing contract, this article proposes a new programming idea on CKB, which is energizing-data. CKB stores the data of consensus, and energizing data is to give the data meaning and value. So things a developer need to do are:

  1. figure out what data you want to store on CKB (making it meaningful and valuable by consensus)
  2. define the life cycle of data (generation, transformation, vanishment)

After a brief introduction of cell model, this article describes more details of energize-data.

Cell Model

Cell is the space unit where user can store their data, it consists of:

  1. capacity:the size of cell space
  2. data:the data stored
  3. type:the script to define the life cycle of data as well as the meaning of data
  4. lock:the script to define the authority of cell


1. Define the data of your program you want to reach a consensus

Classify data to different types according to your design, and each of them will be stored in different cells. If the data should be owned by user, it will be stored in cell maintained by user.

Once the data in cell is defined, the type and lock script will be designed around that data. Everyone can figure out a cell by type, knowing the meaning of data and how to use it.

2. Define the life cycle of data

The life of data consists of: data-generation, data-transformation, data-vanish.
And type script define rules of these changes:

// if input cells don't contain cell of this type, but output cells do
fn generate() -> bool;

// if both input and output cells contain cell of this type
fn transform() -> bool;

// if input cells contain cell of this type, but output cells don't
fn vanish() -> bool;

Next section use UDT (User Defined Token) protocol as example to illustrate train of thoughts while energize-data on CKB.

UDT20 Protocol as Example

UDT20 Protocol is one standard for defining digital assets on the CKB, which completes functions similar to ERC20.

1. Define the data of protocol

Data of UDT20 token consists of : id, name, symbol, supply, balances.
Data of balance should be owned by user and stored in cell of user.
The other data can be stored in one cell, as shown below:

Considering there are many udt20 balance cells sharing one type, we should put type code in a separate cell to avoid duplication, as shown below:

2. Define the life cycle of data

The energize-data way of programming should be data focused. So we should define three different life cycles depending on three different types of data.

  • Life cycle of UDT20-Code

Because we want code to be immutable, so transformation and vanishment of data are not allowed. And we don’t have rules of data-generation, so we don’t need to implement fn generate() either.

  • Life cycle of UDT20-Info
fn generate() -> bool {
    // Input cells should not contain cell of this type, but output cells should
    // Check data format 
    // ID equals to hash of tx inputcell[0] to make sure uniqueness

fn transform() -> bool {
    // Both input and output cells should contain cell of this type 
    // UDT20 info should be immutable
    return false;

fn vanish() -> bool {
    // Input cells should contain cell of this type, but output cells should not 
    // UDT20 info should be immutable
    return false;
  • Life cycle of UDT20-Balance
// Balance data can only be generated when issuing tokens
fn generate() -> bool {
    // Things to check:
    // 1. input cells should not contain cell of this type, but output cells should
    // 2. tx output cell[0] should be UDT20-Info Cell of issued token
    // 3. type::args of balance-cell point to output cell[0]
    // 4. balance == supply
    // 5. type::code_hash point to UDT20 Code Cell
    // 6. there are only one cell of this type in output cells

As shown below:

fn transform() -> bool {
    // Things to check:
    // 1. both input and output cells should contain cell of this type
    // 2. accumulated balance of input cells equal to that of output cells

fn vanish() -> bool {
    // Input cells should contain cell of this type, but output cells should not
    // because the protocol constraint the supply of token as invariant, so vanishment is not allowed
    return false;
    // If switch to case of image-token, burn-token rules can be defined here

3. Handle lock of cell

Lock can be any script according to the scene.

In circumstance of UDT20-Code-Cell and UDT20-Info-Cell, we can set a dead lock to make sure cell immutable.

In circumstance of UDT20-Balance-Cell, we can set a lock controlled by a private key or multi-key if data controlled by users.
If balance controlled by layer2 protocol, we can set that to be unlocked by layer2 proofs.


Instead of contract, this article provides another perspective of programming on CKB, which is energize-data. We think data is a first-class citizen, all we do is to make data valuable and meaningful through consensus. Type and lock script are defined exactly according to data of that cell, and type takes care of life cycle of data, lock takes care of authority of data.

At last we still have a question about how different data can interact, similar to contract interaction. So we will discuss that in another article soon after.


Great angle. One question. Is the transform function necessary, if generate and vanish function are well defined, since transform itself means some cells vanish and some cells generate.

I prefer transform to be necessary, it’s clearer to me. Life cycle of data is a little different from life cycle of cell

For some UDT20, your design may be right. But I think for different application scenarios we should design different schemes. Here are some questions:

Ingrained habits cannot be cast off overnight, though we had created a batter protocol like ERC777, but we still can’t replace ERC20. So could this happen again on CKB if the UDT20-Code is immutable ?And for the UDT20-Info, if the transform function is immutable, could the manager execute the action of mint or burn ?

In my opinion, those functions more like the parameters that exchanges or applications need to detect than the initial desion for UDT. But I support we should modularize these functions, so we can build UDTs on CKB just like palying LEGO.

Good question. UDT-Code and UDT-Info of course can be mutable depending on demands.