内置函数与动态布局:高效证明工作的必经之路

原文Builtins and Dynamic Layouts
翻译及校对
「Starknet 中文」社区

摘要:内置函数优化证明进程。然而,每条证明都是根据布局计算的。而对特定证明工作,如果布局效率低下,内置函数的优势就会大打折扣。目前,有个布局小型静态列表,每个证明都是根据该列表中最合适的布局计算的。这种布局静态列表的方式不足之处有二。首先,布局种类有限。这对于大多数证明工作来说效率低下,会造成复杂的收费机制,让用户承担不必要的成本。其次,手动维护列表困难。一旦内置函数数量过多,手动维护就会变得很困难,实际上会阻碍证明进程中支持大量细微之处高效的内置函数。为解决这些问题,StarkWare 团队正在开发一个动态布局系统,其中的布局都是为每个证明工作量身定制的。

Cairo 堆栈通过将 Cairo 代码编译成适用于 STARK 友好型 CPU 架构的指令来促进可证明的通用计算:Cairo VM(以下称为 CVM)。通用 CPU 的许多优势是以固有成本作为代价的,CVM 并未针对一些常用运算进行优化。 Keccak、Pedersen、Poseidon 哈希函数是这类常见运算,还有椭圆曲线操作、范围检查(即检查特定数字是否位于特定值范围内)等其它运算。

为解决 CVM 相对低效的问题,Cairo 堆栈引入了关键运算的内置函数概念:即优化此类运算证明复杂性的插件。内置函数可以类比 ASIC:ASIC 是专用集成电路,而内置函数是应用程序专用代数约束(AIR)。如果不知道或者不记得什么是 AIR,文章稍后会简要介绍;更多详细信息请阅读这篇文章

简而言之,证明复杂性与称为轨迹单元的资源相关(大致呈线性关系),内置函数通过使用比 Cairo VM 少得多的轨迹单元来简化特定运算的证明。

解释过内置函数的好处后,就知道为什么要为许多常用运算开发内置函数了。这说起来容易做起来难。目前把新内置函数引入 Starknet 的过程包含以下几个步骤:

  1. 编写 AIR

  2. 通过创建新布局(如下所述)与证明器集成

  3. 集成到 Starknet,即修改其代码库和开发者工具以使用新的内置函数

除了编写 AIR 的挑战之外,在其余两个阶段还有很大的改进空间。这篇进阶级文章将更详细地介绍作为应用程序专用 AIR 的内置函数、上述问题以及未来计划。

内置函数:应用程序专用 AIR

AIR 是代数中间表达式(Algebraic Intermediate Representation)的缩写。在本文及 StarkWare 其它文章中,AIR 是表示虚拟机的多项式系统。例如,Cairo 的名称来源于 CPU AIR:表示特定 CPU 架构的多项式系统。此多项式系统的解代表有效的状态转移,称为有效代数执行轨迹(AET)。

STARK 通过证明给定的 AIR 对应的执行轨迹有效,来证明虚拟机的运算正确。大致上来说,执行轨迹是一组数字表,而 STARK 协议证明这些数字共同解决一个多项式系统。

同样的运算可以有多种计算方式,其中一些计算要更为高效。在本文中,证明复杂性基本上取决于轨迹大小,即表格中轨迹单元的数量。由于轨迹是针对 AIR 生成的,因此专为应用程序设计的 AIR 可以大幅减少特定计算的执行轨迹。内置函数是专为应用程序优化的专用 AIR。

下表展示了特定内置函数的效率改进(都已投入生产)。

轨迹布局:现在和未来

之前说到 AET 大致上是一个数字表,表示编码虚拟机的步骤排序(即程序的执行)。为计算证明,证明器在相关 AIR 的执行轨迹上运行 STARK 协议。

在上文中,我们介绍了内置函数作为应用程序专用的 AIR,旨在通过减少对计算进行编码所需的轨迹单元数量,来最大限度降低证明的复杂性。然而,如果在 Starknet 随意集成内置函数,可能会导致浪费许多轨迹单元,预期的好处也会减少。下面来详细说明。

简而言之,轨迹布局是将轨迹单元分配给不同的「组件」。在本文中,这些组件是 CVM 和内置函数。具体来说,布局指定每个组件获得的轨迹单元的相对数量。(布局构造始终是用来简化验证的。如需了解更多,请阅读这篇文章中的「简洁性」部分)。

关键点在于,证明复杂性取决于布局分配的轨迹单元总数,而轨迹单元分配有可能大于实际需要。例如,为证明 CVM 的步骤排序,仅将轨迹单元分配给 CVM 组件的布局,与把一半的轨迹单元分配给 Poseidon 内置函数的布局相比,效率大致翻倍。总之,合适的布局可以大大降低证明特定计算的复杂性。

目前有一份手动维护的布局列表,主要由于两个原因逐渐增长:

  1. 内置函数只能用于为它们分配轨迹单元的布局。因此,添加内置函数至少需要一个新布局。

  2. 为执行 Cairo 代码定制的布局可以优化单元分配。因此,单元里用例的优化通常需要新布局。

证明器和验证器(Solidity 和 Cairo 验证器)的代码是根据布局列表配置的。

随着添加 Keccak 和 Poseidon 内置函数,发现越来越难以保证布局列表小巧,同时容纳众多内置函数,保持大多数 Starknet 区块高效执行。此外,随着引入额外的内置函数,效率预计会大幅下降,因为布局必须考虑内置函数之间许多可能的组合与比例。

StarkWare 团队目前正在努力改进系统,放弃预先制定的布局列表,支持「动态布局」,即为每次执行 Cairo 代码即时定制。动态布局将始终针对手头的验证工作进行最佳比例的分配。从工程学的角度来看,支持动态输入需要对代码库进行相当大的更改。然而,StarkWare 团队希望利用动态布局,提高轨迹单元利用率,更好地利用证明器,来简化 Starknet 的证明层。

有了动态布局,手动维护许多内置函数的麻烦就不复存在,从而简化 Starknet 集成更多新内置函数的过程。

动态布局和费用

交易费用的一个目的是向用户收取交易产生的协议边际成本。由于交易费用的单位是货币,费用机制涉及从资源(例如虚拟机步骤、内置函数、calldata、以太坊 gas)到代币(例如 STRK、ETH)的转换。

目前,因为证明器根据总轨迹而非利用比率来收取费用,所以浪费的资源是由用户来承担的。动态布局将提高轨迹单元利用率,从而减少收取「不必要」的交易费用(包括并非由用户交易直接产生的资源消耗)。

Starknet 内置函数集成

至此,集成内置函数就差最后一步,即修改 Starknet 代码库来实现实际运用。代码修改幅度与布局应用相关,确保 Starknet 操作系统在可能的情况下调用内置函数就必须要修改代码。例如,Starknet 操作系统执行 Cairo 代码期间调用 Poseidon 哈希函数,同时要调用 Poseidon 内置函数。

与布局类似,现在可以手动支持 Starknet 内置函数。然而,与布局情况不同的是,这种手动支持即使有许多内置函数,也并不会对集成造成障碍。换句话说,Starknet 内置函数支持并不是集成的障碍,动态布局将真正为创建和集成额外内置函数铺平道路。

总结

在本文中解释了什么是内置函数、它们的好处、涉及的挑战以及 StarkWare 的计划。目前重点关注动态布局,它不仅会提高证明过程的效率,还会便于新内置函数集成。

Subscribe to Starknet 中文
Receive the latest updates directly to your inbox.
Mint this entry as an NFT to add it to your collection.
Verification
This entry has been permanently stored onchain and signed by its creator.