LOADING...
LOADING...
LOADING...
当前位置: 玩币族首页 > 行情分析 > 一文了解 CKB 编程模型

一文了解 CKB 编程模型

2020-04-21 Nervos 来源:区块链网络

昨天,由 Nervos Grants 项目团队 Obsidian Labs(黑曜石实验室) 联合 Nervos 和 Nervos Community 一同推出的CKB 编程体验课程正式开课啦!这是我们首次为 Nervos 中文社区的伙伴们精心打造的第一套开发体验课程。在昨天的课程中,CKB 编程体验课讲师 Obsidian Labs 创始人& CKB Studio 核心开发者Phil Li和大家初步介绍了 CKBStudio 的安装以及 IDE 的使用界面,并让大家了解如何在 CKB Studio 上进行转账以及部署简易合约。


在接下来的课程中,Phil Li 还将继续带大家实操 sUDT 的发币和转账,type 和 lock script 的脚本编程,以及 JavaScript 的智能合约编译。这门课程是 CKB 初学者了解 CKB 的极佳入口,为了方便同学们更好的掌握课程内容,我们也为大家整理和汇总了CKB 编程模型的基础图谱,供大家参阅。



Nervos CKB 是一个以状态为中心的 Layer 1 底层架构,其中交易表示状态的更改和迁移。CKB 提供了一种独特的基于 CKB VM 和 Cell 模型的有状态的图灵完备编程模型。



CKB 编程模型


如果您想要在 CKB 上进行开发,那么您首先应该要理解它的编程模型。CKB 中的状态是一等公民(First-Class Citizen),状态包含在交易和区块中,它们直接同步在节点之间。CKB 的编程模型由三部分组成:


状态生成(链下)状态存储(Cell 模型)状态验证(CKB VM)
在这个模型中,去中心化的应用逻辑被分为两个部分(生成和验证),分别在不同的地方运行。状态生成发生在客户端的链下,新的状态被打包成交易并广播到整个网络;状态验证发生在链上,它会确保状态转换的有效性并创建一个去信任的系统(trustless system)。
CKB 交易的 inputs 包括对之前 outputs的引用,以及能够解锁它们的证明。客户端将生成的新状态作为交易 outputs,在 CKB 中称为 cell。因此,cell 和交易输出的表述是可以互换的。Cell 是 CKB 中的主要状态存储单元,资产所有权归用户所有,并且必须遵循脚本指定的相关应用程序逻辑
我们在 CKB VM 中执行脚本(后文将做具体介绍)并验证交易输入中包含的证明,以确保用户可以使用这些引用的 cell,并且在指定的应用程序逻辑下状态转换是有效的。通过这种方式,网络中的所有节点都可以验证新状态是有效的,并保留这些状态。


01


Cell 模型:通用化的 UTXO 模型



Bitcoin 把整个账本分割保存在了一个个 UTXO 里面,UTXO 是未花费交易输出(Unspent Transaction Output)的简写,它被锁定在特定的所有者手中,记录在区块链上,并被整个网络识别为货币单位。它的数据结构非常简单,只包含两个字段:

class TxOut{public:Amount Value;Script scriptPubKey;...}


每一个TxOut代表了一个硬币并且有自己的命名,这是由Value定义的,scriptPubKey是一段表示这个硬币的所有者是谁的脚本(通常包含了所有者的公钥),只有能提供正确的参数使这个脚本运行成功的人,才能把这个硬币「转让」给另外一个人。
Cell
Layer 1 的关注重点在状态,以 Layer 1 为设计目标的 CKB 设计的关注点很自然就是状态。CKB 想要验证和长久保存的状态,不仅仅是像在比特币中那样简单的数字(Value),而是任何人们认为有价值的、经过共识的数据,Bitcoin 的交易输出结构满足不了这个需求。只需要将Value一般化,把它从一个存放整数的空间变成一个可以存放任意数据的空间,我们就得到了一个更加一般化的「Value」或者叫 Cell:

pub struct CellOutput {pub capacity: Capacity,pub data: Vec<u8>,pub lock: Script,pub type_: Option<Script>,}


在 Cell 里面,Value变成了capacity和data两个字段,这两个字段共同表示一块存储空间,capacity不仅仅只是存储 Token 的数量,也能表示 cell 可以存储数据数量的限制,这就是名字的由来,它是 cell 能够存储的容量限制,data则是保存状态的地方,可以写入任意的一段字节。
Cell 模型是一个全新的模型,引入了lock script和type script的概念,我们将在后面提到。
总的来说,UTXO 模型让账簿的历史记录更加清晰,但是它缺乏通用的状态存储,这会让它原本就缺乏表现力(inexpressive)的脚本更加难以使用。Cell 模型是 UTXO 模型的一个通用版本,它是 CKB 上非常灵活和具有创造力的部分。
如果你想要了解更多关于 Cell 模型的内容,欢迎查阅《理解 CKB 的 Cell 模型》:https://talk.nervos.org/t/ckb-cell/1562


02


锁定脚本 & 类型脚本:一个全新的验证模型



CKB 是一个全新的验证模型,与其它一些区块链不同,CKB 为整个社区提供了开发 CKB 脚本的自由。


1.锁定脚本
每个 Cell 都有一个锁定脚本。当交易中的 Cell 被以输入的形式使用时,锁定脚本必须执行。交易只有在所有的输入中锁定脚本都正常(执行并)退出时(没有例外)才有效。因为脚本在输入上运行,所以它可以扮演锁的角色来控制谁可以解锁或者销毁 Cell,以及花费储存在 Cell 中的容量。
以下是一个总是可以正常(执行并)退出的锁脚本的代码示例。如果使用这段代码作为锁脚本,那么任何人都可以销毁这个 Cell。

int main(int argc, char *argv[]) {return 0;}


最主流的锁定数字资产的方式是用非对称加密创建的数字签名。
这个签名演算法有两个要求:
Cell 必须要包含公钥的信息,所以只有真正的私钥可以创建有效的签名;交易必须包含签名,而且通常以整个交易作为消息去签名。
2.类型脚本
类型脚本和锁定脚本很相似,但有两点不同:
类型脚本是可选的;在任一交易中,CKB 必须在输入和输出端都运行类型脚本。
虽然我们只能在 Cell 中维持一种脚本,但我们不会想要在一个单一的脚本中扰乱(脚本)不同的职责。锁定脚本只为输出执行,所以他的首要任务是保护 Cell。只有所有者可以以输入的形式使用 Cell,以及花费储存于其中的通证。
类型脚本的目的是在 Cell 上建立合约。当你得到一个特殊类型的合约时,你可以确定 Cell 已经在特定代码中通过验证。同时这个代码也会在 Cell 被销毁时被执行。典型的类型脚本场景是用户自定义 Token,这种类型脚本必须在输出上运行,所以通证的发行必须被授权。总的来说,类型脚本是在 cell 转换阶段中用于验证某些规则的。
如果你想要了解更多关于 CKB 验证模型的内容,欢迎查看《CKB 脚本编程简介第一弹: 验证模型》。


03


CKB VM:一台真正的迷你电脑



CKB VM 是一个基于 RISC-V 指令集的 VM,用于执行类型脚本和锁脚本。这意味着什么呢?这意味着我们(在某种程度上)在 CKB 中嵌入了一台真正的迷你计算机,而不是一台虚拟机。真正计算机的好处是,你可以使用任何语言编写任何你想编写的逻辑。
我们可以用 JavaScript 编写 CKB 脚本代码。这是怎么实现的呢?那是因为我们有 C 编译器可用,我们所做的只是采用了一个 JavaScript 实现的嵌入式系统,通过 duktape 从 C 编译成 RISC-V 二进制,并放在区块链中,然后 boom,我们就可以在 CKB 上运行 JavaScript!因为我们在这里使用的是一台真正的迷你计算机,所以我们可以将另一个 VM 作为 CKB 脚本嵌入到 CKB VM 中,并在 VM 路径上探索这个 VM。
我们还可以用这个方法进行扩展,我们可以在 CKB 上通过 duktape 使用 JavaScript,也可以通过 mruby 使用 Ruby,我们甚至可以在 CKB 上使用比特币脚本或 EVM 如果我们只是编译它们的 VM 和把它放在链上。这确保了 CKB VM 既能帮助我们保存自身的优势,又能建立一个多样化的生态系统。在 CKB 中,所有的语言都应该被平等对待,自由应该被掌握在区块链智能合约开发者的手中
如果你想要了解更多关于 CKB VM 的内容,欢迎查看《RFC:CKB-VM》:、https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0003-ckb-vm/0003-ckb-vm.md


04


UDT:First-class asset



现有区块链的常见用途是向 Token 发行方发行具有特殊用途/意义的新 Token。在以太坊,我们称之为 ERC20 代币。为了区别于 ERC20,我们将 CKB 上发行的 Token 称为用户自定义代币(user defined token,简称 UDT)。
什么是 First-Class Asset?
First-Class Asset 的概念实际上来自 First-Class Function。First-Class Asset 是用户直接拥有并可以直接操作的加密资产。
为什么 UDT 是 First-Class Asset?
Ethereum 是为每个智能合约帐户提供了独特的存储空间,而 CKB 是在多个 cell 之间传播数据。Cell 的锁定脚本和类型脚本决定了该 cell 属于哪个帐户,以及如何与 cell 交互。在 CKB 中,我们有一个新的设计来存储 UDT 用户的余额:
用一个特殊的类型脚本来表示该 cell 存储的是 UDT。Cell data 的前 4 个字节包含了当前 cell 中 UDT 的数量。
这个设计有以下几个含义:
UDT cell 的存储成本总是恒定的,它与 cell 中存储的 UDT 数量无关。用户可以将 cell 中的所有 UDT 或部分 UDT 转移给其他用户实际上,可能有多个 cell 含有相同的 UDT。用于保护 UDT 的锁定脚本与 UDT 本身解耦。
每个 Token 用户将其 UDT 保存在自己的 cell 中,Cell 负责为 UDT 提供存储空间,并确保它们自己的 Token 是安全的。通过这种方式,UDT 可以真正地属于每个单独的 UDT 用户,而不像 ERC20 那样将所有 Token 用户的余额都存储在 ERC20 合约存储空间中,而 ERC20 合约存在某些安全漏洞。
CKB 的经济模型关注状态存储激励问题。用户在区块链上保存状态不仅需要支付写入费用,而且应该承担与存储时间成正比的存储成本。这解决了我们在 Ethereum ERC20 合约中实现「存储租金」时遇到的问题,例如,如果用户的资产状态混合在一个地方保存,那么如何让每个用户仅支付存储自己资产的成本将是一个问题。
如果你想要了解更多关于 First-class asset 的内容,欢迎查看《First-class Asset》:https://talk.nervos.org/t/first-class-asset/405


05


Type ID:提供可升级性和确定性之间的平衡



在区块链的世界里,有两个问题是每个人都必要面对的:


可升级性确定性之间的矛盾。


可升级性:在一个智能合约部署在区块链上之后,我还能升级它吗?假设一个智能合约得到了广泛采用,然后突然有人在这个智能合约中发现了一个 bug(遗憾的是,这样的情况在区块链行业总是会发生),我们能否在不影响所有用户的情况下,将智能合约升级到一个修复完成的版本呢?


确定性:这里有两个部分:


确定性 A:如果我选择一个智能合约来保护我的 token,那么我的 token 在未来也会安全吗?(可以由我解锁,且只能由我解锁)确定性 B:如果我现在签名了一笔交易,然后稍后再发送它,我的交易还会被区块链接受吗?
注意,一个安全的区块链要比这里提到的内容有更多的确定性需求。在这里我只描述和讨论问题相关的属性。
如果我们仔细想一想,就会发现可升级性和确定性之间总是存在冲突:
如果一个智能合约可以升级,那它可能具有不同的行为,从而使攻击者能够解锁这个 cell,或者禁止 token 所有者去解锁这个 cell。如果一个智能合约可以升级,那么一笔已经签名的交易可能会(在升级前后)执行不同的行为,从而被区块链拒绝。
回看过去,在可升级性和确定性之间,你只能选站一边。并且大多数现有的区块链项目都选择了确定性这一边。「代码即法律」的思想在区块链领域非常流行。但是我们都知道软件的设计是一个权衡的过程。在特定情况下,牺牲一些确定性来换取可升级性带来的便利是有意义的。因此,我们实现了一个独特的脚本:type IDscript在 CKB 上,这个功能完全是可选的,你可以像在其它区块链中一样,在 CKB 上完美地践行「代码即法律」的原则,并且可以提供可升级性和确定性之间的平衡。我们只是希望这个独特的功能,能为那些真正需要它的人提供新的可能性。
如果你想要了解更多关于 Type ID 的内容,欢迎查看《CKB 脚本编程简介[6]:Type ID》:https://docs.ckb.dev/blog/ckbscript-06


06


Duktape 高级编程:用 JavaScript 编写 CKB 脚本



得益于强大的 CKB VM,我们可以在 CKB 上通过 duktape 使用 JavaScript。我们不仅可以有一些逻辑非常简单的代码片段,还可以解析 CKB 数据结构,在脚本中放置外部库等等。我们的 CKB 核心开发人员 Xuejie 写了一篇关于如何实现的文章:《CKB 脚本编程简介[7]:Duktape 高级编程》:https://docs.ckb.dev/blog/ckbscript-07
这篇文章中演示了如何创建一个 CKB 脚本项目:duktape-powered,这个项目有以下需求:
外部库依赖CKB数据结构的序列化/反序列化进行哈希计算
对于想要开发 JS 项目的人来说,这是一个非常有用的例子,你可以通过 JavaScript 和 duktape 获得精简的 CKB 脚本开发体验。


07


调试:支持基于 GDB 和 REPL 的开发/调试



调试 CKB 脚本和你日常调试程序并没有太大区别。CKB 脚本调试的第一种方案,通常适用于 C、Rust 等编程语言。也许你已经习惯了写 C 的程序,而 GDB 也是你的好搭档。你想知道是不是可以用 GDB 来调试 C 程序,答案当然是:Yes!你肯定可以通过 GDB 来调试用 C 编写的 CKB 脚本。
然而,GDB 仅仅是现代软件开发中的一部分。动态语言在很大程度上占据了主导地位,很多程序员都使用基于 REPL 的开发/调试工作流。这与编译语言中的 GDB 完全不同,基本上你需要的是一个运行的环境,你可以输入任何你想要与环境进行交互的代码,然后得到不同的结果。CKB 也会支持这种类型的开发/调试工作流。
如果你想要了解更多关于如何调试 CKB 脚本的内容,欢迎查看《CKB 脚本编程简介[5]:调试》:https://docs.ckb.dev/blog/ckbscript-05


08


拥抱 WebAssembly 生态系统



与 WebAssembly 相比,RISC-V 实际上是一个更低层次的抽象,我们可以移植现有的 WebAssembly 程序,并直接在 CKB VM 上运行它们。通过这种方式,我们可以拥有 RISC-V 提供的灵活性和稳定性,同时也可以拥抱 WebAssembly 生态系统。
在 CKB VM 中运行 WebAssembly 程序实际上比直接使用 WebAssembly 虚拟机有更多的好处:
在 CKB 环境中,我们可以附加任何我们喜欢的环境功能,从而支持所有针对不同区块链的 WebAssembly 程序。更重要的是,我们可以使用导入,因为我们想要向现有的 WebAssembly 程序引入新功能,因为导入功能是与 WebAssembly 程序一起提供的,所以 CKB 本身不需要做任何事情来支持这一点,所有的神奇之处都发生在一个 CKB 脚本中。而对于支持区块链的 WebAssembly,这些环境功能很可能是固定的,并且是共识规则的一部分,不能随意引入新的环境功能。同样的,这个基于 CKB 的转型工作流能够让它更容易地支持新的 WebAssembly 特性,比如垃圾回收或线程,它实际上只是将所需的支持功能作为 CKB 脚本的一部分即可,所以当 WebAssembly 虚拟机得到更新时(如果已更新),我们无需再等待 6 个月来进行下一次硬分叉。易于实现:在 RISC-V 上构建 WebAssembly 会让人感觉更自然,因为 WebAssembly 在更高的层级上抽象了许多高级特性,例如更高级别的控制流,垃圾回收等。另一方面,RISC-V 模拟了一个真正的 CPU 可以做什么,这是在计算机内部运行的实际 CPU 之上非常薄的一层。因此,虽然这两个方向都是有可能的,但是确定(certain)的功能在 RISC-V 方向的 WebAssembly 中更容易实现,而在 WebAssembly 方向的 RISC-V 中可能会遇到障碍。另一个可供选择的方案是 EVM,多年来 EVM 一直在倡导图灵完备的解决方案,但可惜的是,在 EVM 上构建任意复杂的算法几乎是不可能的:要么编码部分太困难,要么 gas 消耗不合理。为了在 EVM 上引入最新的算法,人们不得不想出各种各样的破解方法,当伊斯坦布尔硬分叉发生时,我们只能在 EVM 中运用合理的 blake2b 算法。那么其他的算法呢?
我们试图在这一代的 CPU 架构上找到最小的层,而 RISC-V 是我们可以向区块链世界公开的最透明的模型,同时确保安全性和性能。任何不同的模型,例如 WebAssembly、EVM等,都应该是 RISC-V 模型之上的层,并且可以通过 RISC-V 模型自然地实现,但是,另一个方向可能就不那么顺利了。
此外,我们有一个新的项目可以用来生成高性能的 WASM 程序你可以查看并了解详情:《CKB 脚本编程简介[8]: 高性能 WASM》:https://docs.ckb.dev/blog/ckbscript-08


开发者社区


看到这里,你们是否已经对 CKB 的编程模型有了初步的了解,或者有了一些很好的想法?
今年年初,我们已经发布了 Nervos Grants 计划来促进 CKB 上的创新和发展,并支持多样化和繁荣的生态系统发展。并成立了3000 万美元的基金,用于资助开发者在 Nervos 上的开发。
Grants 计划的目标是吸引更多有才华的人围绕 Nervos 开发解决方案,来研究和建立必要的工具,并激励那些有意愿和有激情致力于这些解决方案的开发人员和项目。
我们的长期愿景是完全地去中心化和社区主导。要实现这一点意味着我们需要激发并引导那些希望为构建 Nervos 基础设施做出重大贡献的个人、项目和团队。
您可以访问Nervos Talk来了解 Grants 计划详情,并获取我们希望看到的提交类型列表。如果你也对 Nervos 项目感兴趣,如果你也有好的 idea、经验和技能,我们邀请您提交一份资助提案,和我们一起构建 Nervos 生态系统和共同知识库(Common Knowledge Base,CKB)。
和我们做的每一件事一样,Grants 计划过程和程序将是完全透明的。从评估申请,到投票筛选,项目的每一步都将向社区成员开放,让他们进行审查并提供反馈。
更多关于 Grants 的信息,欢迎查看:
RFC: Nervos Ecosystem Grants Programhttps://talk.nervos.org/t/rfc-nervos-ecosystem-grants-program/4038/Open Grant Program Categories and Scope of Work for Applicationshttps://talk.nervos.org/t/open-grant-program-categories-and-scope-of-work-for-applications/4109

相关阅读推荐:

在 CKB 上编程到底有什么样的优势?

—-

编译者/作者:Nervos

玩币族申明:玩币族作为开放的资讯翻译/分享平台,所提供的所有资讯仅代表作者个人观点,与玩币族平台立场无关,且不构成任何投资理财建议。文章版权归原作者所有。

LOADING...
LOADING...