Skip to content

Commit

Permalink
docs: update draft of kuai proposal
Browse files Browse the repository at this point in the history
1. rename models to `Store`, `Contract` and `Token`
2. complement details added in #5
3. add some promising features
  • Loading branch information
Keith-CY committed Oct 5, 2022
1 parent 3dbad76 commit db791f4
Showing 1 changed file with 90 additions and 33 deletions.
123 changes: 90 additions & 33 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,53 +90,57 @@ Two abstractions will be promoted in `Kuai`: `Data storage` and `Data manipulati

#### Abstraction of data storage

There'll be three basic data models used in `Kuai` based DApps: `Data`, `Code`, `MultiCoin Token`
There'll be three basic data models used in `Kuai` based DApps: `Store`, `Contract`, `Token`

##### Data
##### Store

The basic function of cells in CKB is storing data. But data are meaningless without schema, so the first basic model introduced by `Kuai` is named `Data` which is used to transform plain data into a structured data with schema.
The basic function of cells in CKB is storing data. But data are meaningless without schema, so the first basic model introduced by `Kuai` is named `Store` which is used to transform plain data into a structured data with schema, similar to [ORM](https://www.wikiwand.com/en/Object-relational_mapping)

Note that a `Data` model could be a group of cells matching the same pattern and working as an entity so it could be regarded as a virutal DApp. Say we have 2 DApps in `School Roster Data` models, each of them consists of many `Student Data` models. And we are going to build a `Sports Meeting` DApp, a new `Sports Meeting Data` model could be created and consists of partial `Student Data` from School A and B respectively, it should work as same as a `School Roster` DApp.
Note that a `Store` model could be a group of cells matching the same `pattern` and working as an entity so it could be regarded as a virutal DApp. Say we have 2 DApps in `School Roster Store` models, each of them consists of many `Student Store` models. And we are going to build a `Sports Meeting` DApp, a new `Sports Meeting Store` model could be created and consists of partial `Student Store` from School A and B respectively, it should work as same as a `School Roster` DApp.

##### Code
<sub>Sidenote:
For JavaScript developers, the `Repository` concept in [TypeORM](https://github.com/typeorm/typeorm/blob/master/docs/working-with-repository.md) is quite similar, or to say, `Store` is a simplified `Repository` in TypeORM. `Store` has its own schema and accepts a pattern to load data from CKB, just as `Repository` accepts an `Entity` and builds a query string to load data from database.
<sub>

`Code` model is extended from `Data` model and used for scripts. A `Code` model has not only attributes, but also methods. In other words, it's not only read-/writable, but also executable. `Code` model's data/state could be updated by some rules rather than a simple `set` method inherited from the `Data` model.
##### Contract

##### MultiCoin Token
`Contract` model is extended from `Store` model and used for scripts. A `Contract` model has not only attributes, but also methods. In other words, it's not only read-/writable, but also executable. `Contract` model's data/state could be updated by some rules rather than a simple `set` method inherited from the `Store` model.

Token is a general use case that should have ability of transferring between DApps, so the third model to introduce is `MultiCoin Token`, which is specialized from `Code` model with specific attributes and methods.
##### Token

Token is a general use case that should have ability of transferring between DApps, so the third model to introduce is `Token`, which is specialized from `Contract` model with specific attributes and methods. Especially, a `Token` model is a collection of tokens, similar to [ERC 1155](https://eips.ethereum.org/EIPS/eip-1155) that represents multiple token types in one model.

#### Abstraction of data manipulation

DApps can read states from each other freely because data/states are arranged uniformly by the abstraction of data storage.

DApps can also communicate with each other freely if data manipulation has been abstracted.

##### Data
##### Store

A `Data` model should have 7 basic interfaces
A `Store` model should have 7 basic interfaces

- New(pattern): create an `Data` model binding to specified cells, as a DApp located by the pattern, ps: it's a virtual DApp rather than an explicit DApp, but because cells are following the same rule, they can work together as an entity.
- New(pattern): create an `Store` model binding to specified cells, as a DApp located by the pattern, ps: it's a virtual DApp rather than an explicit DApp, but because cells are following the same rule, they can work together as an entity.
- Destroy(): remove state and turn the cells into empty
- Duplicate(): create a `Data` model from a instance
- Duplicate(): create a `Store` model from an instance
- Sync(blockNumber?): will load and update data from the chain at latest(or specific block) global state
- Get(path): will read value of specified path
- Set(path, value): will set given value at specified path
- Delete: (path): remove key/value at specified path

##### Code
##### Contract

A `Code` model should have 5 more interfaces than `Data` model
A `Contract` model should have 5 more interfaces than `Store` model

- Deploy(): deploy the script on the chain
- Extend(code): extends from an existing `Code` model for overriding
- Upgrade(): upgrade the script on the chain
- Run(method: string, params: Array<any>): call a method of the script to update its state
- Link(abi: Array<object>): instantiate a script SDK from ABI
- Deploy(): deploy the contract on the chain
- Extend(contract): extends from an existing `Contract` model for overriding
- Upgrade(): upgrade the contract on the chain
- Run(method: string, params: Array<any>): call a method of the contract to update its state
- Link(interfaces: Array<object>): instantiate a contract SDK from interfaces. mainly used to encode a human-readable method call into a message transferred between `Contract` models.

##### MultiCoin Token
##### Token

A generally used token must have some methods based on `Code`
A generally used token must have some methods based on `Contract`

- Metadata(tokenId, metadata?): a setter/getter to the metadata of a specific token id including `name`, `symbol`, `tokenURI`, `totalSupply`)
- Mint(tokenId, amount): Mint a token
Expand All @@ -145,12 +149,19 @@ A generally used token must have some methods based on `Code`
- Redeem(address, dapp, tokenId, amount): unstake from a dapp and burn a staking token
- Lock(address, amount, tokenId, locktime): lock tokens, for cases like pre-sale, bounty of a team
- Unlock(address, tokenId, amount): unlock tokens
- Combine(token): combine two `MultiCoin Token` models into one
- Combine(token): combine two `Token` models into one
- GetBalance(address, tokenId): get token balance of a given address


Notice, all actions will be grouped and finalized together, viz. `mint`/`send` multiple token id will be finalized with a single transaction

<sub>Sidenote:
The relations between `Store`, `Contract` and `Token` could be analogized to JavaScript Built-in Objects [Map](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map), [Reflect](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect) and [Date](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date)
`Store` is similar to `Map` in JavaScript which is an iterable collection of key-value pairs and has basic methods such sa `get`, `has`, `set`, `forEach`, `keys`, `values`, `entries`. Its only usage is to store structured data.
`Contract` extends `Store` to have the ability to retrieve/alter its internal data by specific interfaces rather than simple `get/set` methods. For interoperability, `Contract` exposes a uniform approach to update its state, named `run(methodSignature, argumentList)` which is similar to `Reflect.apply(fn, thisArg, argumentList)` so the trigger could be broadcasted via message in the model tree, we will talk about it later.
`Token` is specialized from `Contract` and can be thought of as `Date` in JavaScript which has its own specific attributes and methods `now`, `setHour`. `Token` would have methods like `mint`, `burn`, `transfer`, etc. `Date` and `Token` are used so widely that they have their own seats in Built-in Objects. More advanced models will be added along with the evolving ecosystem.
</sub>

#### Reactive Lazy Evaluation

As mentioned above
Expand All @@ -160,11 +171,11 @@ As mentioned above
All actions/manipulations adopted on a model will be cached and evaluated at the end of the pipeline.

```javascript
const model = new Data()
const model = new Store()
model.action_1()
model.action_2()
// ...
modeol.action_n()
model.action_n()

/**
* get a structure with initial state and actions
Expand Down Expand Up @@ -192,17 +203,29 @@ model.finalize()

Lazy evaluation is beneficial to the following points:

1. state of the model could be traversed for debugging
2. actions could be revoked easily to find the best path of state transition.
3. inspector(or other dependencies) could be injected to enhance development
1. State of the model could be traversed for debugging
2. Actions could be revoked easily to find the best path of state transition.
3. Inspector(or other dependencies) could be injected to enhance development

#### Model Tree

There would be multiple levels of `Data` models constructing a model tree.
The keyword **model tree** was mentioned in the sidenote above of analogizing `Contract` to `Reflect`.

Every cell on CKB could be treated as a DApp because every cell has its own state and script while a group of cells using the same script should also be treated as a DApp because they adopt the same logic on a broader state.
Every cell of CKB could be treated as a minimal DApp because every cell has its own state and script, but usually a group of cells using the same script will work together as a real DApp because it adopts the same logic on a broader state. Thus a DApp running on CKB could be represented as a 2-level tree which has cells as leaves and shared scripts as nodes.

```mermaid
flowchart BT
cell_0 --> script_a
cell_1 --> script_a
cell_2 --> script_a
cell_3 --> script_b
cell_4 --> script_b
cell_5 --> script_b
script_a --> DApp
script_b --> DApp
```

Besides, if a DApp_A wants to interact with another DApp_B, stateof DApp_B would be a part of DApp_A's state so the models would be like
Similarly, a DApp could be destructed into a multi-level **model tree**. And if a **DApp_A** wants to interact with another **DApp_B**, state of **DApp_B** would be a part of **DApp_A**'s so the **model tree** of **DApp_A** would be like

```mermaid
flowchart BT
Expand All @@ -212,12 +235,42 @@ cell_a_1_model --> dapp_a_sub_model
cell_a_n_model --> dapp_a_sub_model
dapp_a_sub_model --> dapp_a_model
cell_b_0_model --> dapp_b_model
cell_b_1_model --> dapp_b_model
cell_b_n_model --> dapp_b_model
dapp_b_0_sub_model --> dapp_b_model
dapp_b_1_sub_model --> dapp_b_model
dapp_b_n_sub_model --> dapp_b_model
dapp_b_model --> dapp_a_model
```

With a set of standardized interfaces, the detail of DApp_B's model tree could be obscure to DApp_A.

This idea is from [actor model](https://www.oreilly.com/library/view/applied-akka-patterns/9781491934876/ch01.html) so the structure of an application is similar

![actor model](https://camo.githubusercontent.com/0aec56b15a4dcccf39723b43503b32e3b3a3a364ef0c3f760c9fc6a0e0ae77f3/68747470733a2f2f7777772e7a61727469732e636f6d2f77702d636f6e74656e742f75706c6f6164732f323032312f30352f696d6167652d31332d373638783237352e706e672e77656270)

Actor model is a programming paradigm for concurrent computation, states will not be stored in a single point, but distributed to various actors so computation could be performed in many actors.

Actor model follows several fundamental rules
- All computation is performed within an actor
- Actors can communicate only through messages
- In response to a message, an actor can:
- Change its state or behavior
- Send messages to other actors
- Create a finite number of child actors

From the perspective of the model tree and CKB's cell model, states/cells will not be stored in a single `Store` model, but distributed to a bulk of `Store` models and can be updated in parallel via messages. If a model handles a message, it would
- Update model's state
- Proxy the message to another model
- Create a new model to fetch more state/cells and handle the message

States/cells are arranged isolatedly into different pieces and can only be changed by messages, the updates are sequenced and data conflicts are avoided naturally.

One more interesting point is that model tree could be server-agnostic. As mentioned above, if **DApp_A** relies on **DApp_B**, e.g. **Swap DApp** relies on **Token DApp**, model tree of **DApp_B** will be a part of **DApp_A**'s model tree, illustrated in the diagram above, and **DApp_A** have to rebuild the model tree of **DApp_B** to interact with it. In actor model, **DApp_B**'s model tree could be rebuilt locally or remotely because the interactions are transferred by messages, thus **DApp_A** could request the server of **DApp_B** to output `Store` by a specific `action`.

Take a concrete example, there's a **Swap DApp** to swap **Token A** and **Token B**. Now **user** wants to swap **X token a** with **Y token b** from **Swap DApp**
1. **Swap DApp** requests **Token A DApp** to take an action **transfer X from swap_pool to user** and return a `Store of Token A`
2. **Swap DApp** requests **Token B DApp** to take an action **transfer Y from user to swap_pool** and return a `Store of Token B`.
3. **Swap DApp** combines `Store of Token A` and `Store of Token B` to generate a transaction for user to confirm the swap.

### Conventions

`Kuai-convention` is a set of conventions for the implementation reference of `Kuai-runtime` and the usage guide of `Kuai-runtime`, such as:
Expand Down Expand Up @@ -317,3 +370,7 @@ Last but not least, as an open source project, `Kuai` would be introduced to dev
- M6
- Use the project to deliver a simple .bit dapp

## Promising Features
- Working with contracts purely by JavaScript/TypeScript instead of Rust/C;
- Supporting [open transactions](https://en.bitcoin.it/wiki/Open_Transactions) for further use cases;
- Adding [DSL](https://www.wikiwand.com/en/Domain-specific_language) for facilication of development.

0 comments on commit db791f4

Please sign in to comment.