Noname 2.0:解锁数字泛型、Folding Scheme以及Playground - ZKSECURITY

本文介绍了noname 2.0预览版的主要更新,包括支持泛型数组、通过Sonobe集成支持folding scheme、交互式在线 Playground、R1CS优化以及社区贡献的bug修复和功能改进。这些更新旨在提高noname语言的灵活性、效率和用户友好性,使开发者能够编写更复杂的ZK电路,并简化IVC应用的开发。

landing

我们很高兴地宣布即将发布的 noname 2.0 preview;这是 noname 语言的一大飞跃!此版本将引入强大的增强功能,使开发人员能够编写更复杂的 ZK 电路。值得注意的增强功能包括:

  • 通用大小数组(Generic-Sized Arrays):通过使函数能够处理各种大小的数组,从而在电路代码中释放更大的灵活性和有效性。
  • 通过 Sonobe 集成实现 Folding Schemes:无缝地为 IVC(增量可验证计算)创建电路。特别适用于以下应用:EVM 上的比特币轻客户端、Rollup 和 zkVM。
  • 交互式在线 Playground:通过新的 Web 平台轻松地实验、学习和分享你的代码。
  • R1CS 优化:通过减少从 R1CS 后端生成的约束数量来提高性能。
  • Bug 修复和生活质量提升(Life improvements):许多社区贡献显着提高了语言的可用性和稳定性。

这些增强功能,加上我们充满活力的开源社区的宝贵贡献,已将 noname 转换为一种更加通用和用户友好的语言。在这篇文章中,我们将讨论这些更新的具体内容,概述我们将其变为现实的历程,并感谢我们的社区为推动这一进展做出的重大贡献。

通用大小数组(Generic-Sized Arrays)

我们正在进行的工作之一是增强标准库,使开发人员更容易开始使用 noname。我们面临的一个关键挑战是使该语言能够处理接受和返回各种大小的数组的函数。

最初,我们考虑在没有显式泛型(generic)功能的情况下进行管理,这受到了 GoLang 长期以来没有泛型功能的启发。但是,鉴于 noname 是一种类型化的 DSL,并且非常强调类型检查,我们意识到支持泛型类型的必要性。

为了解决这个问题,我们将泛型语法引入到语言中。最初,我们使用函数名称旁边的传统语法 <P> 来表示泛型参数。例如:

fn to_bits<LEN>(val: Field) -> [Field; LEN]
fn from_bits<LEN>(bits: [Field; LEN]) -> Field

我们的主要目标是在实现通用大小数组功能的同时,最大限度地减少代码库的更改。

我们最初计划放宽对泛型类型的某些类型检查,将其推迟到电路合成器阶段。这种方法类似于动态调度(dynamic dispatch)的概念,在合成器阶段保留和管理指针后面的底层结构,以传播常量值并解析泛型类型。

但是,这种方法无法在编译管道之后的合成器阶段之前解析泛型类型。这需要对合成器的假设进行重大更改,这些假设很大程度上基于具体类型。

最终,我们采用了另一种称为单态化(monomorphization)的方法。与其大量重构电路合成器,不如在管道中的单态化阶段处理泛型类型并将其解析为具体类型,然后再将其传递到电路合成器阶段。下图描述了该管道。

pipeline

通过单态化,合成器保持不变,无需适应新的泛型语法。与类型擦除相比,这种方法显着降低了复杂性和潜在风险。

让我们看一下单态化如何在代码级别工作:

fn main() {
    // 由于 to_bits / from_bits 是泛型函数,
    // 这将创建一个新的函数 AST 实例,位长度为 3
    let bits = to_bits::<3>(2);
    let val = from_bits::<3>(bits);

    assert_eq(val, 2);
}

在管道中传递单态化之后,它会根据泛型参数的不同常量值实例化泛型函数。这两个函数调用将指向新的函数实例,而不是原始的泛型函数 AST。

函数实例化过程会将泛型类型转换为具体类型,例如:

to_bits::<3>(2);

// 上面的函数调用将实例化 to_bits 函数,如下所示
fn to_bits(val: Field) -> [Field; 3]

因此,经过单态化后,返回值的泛型类型 [Field; LEN] 变为具体类型 [Field; 3]

我们还意识到 turbofish 语法 不必要地冗长。详细原因在 RFC 中进行了解释。

最终,它具有以下语法来表达泛型函数,该语法不太冗长且更自然:

fn to_bits(const LEN: Field, val: Field) -> [Field; LEN]
fn from_bits(bits: [Field; LEN]) -> Field

这允许将函数调用简化为:

fn main() {
    let bits = to_bits(3, 2);
    let val = from_bits(bits);

    assert_eq(val, 2);
}

有关单态化设计过程的更多详细信息,请参阅我们的第一个 RFC。我们仍在寻找有关设计和实施的反馈,因此请随时分享你的想法和建议。

通过 Sonobe 实现 Folding

Sonobe 是一个 IVC(增量可验证计算)框架,可简化用于 Folding Schemes 的电路开发。它有效地抽象了 Folding Schemes 的复杂性,使开发人员可以主要专注于实现核心 IVC 逻辑。

folding

Sonobe 通过处理周围的基础架构来促进 IVC 电路的集成。开发人员可以专注于定义函数 𝐹 的电路,如图所示。然后,它会管理计算序列并生成一个证明,以验证 IVC 过程的正确性。

潜在的应用包括计算一系列比特币区块链下转换的证明,然后在以太坊虚拟机 (EVM) 上对其进行验证。这意味着可以在 EVM 上实现比特币轻客户端。另一个有趣的应用可能是证明虚拟机 (VM) 的计算。由于 VM 中操作码的计算逻辑是固定的,因此将操作码与来自初始状态的输出一起输入始终会导致确定的最终状态。

为了使 noname 能够通过 Sonobe 支持 Folding Schemes,我们确定了两个简单的要求:

  • 与 arkwork R1CS 格式兼容。
  • 将 noname 集成为 Sonobe 中的新前端。

虽然 noname 已经支持生成与 SnarkJs 工具包兼容的 R1CS 电路,但它目前依赖于 Circom Rust 库,而不是 arkwork R1CS 库。因此,有必要为后者创建一个端口。

Pierre,Sonobe 的核心贡献者,发起了对 noname 集成的研究。他建议 noname 支持数组公开输出,这是一项重要功能。值得注意的是,社区的 erhant 迅速实施了该建议,并且 finiteprods 将该功能扩展到 支持所有类型 作为公开输出。

特别感谢 Pierre 和所有在 Sonobe 集成开发中发挥关键作用的贡献者。现在,你可以用 noname 编写电路,从而无缝地整合 Folding Schemes。

在线 Playground

在线 Playground 是一个用于快速共享和测试代码片段的宝贵工具。Logan 发现了这一需求,并 提出了一个建议 以提出一项开发,随后主动 实施了在线 Playground

playground1

如屏幕截图所示,与终端界面相比,Web UI 提供了更加直观的体验来浏览功能。它支持使用用户输入编译和运行 noname 代码。此外,它还提供了选择后端以显示汇编输出的选项,这对于检查和调试约束很有用。

playground2

由于 Logan 的努力,在线 Playground 代表了丰富开发体验的重大进步,尤其是在原型设计、测试和调试 noname 代码方面。即使在编辑器中没有用于 linting 和语法高亮显示的语言服务器的情况下,此 Playground 也可以通过提供具有用户友好 UI 的其他调试工具来解决现有差距。它可能会为未来的增强功能奠定基础,这些增强功能将继续改善开发人员体验并简化开发流程。

R1CS 优化

在重构以支持多个后端之后,我们向 noname 添加了 R1CS(Rank-1 Constraint System)后端,如我们在 之前的博客文章 中提到的那样。最初,每个操作都会在 R1CS 中生成一个约束,这是一种简单但幼稚的方法。证明系统的性能受到约束的大小和数量的显着影响,这使得优化至关重要。

为了提高性能,我们通过累积线性组合并仅在必要时添加约束来优化 R1CS 约束生成。具体来说,在比较相等性或算术乘法运算的情况下,需要约束。

此优化导致生成的约束数量显着减少。例如,考虑为 iterate.no 示例 生成的约束:

优化前:

v_3 == (v_1 + -1) * (1)
v_4 == (v_3 + 3) * (1)
v_4 == (v_2) * (1)

优化后:

v_1 + 2 == (v_2) * (1)

前两个约束是为加法和减法运算生成的,可以将其累积为中间线性组合。然后,在断言相等性时,累积的线性组合用于生成必要的约束。

虽然此优化显着提高了性能,但它给调试带来了挑战,因为约束不再与代码一一对应。为了解决这个问题,我们计划保留所有中间线性组合,以便可以将相应的操作追溯到代码。此调试信息可以 导出为 JSON 文件并在 Playground 中显示,从而帮助开发人员调试并确保约束的准确性。

来自社区的其他贡献

除了这些重大更新之外,许多社区贡献都显着增强了 noname。我们想向社区成员的以下宝贵努力致敬。我们非常感谢他们的支持。

增强功能

修复

  • 函数名和变量名之间的冲突:#125,作者:MohamedElqdusy
  • 允许不同 for 循环中使用相同的变量名:#152,作者:Prabhat1308
  • 当未使用私有输入时应抛出错误:#87,作者:vuvoth

文档

结论

我们希望这些有机的增强功能为开发人员提供更大的灵活性、效率和更直观的开发体验。再次,我们向所有参与此过程的贡献者表示衷心的感谢。

如果你有兴趣了解更多关于 noname 内部工作原理的信息,你可以查看 我们最新的代码演练视频

更多资源

  • 原文链接: blog.zksecurity.xyz/post...
  • 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
zksecurity
zksecurity
Security audits, development, and research for ZKP, FHE, and MPC applications, and more generally advanced cryptography.