Solidity 团队发布了一系列名为 "通往核心 Solidity 之路" 的博文,分享了该语言的未来发展方向。
由 Solidity 团队于 2025 年 10 月 21 日发布
Solidity 刚刚迎来了它的 10 周年。 对于我们来说,这是一个绝佳的机会来展示 “通往 Core Solidity 之路” ,这是一系列博客文章,我们将通过这些文章分享该语言的未来发展方向。
在这个系列中,我们想向社区展示我们如何从长远角度看待该项目的路线图。 虽然我们对其总体方向非常有信心,但许多细节尚未确定。 这既是对未来发展方向的展示,也是对语言未来发展讨论的邀请,以及对建设性反馈的请求。
这第一篇博文简要介绍了长期路线图的每个部分。 所有这些主题都将在本系列中进行深入探讨:
...还有更多!
今年团队发生了一些变化,其中一些对我们的计划产生了重大影响:
我们打算在 Devconnect 周期间于阿根廷举行的 Solidity Summit 2025 上,提供更多关于团队能力以及获取更多资源以用于项目正在进行和未来开发的最新消息。
在深入了解具体细节之前,让我们先明确该语言本身的未来。
构思它的环境与今天截然不同。 当时唯一真正的替代方案是 LLL - 一种受 Lisp 启发的非常底层的语言, 与其说类似于 Solidity,不如说更像 Yul - 以及 Serpent - 一种 pythonic 语言,是 Vyper 的精神先驱。 这两者都是 EVM 语言发展的重要步骤,但也存在重大缺陷,这些缺陷影响了 Solidity 的设计。
一开始,Solidity 的重点是人体工程学和引入适当的高级抽象。 对于从通用语言过渡过来的程序员来说,熟悉度也是一个重要的考虑因素,并且可能是 Solidity 受欢迎程度的重要原因之一。 虽然安全性和正确性一直被认为是重要的,但只是逐渐地,它们才成为凌驾于其他考虑因素之上的因素。 该语言受到了智能合约黑客攻击漫长历史以及针对它们的对策的影响。 它不断适应,变得更加严格和明确。
不幸的是,在不断变化的首要任务下,有机增长导致了大量的 技术债务、不必要的复杂性和许多不一致之处。 与此同时,该语言仍然不完整,并且缺少诸如泛型之类的重要功能。 特别是,如果要将它们移植到当前的类型系统上,这将是一项复杂的 undertaking。 这样的任务将带来引入关键错误的巨大风险。
因此,我们决定采用不同的方法来解决这个问题,这导致该语言的工作被分为两个独立的轨道:
Core Solidity 目前处于原型阶段,所有设计工作都在 solcore 存储库 中进行。 该工作的结果将是新的语言规范,然后将在 solc 中实现为新的编译器前端,与 Classic Solidity 共享后端。 Solidity 1.0 将标志着 Core Solidity 变得足够稳定,可以作为 solc 中的默认前端。
我们目前的大部分工作都集中在后端改进上,这将使 Classic 和 Core Solidity 受益。 长期以来,重点主要放在解决 IR pipeline 中的长期问题上,以便默认启用它并弃用旧的 evmasm pipeline。 另一个重要的方向是 ethdebug 规范的实现。 最后,始终需要一些努力来支持对底层平台所做的更改。
IR pipeline 存在长期存在的问题,这些问题阻止它成为默认设置并完全取代 evmasm pipeline。 我们正在多个方面解决这些问题。
首先,优化器 pipeline 存在不确定性问题,如果将不相关的源文件添加到编译中,则生成的字节码可能会更改。 当 Yul AST 节点的内部 ID 无意中影响 IR pipeline 中执行的操作顺序时(通常在优化器中),通常会出现这些问题。 目前,这些内部 ID 只是基于代码生成器生成的标识符,其中包括 Solidity AST ID,以此来保持唯一性。 我们的目标是通过为内部 ID 切换到本地的、顺序的数值来缓解这种情况,使其独立于全局 Solidity AST。
除此之外,IR pipeline 目前的编译时间很长。 虽然 ID 处理的更改有所帮助,但根本问题更多地与某些优化器步骤的高算法复杂性有关。 因此,我们正在重建 pipeline 的内部表示和代码生成,遵循在主要编译器中证明的设计模式,并针对 EVM 的独特约束对其进行调整。 特别是,我们正在将 Yul IR 转换为 control-flow graph (CFG) 中的 static single-assignment form (SSA)。 这种 SSA-CFG 结构不仅与广泛使用的表示形式保持一致,而且还支持更有效的数据流优化过程 - 从而缓解了上述算法复杂性问题。
为了支持这项工作,我们与马德里 Complutense 大学的 COSTA 团队 合作开展 GreY 项目。 该团队以他们在 Circom 2 和 GASOL 上的工作而闻名。 该项目最初是一个以太坊基金会资助项目,目前在 Argot Collective 下继续进行,旨在开发用于将从 Yul 生成的 SSA-CFG 转换为 EVM 字节码的新型贪婪算法。 因此,它不仅可以作为 Solidity 未来 IR 到 EVM 字节码转换的方法论和理论基础,而且还可以在节省 gas 方面带来巨大的胜利。
虽然前面的段落侧重于编译器性能,但生成的字节码在部署合约和与之交互所需的 gas 方面的性能同样重要。 在从 Solidity 过渡到 Yul IR 的过程中,某些优化所需的某些语义信息会丢失,或者至少更难恢复,尤其是类型信息和内存布局细节。 为了解决这个问题,我们正在探索通过类型和可能的内存对象来丰富 Yul 的方法。 我们还在评估其他中间表示形式,例如 Sonatina 或诸如 MLIR 之类的工具,以定义从 Solidity 到 Yul 的更渐进的降低。这些途径可以保留更多的语义,并在不同的抽象级别上实现更强大的优化过程。
我们的长期目标之一是改善调试体验。 当前编译器提供的调试信息有限,并且在代码优化后会显着降低。 IR pipeline 引入的复杂混排以提供更好的堆栈分配也无济于事。
ethdebug 规范正在解决此需求, 该规范建立了一种与编译器无关的格式,该格式提供了对合约代码和数据布局的丰富描述。 该规范的初始版本已接近完成,并且正在进行参考实现的开发。
现在,该规范正在 Solidity 编译器中实现。 在 solc 0.8.29 中,我们发布了对规范一部分的实验性支持,该部分将源代码映射到字节码中的相应指令。 虽然此信息已经以源映射 的形式提供,但这只是规范的一部分,并且输出将在将来的版本中扩展,以涵盖 所有 ethdebug schemas。
在内部,一个主要缺失的部分是对优化器的支持,这是整个工作的重点。 挑战在于在优化步骤中保留调试信息,因为某些优化会破坏源代码和生成的指令之间简单的 1:1 关系。 在此过程中,块可能会被复制或合并,并且必须对调试注释应用等效的转换。
以太坊升级中包含的大多数 EIP 解决了共识层,或者至少解决了执行层中不直接影响编译器的方面。 确实影响编译器的通常相对较小。 最近的例子是 Fusaka 升级中引入的 CLZ 操作码(EIP-7939)。 另一个例子是 PAY 操作码 (EIP-5920),这将需要引入一个新的内置函数来取代有问题的 .send() 和 .transfer()。
我们预计未来分叉中进行的其他更改包括代码大小限制的调整(EIP-7907/EIP-7903)、操作码的定价 (EIP-7904) 或内存 (EIP-7923)。 这些都不一定需要影响代码生成,但在许多情况下,优化器的选择都受到估计的 gas 成本的指导,这将需要更新它们。 某些启发式方法也可能需要调整 - 例如,更便宜的跳转会影响内联权衡。 从更大的角度来看,某些操作或模式变得更便宜可以实现迄今为止被认为不可行的解决方案。
虽然我们已经看到尝试在即将到来的 EVM 升级中恢复 EOF,但由于 Ipsilon 团队(他们是其开发的主要力量)的解散,我们预计这是不可行的。 但是,有几个较小的提案,解决了同一组问题的一部分,例如 Greg Colvin 的 EIP-7979 和EIP-8013。 虽然两者都是最近的提案,但值得注意的是,它们是他早期的提案的延续,这些提案旨在 消除静态跳转并引入子例程,这比 EOF 早得多。 最后,EIP-8024 可能是绕过围绕操作码立即参数的问题并提供对堆栈更大部分的访问的一种方法。
计划引入的 Verkle trees 是即将到来的最大变化。 虽然有益,但这样的变化将是一项艰巨的任务,并且需要我们重新思考一些根深蒂固的语言机制和约定。 例如,storage 中动态数组的数据区域与其大小字段不位于同一位置这一事实可能必须更改,因为它依赖于所有存储槽的定价都是统一的这一假设。 同样,以块为单位读取和定价代码将对编译器如何在二进制文件中布局它引入新的约束。 特别是,首次访问数据段将在不适合单个块的合约中导致额外的惩罚。
长期以来,我们一直不愿向 Classic Solidity 添加过多的新语言特性,并进一步复杂化其实现,同时也可能引入设计元素,这将限制我们在 Core Solidity 中的选择。 我们希望能够快速完成 Core Solidity,并在其基础上以更少的精力来实现它们。 一些作为新的标准库的一部分,一些作为语法糖,这两者都会带来更少的维护负担和更好的可扩展性。 该语言本质上处于软功能冻结状态。
随着 Core Solidity 的范围变得更加清晰,并且它演变为一个单独的子项目, 我们已决定更改此方法,并将 Classic Solidity 稍微向前推进, 只要它不与新前端的长期方向相冲突。
“Classic Solidity 的未来:路线图愿望清单” - 本系列即将发布的帖子之一 - 将展示一个语言功能列表,我们仍然乐于在当前语言中实现这些功能,该列表按所需的实现和设计工作量以及当 Core Solidity 接管时,它将在长期内提供的价值进行分类。 它将附带每个功能的详细描述、已知的困难和设计选项。
我们预计在转向 Core Solidity 之前,我们将无法交付所有这些功能。 这并不意味着它们将被放弃。 虽然它们可能永远不会出现在 Classic Solidity 中,但我们认为其中许多功能对于 Solidity 的长期发展至关重要,并且能够使用新的语言机制构建它们正是我们从一开始的目标。
0.9 重大版本与任何重要的新功能无关。 我们目前正在进行的所有工作都可以以非破坏性的方式引入,最多只有一些细节被推迟到这样的版本。 总体主题将是简化和删除已弃用的功能,以消除代码库中积累的一些技术债务。
最大的变化包括切换到 IR pipeline 并默认启用优化器。 我们还计划删除对旧 EVM 版本和过时语言功能的支持,例如.send()/.transfer() 内置函数或虚拟修饰符。 SMTChecker 将放弃对 BMC 的支持,并将重命名为 SolCMC。
0.10 及更高版本的计划不太具体。 我们希望删除更多过时的元素,并且我们可能会以重大方式调整现有功能,以解决它们的一些设计问题 (继承、try..catch、构造函数评估顺序等)。 但是,就功能而言,总体主题将是与 Core Solidity 的融合。
我们对 Core Solidity 的目标之一是使从当前语言的过渡尽可能顺利。 当然,这在许多方面都是一项重大更改,但表面语法的更改将比内部结构的更改少得多。 该计划的一部分是将 Classic Solidity 的语法更接近我们在 一系列重大版本中希望在 Core Solidity 中拥有的最终状态,从而使更改更加渐进。 此类更改可能包括:
合约不需要用相同的语言编写,也可以通过外部调用进行互操作。 它们只需要使用相同的 ABI,这自然会在 Classic 和 Core Solidity 之间实现。 但是,我们计划在互操作性方面走得更远。 我们希望能够使两种语言在同一项目中并排使用。
实现此目标的第一步是为两个前端提供一个通用的编译接口。 这将使编译器能够提供以任一语言编写的源代码,作为同一组输入的一部分。 用一种语言编写的合约必须完全独立于用另一种语言编写的合约,并且将产生不同的输出(字节码、AST 等),但这些输出将由编译器组合成一个通用结构,而不是按语言分隔。
第二步将在函数级别启用兼容性。 我们将使可以从另一种语言中导入和调用以一种语言编写的自由函数。 这还可能包括接口定义、错误、事件和某些类型。
Core Solidity 是对 Solidity 类型系统的大部分向后兼容的升级。 它从像 Lean 和 Haskell 这样的纯函数式语言,以及像 Rust 和 Zig 这样的现代系统语言中汲取思想,并根据我们从 Classic Solidity 中学到的知识,将它们适应 EVM 环境。
这种转变将代表 Solidity 的功能和表达能力的一大步。 Classic Solidity 中的大多数高级语言功能都可以定义为标准库构造,并简化为一种名为 SAIL 的极简内部语言。 SAIL 本身是有意设计得尽可能精简,同时仍然支持核心功能:
这是一种语言设计和编译器构建方法,通常用于其他高保证领域(例如,定理证明器),并且支持我们围绕正确性/形式规范和语言的长期社区管理的目标。
我们的总体目标之一是拥有一个非常简单且灵活的语言核心,其中大部分 当前功能集都在语言中定义,即它的标准库。 如今,扩展编译器很困难,因此,它无法从 渴望贡献的应用程序开发人员的丰富实践经验中受益。 我们最终希望为该库的管理建立一个社区驱动的 EIP 风格流程,并鼓励主要以这种方式完成扩展。
标准库应该有多广泛? 不同的语言对此问题的回答不同,并且没有正确或错误的答案。 有些,如 C,采用极简主义路线,只提供编译器提供的基本实用程序。 另一些,如 Java 或 Python,是“包含所有内容”的,并提供了开箱即用的大量高级工具。
出于必要,Solidity 最初将采用极简主义,因为这是我们计划降低编译器维护负担的方式。 该库将包含一小组低级实用程序、基本类型定义以及当今作为编译器固定部分存在的其他元素。 它是会无限期地保持这种状态,还是会发展成为一个功能齐全的常见模式集合, 以适应各种各样的用例,这仍然是一个悬而未决的问题,并且需要通过社区驱动的过程来决定。 只有在建立了这样的过程之后,一个丰富的标准库才有可能在第一个地方实现。
Classic Solidity 的一个很大的缺点是缺乏语言规范。 不幸的是,当前形式的语言带有太多的包袱。 我们不想将其作为事物应有的方式而加以确立。 我们普遍认为,它已经达到了这样的复杂程度,以至于定义形式语言语义将需要大量的精力。 即使有了所有这些工作,它仍然只能充当临时措施,而不能实际解决根本问题。
相反,Core Solidity 足够小以进行形式化,并且从一开始就是以这样的规范为目标而构建的。 我们希望能够交付一种语言的可执行形式规范,该规范可用于验证类型系统本身的完整性以及以 Core 编写的应用程序代码。 这种可执行语义还应该能够充当参考实现,可用于模糊测试新实现。
我们还希望避免语言碎片化。 随着越来越多的竞争编译器出现,我们认为它们都 通过遵循相同的规范,同时在生成的代码质量、优化方面展开竞争,并且可能通过标准库的替代实现来使最终用户受益。 一旦语言稳定下来,我们将建立一个开放的过程来进一步开发它。
我们计划定期发布新博文作为本系列的一部分,并希望邀请社区积极参与,帮助我们塑造 Solidity 的未来。
我们已经启动了一个 论坛主题,以促进对该系列即将发布部分的反馈和公开讨论。我们请读者花时间浏览本博文中分享的概述,并通过在论坛主题下方分享他们的想法来参与到未来的过程中。
- 原文链接: soliditylang.org/blog/20...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!