5.1 容器(dapps智能合约)
容器是可扩展的智能合约——专为互联网规模服务设计的可互操作计算单元。建立在互联网计算机上的dapp可以由一个或多个容器组成。一些 dapp 的容器可能提供最终用户可以通过浏览器访问的 Web 界面。
容器的一些主要设计特点包括:
- 它们是通用的,这意味着智能合约程序类是图灵完备的(即任何可计算的东西都可以通过智能合约计算)。
- 它们是防篡改的,这意味着程序的指令得到忠实执行,中间和最终结果被准确存储和/或传输。
- 它们是自治的,这意味着智能合约由网络自动执行,无需任何个人采取任何行动。
除此之外,容器
- 是可组合的,因为它们可以相互交互,并且
- 支持代币化,这意味着他们可以使用和交易数字代币。
需要注意的一个重要特性是,IC 允许容器的一系列可变性策略,从完全不可变到单方面可升级,以及介于两者之间的其他选项。在某些情况下,不可变性是必不可少的,例如,可以想象一个金融合约,其中重要的是容器中的代码永远不会改变。在其他情况下,需要可变性,可以升级容器以更好地为用户服务或修复错误。
从智能合约到容器
智能合约是一个软件或计算机程序,它对输入起作用并忠实地产生经过认证的结果,同时保持其内部状态的完整性。要使智能合约受信任,它必须在可信任的平台上运行,例如互联网计算机。与传统软件相比,智能合约具有巨大的优势,因为它们提供了从输入到输出的信任链并且不可篡改。
容器子首先是智能合约。但是,有几个类比可能从不同的角度更容易理解。
- 容器类似于操作系统中的进程。
- 容器类似于 docker 和开放容器倡议所使用的容器。
- 容器是 WebAssembly 模块实例。
- 容器是一个actor(参与者),就像在actor模型中一样。
容器作为智能合约
部署在互联网计算机和传统区块链上的智能合约之间的一个关键区别是如何验证来自智能合约的数据。Internet 计算机由 Chain Key Cryptography 提供支持,它可以使用整个互联网计算机的单个 48 字节公钥来验证在任何子网区块链上运行的任何智能合约认证的任何工件。这与传统区块链形成对比,传统区块链需要来自 Genesis 的整个区块链来验证当前状态。
一个有用的类比是传统数据库与其事务日志之间的类比。子网区块链是加密认证的子网状态的交易日志。在传统的区块链中,需要重放整个交易日志以验证在区块链上运行的智能合约的状态。在子网区块链上,子网状态,即在区块链上运行的所有智能合约的状态,会定期重新认证(目前每 100 个区块),因此整个子网区块链不需要永远保留,或者,如果需要是的,它可以作为备份存储起来。这使得在互联网计算机上运行的智能合约比在传统区块链上运行的智能合约具有明显的可扩展性优势。
容器作为过程
容器很像 Linux、MacOS 或 Windows 等操作系统中的进程。操作系统跟踪进程的有效内存范围,而互联网计算机在容器的线性内存上实施边界。当有工作要做时,操作系统调度程序会唤醒一个进程,而 IC 会在其输入上调度容器的执行。操作系统代表进程维护状态,例如打开的文件描述符和父进程。类似地,互联网计算机代表容器维护状态,但不是文件描述符之类的东西,而是跟踪容器的周期平衡、未完成的调用、权限等。正如进程不能直接修改其文件描述符表一样,容器也不能直接修改其循环平衡。
操作系统为进程提供允许它们执行特殊操作的功能,例如操作文件和与外围设备通信。同样,互联网计算机为容器提供 API,以便它们可以:
- 付款;
- 呼唤其他容器;
- 创建和管理容器;
- 管理权限;
- 获取系统时间 - 分布式系统中的一个重要功能。
互联网计算机的一个独特功能是它提供了对安全随机性的访问。很快,容器子也将能够通过此类 API 签署比特币和以太坊交易。
在幕后,进程和容器之间的最大区别在于容器被复制到多个节点上。当一个进程发生故障时它会崩溃,但是当容器发生故障时,由 WebAssembly 中的陷阱引起,它不会崩溃。相反,它的状态会回滚到当前消息开始执行之前的状态,以便容器可以继续执行新消息。当然,如果容器在它收到的所有消息上崩溃,这几乎没有什么帮助,但它是一个非常有用的保护措施,可以防止容器逻辑中意外遗漏的情况。事实上,容器不能以与进程终止相同的方式终止——因为没有 exit() 或 abort() 系统调用。容器只能由控制器通过管理命令从互联网计算机中删除。容器的控制器是允许执行管理命令(例如移除或升级容器)的用户或另一个容器。在互联网计算机上构建自主或自治服务时,一个容器控制另一个容器的能力是一个关键因素。
容器作为容器
canister一词的含义与container一词相似,实际上,canister通常被理解为圆柱形容器。而且,确实,容器概念与容器概念有几个共同点。
Docker 提供了以下定义:“容器是一个标准的软件单元,它打包代码及其所有依赖项,以便应用程序从一个计算环境快速可靠地运行到另一个计算环境。”
容器和容器的相似之处还在于它们可以运行和暂停(容器)或停止(容器)。它们可以在停止时四处移动。容器在其中运行一个进程,因此它们还必须处理退出的进程。
因此,容器和容器的主要区别在于容器是一种智能合约,即它提供安全保证并运行在可信平台上。
作为 WebAssembly 实例的容器
容器很像WebAssembly模块实例。这不仅仅是一个类比——这就是容器在互联网计算机上的实际实现方式。
从技术上讲,容器的代码部分是一个导入系统 API 的 WebAssembly 模块;即互联网计算机向容器提供的功能。此外,容器可以导出自己的 API,供用户和其他容器调用。
根据 WebAssembly 规范:“模块实例是模块的动态表示,具有自己的状态和执行堆栈。” 因此,部署在子网区块链上的容器是一个 WebAssembly 模块实例,而不仅仅是一个 WebAssembly 模块——一个重要的区别——因为可能有许多容器运行同一个 WebAssembly 模块。
容器使用正交持久性使模块实例看起来永远存在,从而使数据库或文件 I/O 过时。要持久存储变量,开发人员只需将变量写入内存即可。持久化数据的操作对开发者来说是完全透明的,并且在某种意义上是正交的,开发者不需要做任何特别的事情来持久化数据。
出于两个原因,对容器线性存储器的所有“写入”都进行了跟踪。首先,可以回滚失败的计算或 WebAssembly 陷阱。接下来,如果一个副本由于停电等不可预见的事件而崩溃,当副本重新上线时,它会向其他副本请求修改的页面,从而可以恢复操作。这就是 Internet 计算机如何维持提供具有无限生命周期的 WebAssembly 模块实例的错觉。
采用 WebAssembly 为互联网计算机带来了几个好处:
- 容器可以用任何可以编译为 WebAssembly 的语言(例如 Motoko、Rust)编写,并且用不同语言编写的容器是完全可互操作的。
- WebAssembly 是确定性的,除了一些容易排除的边缘情况。
- WebAssembly 具有形式语义。在更长的时间范围内,可能会有端到端的正式验证的 WebAssembly 执行环境,以提高安全性。
此外,互联网计算机将随着 WebAssembly 规范的发展而发展,随着新功能变得足够成熟,增加对它们的支持。
容器作为actor
Actor 模型是并发计算的数学模型,其中,作为对消息的响应,Actor 可以修改其状态、发送消息并创建更多的 Actor。
容器子在很多方面就像Actor。例如,Actor有:
- 只能由容器本身修改的私有状态;
- 单线程执行,因此不需要基于锁的同步;
- 通过异步消息与其他容器通信的能力;和
- 创建新容器的能力。
传统actor和canister之间的一个重要区别是互联网计算机上的canister具有双向消息传递。消息分为请求和响应,请求可以被回复,互联网计算机跟踪响应的回调。
在参与者术语中,每个参与者都有一个用于接收消息的邮寄地址。容器也有一个邮寄地址,恰好看起来类似于 IPv6 地址。
单个容器只有一个更新执行线程,但互联网计算机可能会并行执行大量容器。另外,我们区分了需要更新容器状态的请求和不能修改容器状态的查询。
虽然容器的更新吞吐量受到区块链共识和单线程执行的限制,但容器可以同时处理数百个查询,实现每秒数千个查询的吞吐量,以及以毫秒为单位测量的延迟。
为了完成这幅图,应该补充一点,最终用户也作为模型中的参与者参与。这意味着浏览器和移动应用程序可以直接对容器进行更新和查询操作。
此外,为互联网计算机量身定制的Motoko编程语言,其灵感来自于actor模型。
与其他类型的智能合约相比的优势
容器具有其他区块链上智能合约的所有功能。然而,与智能合约相比,容器具有性能特征,可以使用它们来构建可扩展的软件服务[1]。容器更适合分布式系统和并发,因为它们包含Actor模型。
统计数据
IC 上的容器数量在IC 仪表板中表示。