CKB 上 type script 的定位

阅读 CKB 源代码的过程中,一个疑惑是:校验交易时,为什么要校验 output.type
在两次 CKB 分享会上,这个问题都被不同的同学抛出来,然后也都引起了热烈的讨论,讨论期间大家也提出了对该字段的不同的认知。之所以对 type script 有各种不同的认知,可能的几点原因:

  • CKB 的设计先进
  • CKB 文档未给出官方定义
  • lock script 和 type script 的对数据的获取权限相同,二者界限模糊
  • “type” 这个命名较难理解

CKB 上 type script 的定位

Cell 有两个脚本字段,locktype,校验交易时会对这两个字段做校验:

  • lock 可以类别为比特币里的 P2SH。交易需提供 input cell 的解锁脚本 unlock script,用于解锁 input cell:
`return VM.exec(ctx, input_cell.lock + transaction.unlock) == 0`
  • type 比较难理解。相关验证:
`return VM.exec(ctx, output.type) == 0`

大家的普遍疑惑是,后面这个校验 output.type 的意义是什么?output 是我交易发起人构造的,难道我还会构造出一个不满足校验的 type 不成? 所以就牵涉出 type 到底是啥?

type script 的定位

type 就是 type script,对于 type script 的多种解读:

  1. 如钱林峰:“type 是对 cell data 的约束”
  2. 如“lock 表资产所有权,type 表资产使用权”
  3. 如“type 是对 cell data 的描述方式,类似于关系型数据库中的 schema”

我比较倾向于第 1 种解读,type 是对 cell data 的约束。对于第 3 种解读,我认为这只是 lock/type 的一种使用方式,并不是其本质定位;对于第 3 种解读,我认为 CKB 作为 verifier 角色,仅对链上交易做校验,并不对数据做操作,也不做“描述(表达)”。

对 “type” 命名的疑问

CKB 设计 type 字段,是借用了 type system 的 type 概念。
参考 Data type - Wikipedia,我对 data type 的理解是:data type 定义了一类 data 的三个元素:

  • operations:该类型的 data 的相关操作,如加减、拼接、存储
  • representation:该类型的 data 的表达意义
  • constraits:该类型的 data 满足的约束,如 8bit 整型数据不能超过 8 比特位

而作为 verifier 角色的 CKB,实际上链上只能定义 constraits of cell data,而其它两个元素 operations 和 representation 是在链下完成的。从这个角度想,我认为 “constrait script” 比 “type script” 更贴切,求指正。

校验** output.type **的意义

解释了 type 的定义,接下来回到最初的问题,交易过程中,校验 output.type 的意义是什么?简单举两个例子说明。

  • 对于 SoV cells,或者说其 cell data 没有意义的 cell,并不需要用到 type script,置空即可
  • 对于 utility cells,其 cell data 需要满足一定约束条件。比如我们想定义一种 ERC20 资产,就可以将 ERC20 标准约束写到 contract-cell 里,而表示 ERC20-cell (表示 ERC20 资产的 cell)的 type script 字段指向 contract-cell,也就是让 contract-cell 来约束 ERC20-cell 中的数据是否合法:
`return cell.type == contract-cell.id && 
       VM.exec(contract-cell.data, cell) == 0`

会发现,对于第二种场景,contract-cell.id 就像是一种数据类型的标识 identifier of data type,contract-cell.data 是该数据类型的约束,cell type 指向 contract-cell 即表示该 cell 满足该数据类型的约束。

更具体的解释,可能还需要 CKB 的同学梳理一下

3 Likes

我是学姐的秘书,以下回答来自学姐,我想混个回复

我大概知道这个问题的答案(因为 type script 就是我反复争取要加上去的)

简单的说,其实没有 type script 大部分功能(注意只是大部分,我们讨论中是的确找到了某些 case 光用 unlock script 是会有安全问题的)也能工作。我觉得 type script 的主要功能是给人提供一个 trust,比如我创建了一个 ERC20 的 cell,通过 type script,你不需要相信我,只需要审查 type script 之后,就知道这个 cell 能怎么演化,确保我不会做恶,就会放心来买我的币。

在 ETH 模型中,因为 generator 过程发生在链上,所以不会有这个问题,但是我们 generator 是在外面,没有 type script 的话,假设你来买我的币,我自己发 generator 随便改吞掉你的币就好了


我也是 Ian 的秘书,以下回答来自 Ian

Lock 管死,type 管生。Lock 负责 tx 中 input cells 的验证,Type 负责 output cells 的验证。Type 负责的是不能随意创建有某个 Type 的 cell 出来,反过来的话,如果 cell 的 type 是 X,那 cell 一定通过了 X 的验证。

5 Likes

我个人觉得,的确有个 type 描述状态更方便
一看就知道这个 cell 是哪个 type 的
所以就叫了 type
这名字我觉得尚可

怎么像 PGP 的逻辑

“type 是对 cell data 内容的约束”。这句话应该这么理解:

假设一个 cell 内的 data 就只有 u256 一个数据,代表某个 UDT 的余额。在没有任何约束的情况下,任何人都可以构造一个 data 内容等于 MAX_INT 的 cell,来冒充这种 UDT。

因此 CKB 的小伙伴发明了 type 字段对其进行约束:所有 type 字段相等(=某个合约的hash值)的 cell 中的data 的含义使用同一个合约进行解析,并且只有这种 cell 能够用这个合约进行解析。所以你可以伪造一个 data 内容任意的 cell,但只要你的 type 字段内容不是特定 UDT 的 type,它就不是这个 UDT 的余额。

那么还剩一个问题,type 字段的内容如何管理——总不能谁都可以把自己的 cell 设置为任意的 type 吧。CKB 接着要求每个 cell 在生成的时候必须通过 type script 的校验。也就是说,generator 可以指定生成的 cell 的 type 为任意值,只要这个 TX 能够通过对应的 type script 的校验。那么显然,类似 UDT 的数额平衡会出现在对应的 type script 中,防止凭空印钱以及凭空烧币。其他的合约也会在这里对 cell data 的内容进行约束。

所以,type 就是对 cell data 内容的约束,这个约束发生在 TX / output cell 的创建时。如果一个 TX 包含多个不同 type 的 output cell 怎么办?挨个验算。:grinning:

3 Likes

这个秘书真好吃

对于 type 这么常见的词没必要太纠结于定义吧,很多编程语言里的 type 含义都有偏差也不是和 wiki 上说的一致。

按照我的经验,实际使用中比较复杂的合约可以在 type script 定里义一组状态约束和状态转换的约束。

比如: UDT 抵押 -> DAI + locked UDT。其中的输入、输出都可以由 type 约束(所以 type 并不是仅能约束 cell 的 data 字段),这个例子中我来实现的话会用 DAI type 验证输入和输出的 UDT 的 type(UDT 本身的合法性和格式已经由 UDT 的 type 保证),并在 DAI type 中验证输出的 UDT 被 lock。

这样看来比较本质的描述是:type 约束 cells 的状态和状态转换

其实也和学姐和 ian 说的差不多了,每人的理解方式不同

(BTW,其实我一直感觉叫做 DNA 会更贴切些

嗯,其实理解了之后,看哪种解读觉得都可以。
只是对于我们新人来说,“很多种定义,很多种玩法” 意味着 “越看越搞不懂这是什么东西,应该以什么使用姿势来用它”。跟学一门新的编程语言是一个道理。

举个例子,一开始我理解为 “lock 表所有权,type 表使用权” (忘了从哪儿听来的了)的时候,就很奇怪,为什么我还要给我自己的 cell 定义个使用权?后来才明白,原来这里说的“使用权”,不是指 “cell 的使用权”,而是指“该 cell 作为一个 UDT 来使用的需要满足的条件”。

“type表使用权”这个说法我也很难理解,所以我倾向于认为是以讹传讹… 一开始按照ian的回答去理解可能是最容易的。

表示赞同,更喜欢DNA这个称呼方式,很贴切

unlock lock script(owner script) to transfer cells,
unlock type script to modify data in cells.

1 Like

很有意思的话题!

我感觉用现实的物品做类比,就像:

  • lock scrip是保险箱的密码,而
  • type scrip是里面物品的防伪认证。

比如在保险箱里放的是“美金”,不是所有纸张都叫“美金”,它是具有一定特征的,这个type scrip实际上认证了这个保险箱里放的确实是“美金”,而不是“人民币”。

按理来说,把价值存储在一个地方(SoV)是要付“保管费”的,以使得管理者能有资金和动力去加强安全网络,以保证你的资产安全;在区块链网络中其实就是矿工,由矿工来保证网络的安全。

在以太坊的网络里,这个“保险箱”是所有用户共有的(所有用户的资产都放在一个合约里),所以所难去收“保管费”。
CKB的高明之处在于,把这个“保险箱”私有化,就可以收取一定的“保管费”来建立整个网络的安全。

1 Like

jjy提到了这样一个案例,所以我觉得type script的功能可能会比防伪认证有更大的想象空间。

用你的例子来说,通过type script我可能不单单可以证明保险柜中存放的是“美金”,而不是“人民币”;还可以通过type script验证这个“美金”是所在这个特定的保险柜里面的,而不是放在外面或者锁在别的保险柜里面。@jjy 不知道这样的描述对不对?

对,可以通过 type 来验证/控制 lock hash

1 Like

抛开含义不说(需要一个官方的权威的解释了),不纠结是不可能的。原因如下:

  • type 本身太 generic。
  • 开发者和非开发者,可能对这个词会有非常不同的直觉性理解。
  • 我们需要向大量的开发者和非开发者解释这个词。
1 Like