当区块链遇上Rust —— 为什么Rust编程语言适合区块链开发
越来越多的著名区块链项目已经选择使用Rust作为其开发语言,包括但不限于 Parity, Polkadot, Substrate, Grin, Ethereum classic, Holochain, Cardano-rust, Exonum, Lighthouse, Nimiq, Nervos, Conflux-rust, Codechain, Witnet。本文试图探讨这一种趋势出现背后的原因。
Rust语言简介
Rust 是一门系统级编程语言,被设计为保证内存和线程安全,防止段错误产生。作为系统级编程语言,它的基本理念是 “零开销抽象”。理论上来说,它的速度与 C/C++ 同级。Rust 可以被归为通用的、多范式、编译型的编程语言,类似 C/C++。与这两门编程语言不同的是,Rust 是线程安全的!Rust 编程语言的目标是,创建一个安全和并发的软件系统。它强调安全性、并发和内存控制。尽管 Rust 借用了 C/C++ 的语法,却杜绝了空指针和悬挂指针,而这二者是 C/C++ 中系统崩溃、内存泄露和不安全代码的根源。
虽然 Rust 是一门系统级编程语言,但并不意味着它只能写底层程序(操作系统、驱动、工具、数据库、搜索引擎等),它的抽象层次之高完全给人惊艳的感觉,实践证明它对问题建模的能力和方便性不比 C++/Java/Python/Ruby 差。但 Haskell 这类超高抽象语言,也不是 Rust 的发展方向。Rust 力求在抽象与现实世界中找到一个平衡。
目前,Rust 已经在 StackOverflow 的年度语言评选中,连续 4 年荣获“程序员最喜爱语言”第一名(2016, 2017, 2018, 2019)。以下是 2019 年调查的截图:
img
Rust语言的历史
我们稍微提一下Rust的历史沿革。
Rust 最早是 Mozilla 雇员 Graydon Hoare 的一个个人项目,从 2009 年开始,得到了 Mozilla 研究院的支助,2010 年项目对外公布。2010 ~2011 年间实现的自举。从此以后,Rust 经历了巨大的设计变化和反复(历程极其艰辛),终于在 2015 年 5 月 15日发布了 1.0 版。在这个研发过程中,Rust 建立了一个强大活跃的社区,形成了一整套完善稳定的项目贡献机制(这是真正的可怕之处)。Rust 现在由 Rust 项目开发者社区(https://github.com/rust-lang/rust )维护。
下图描述了Rust的基因图谱:
img
Rust语言目前的状态
Rust从1.0算起,到目前(2019年5月)为止,已有长足的发展。但整体而言,比起,Python、C、C++ 等,Rust 的使用并不算特别广泛(毕竟太年轻)。调查显示,Rust 使用率不高的很大一部分原因是选择 Rust 的公司占少数。
img
不过,Rust 在工作中的占比也越来越高。过去一年间,Rust 在商业应用上有着令人惊讶的成长。下面是部分人们熟知的公司:
亚马逊:用 Rust 构建工具
Facebook:源代码控制工具
Google:作为 Fuchsia 项目的一部分
微软:在新的 Azure 物联网框架中部分使用 Rust
Twitter:用 Rust 作为构建团队支持的一部分
国内的百度,阿里,也已经在内部小范围的使用上了Rust(https://rustforce.net.cn/section?id=17dd744e-429a-42b1-8d30-01d31d556ab0)。
相信,随着更多公司对 Rust 的选择,Rust 的成长速度将更加迅猛。
Rust与区块链
第一个将Rust应用于著名区块链项目的应该是大名鼎鼎的Gavin Wood博士(https://www.jianshu.com/p/cca7e4f46b86)。Gavin Wood 博士在 2015 年下半年离开了以太坊社区,创立了 Parity Technologies,推出以太坊(Ethereum)客户端 parity,成功占领以太坊社区的半壁江山(https://www.ethernodes.org/network/1)。而这个 parity 客户端就是使用Rust写的。
实际在 parity 出现之前,MaidSafe项目(https://safenetwork.tech/)就已经出现了。MaidSafe用 Rust 语言尝试了很多东西(https://github.com/maidsafe)。Rust语言本身强调的安全性以及MaidSafe这些前沿项目,可能给了 Gavin 充分的理由选择 Rust 作为 parity 开发语言。
Rust本身的语言特性(安全、高性能、并发编程)与区块链的特性(分布式、加密、安全敏感)天生有相当大的重合性。下面我们看看从实际的著名项目中得到的一些反馈。
Parity
以下部分节选自:https://www.parity.io/why-rust/
编程很困难,不是因为硬件很复杂,而仅仅是因为我们是人。我们的注意力有限,记忆也易失,换句话说,我们人类倾向于犯错。
在由测试检查的程序正确性和由逻辑证明的程序正确性两者之间,有一个巨大的区别。即使我们对每一行代码都做了测试,我们仍然不能保证它是正确的。形式化证明则可以保证我们的代码是正确的(至少在某些方面)。
Rust作为一个编程语言显得不同,不是因为它的语法多么漂亮(实际有些人甚至觉得有点丑)或者社区多么受人欢迎,而是因为当用它写代码时获得的那种信心。
看起来Rust会影响你写代码的的效率和表达力,但令人相当惊奇的是,结论完全相反:写一个有效率的、符合习惯的Rust程序比写一个有潜在危险的程序容易得多。
下面是Linux内核在2018年一月到四月期间发现的bug:
img
而对于Rust而言,上图右侧占比 51% 的部分,从语言层面就可以避免。也就是说,对Rust来说,根本不存在上图右边这些问题。
两种观点,“一个人只需要知道如何写C” 和 “只需要把最底层的东西留给专业人士”,这两种观点都是不够的。Linux内核是由强中强的程序员写的,可能是工业界最前面的5%的程序员,但是,仍然,年复一年地搞出 CVE 来。
你有可能会觉得几百万行代码中出现50个bug不算什么。但在一些关键领域,出bug就意味着系统性风险(如,心脏起博器中的bug会导致生命危险)。而且,这50个bug是我们已经找到的,谁知道我们还有多少个bug还没找到?而用了Rust,我们可以事先知道答案。
厉害的是,Rust在实现内存安全和并发安全的同时,并没有以损失性能为代价。更牛逼的是,它甚至是用同一套抽象解决了内存安全和数据竞争这两个不同领域的问题。
Rust的零开销抽象让你在享受安全性的同时,又不损失性能。这正是传统的程序员梦寐以求的。
Parity使用Rust,正是因为用Rust写复杂和高性能的代码时,不用担惊受怕。用Rust写程序,远离未定义行为、数据竞争和内存安全问题。更别说,Rust运行速度快,写起来有趣,易读,还几乎没有运行时。
内存安全问题如此困难,因为你无法容易地写出测试来捕获它们。如果你在beta阶段之前没有找出bug,那么这个bug就可能会在代码中呆几年,就像一个读秒的定时炸弹。当然,也有Valgrind这类的工具,来辅助你捕获这些bug。但是如果在执行时,没有触发内存问题,或这类工具生成的代码在运行时,没有执行,那么它们也捕获不到。
所以,通过使用Rust,我们消除了一大类最复杂和最不可预测的错误。
Rust中内嵌了形式化证明理论,不过仅限于对内存安全和并发。Rust在内部用逻辑证明了你的程序是正确的。这也就是你为什么写Rust代码会写得如此有信心的原因。你的每一次编译,都有一组数学理论在为你提供证明服务。
在很长一段时间内,像Haskell这种函数式编程语言的一大杀手级特性就是可以比较容易地进行形式化证明,而这对于传统的命令式编程语言是不可能的(因为有共享可变性,不安全的指针运算,和不可控的副作用)。但Rust的出现,改变了这种情况,作为一个命令式语言,它却走在被证明的路上。到目前为止,标准库的一部分已经被证明是正确的(https://www.ralfj.de/blog/2017/07/08/rustbelt.html)。
Parity也希望未来能把这些理念带入parity的代码中,证明它们的正确性。
综合上述原因,Rust正在成为一个最先进的主流通用目的语言之一,可以用来写可靠的、安全的、高效的程序。
Solana、Zcash、Parity 的一次对话
以下节选自:https://medium.com/solana-labs/solana-at-portland-dev-meetup-72e4dc7ad32c 和 https://zhuanlan.zhihu.com/p/46123567
本篇是「Solana 、Zcash 和Parity 三家会面讨论为什么Rust适合区块链开发 」,因为是视频转录的文字,加上视频本身在有些地方录制的效果问题,所以经常有口齿不清的情况,所以翻译主要是意译,并且可能跳过一些无意义的文字。
*Anatoly: 我的Rust经历实际上是来自于上一份工作,在Dropbox的时候,用Rust编写压缩相关的工作。当时,没有使用标准库的内存分配器,自己实现了一个类型安全的沙箱。非常酷。但是在开始这个项目之前,Rust并没有吸引我。
*我用了两周时间使用C语言,但是当用到一些外部库的时候,还得写makefile,手动下载这些库,比较麻烦。所以,我决定尝试一下Rust。就在那一刻,“Holy shit, this is amazing.”。我才觉醒到,这是一个和C语言一样快的语言,并且还给了我Haskell般的类型安全。Rust击中了我,这真的很酷。
*Jack: Rust击中我并不是因为速度或者其他因素。那是很久以后的事了,就像我现在才非常关心编写正式的Rust代码,才发现Rust中真正有趣的东西。(慢热)
*但是最初的时候是因为我之前写C#,总是碰到运行时错误。因为这种动态类型,完全没有经过类型检查。我都无法列出遇到过的运行时错误数量了,感觉随便一个简单的操作都能碰到错误。给我的感觉是,这根本不像是编程,因为我还得处理这些运行时的错误(代码里感觉像多了很多“废话”,不精炼)。但是Rust就没有这种感觉。我喜欢Rust的人体工程学,比如包管理、类型安全和Null指针安全等。
*Anatoly: Sean呢?
*Sean: 是的,对我来说也是一样的。速度,可以说是一个我为什么用Rust工作的合理的解释。我可以说,“哦,好吧,它非常快,而且很容易合作,而且非常容易审核”等等。
*但实际上,当我第一次学习Rust的时候,我的感觉是,“我再次爱上了编程”。因为我不太想再次求助于Haskell了(在某些情况下)。当然,Haskell很棒。
*Jack:Haskell有太多的return废话了。
*Sean: Rust将我的编程心智模型和程序思维恰到好处的结合了起来,我太喜欢这些概念了。当我第一次使用Rust的时候,它和现在有很大不同,还有垃圾回收之类的内容。但是过去这几年发生了变化,随着时间的推移它会更加优雅。我想这就是为什么我非常喜欢它的原因之一,就是我看到它的改进比原来越来越好。
*Greg: 这些年我涉足了很多不同的编程语言。C、C++、Haskell、Python等。而且每一次,我都尽力在每个项目上只选择两种语言。我会说,“好吧,如果我想做这些高级的东西,我会选择Python,如果我想选函数式类型的东西,我会选Haskell,当我想做一些底层的东西,我会选C++”。我在这些跨语言交互过渡中被折磨了多次。这真的非常艰难,尤其是涉及垃圾回收的时候,实际上不可组合。
*然后,C++那里没有垃圾回收也没有安全性可言。如果你用C++给Python写个插件,突然间你的程序就崩溃了。它不应该崩溃,对吗?但它就是崩溃了。因此,Rust对我来说,就是一股新鲜空气。我现在使用Rust这一种语言就可以完成整个软件堆栈的绝大部分功能,而不必切换语言了。
*Jack: 我认为C++其实也不是完全不安全的。它还是安全的,但它的安全只存在于简单的情况下,但是当处理复杂的情况,就不安全了。表现就像安全性是一个谎言一样。
*Greg: 你是指未定义行为吧?
*Jack: 是的。
*Greg: 所以,假设你的程序有一个整数溢出,它只是在你正在使用的编译器中出现,但是在语言定义中并没有定义整数溢出的情况,这就是未定义行为。你的编译器允许是允许做任何事情的,任何事情。
*当然,它也许不会出现在你正使用的编译器中。然后你升级编译器,它就崩溃了。或者它在其他人的库中发生崩溃,因为它们有整数溢出,这就很烦。 (原文太长,有兴趣者自行翻阅)
Grin
以下内容摘自grin邮件列表:https://lists.launchpad.net/mimblewimble/msg00258.html 及其相关回复。
Alberto Garcia:为什么你们会选择Rust,我认为他建了一道障碍,阻止了那些对这个项目感兴趣但是对这个语言又不熟悉的人参与进来。
Yeastplume:我没有参与做原始的决定,但是Rust提供了一整套安全机制,需要你花点时间去学习和适应,一旦学会,你写的代码就会如你期望的运作,几乎没有需要硬着头皮跟踪的在C/C++中称为特性的指针/内存分配/缓存溢出/强制转换/任何你能想到的那些问题。因此,就意味着调试、测试奇怪的内存问题所花的时间会减少。在C中,你可以在头脑中约定该做什么不该做什么,但是在Rust中,没有这些心智负担。至于你说到的“障碍”。如果这个障碍能把那些连一个语言都学不会或不愿学的“工程师”排除在外,我觉得这个障碍挺好的。说话可能严厉了点,但是我找不到更好的词来描述我的情绪了。
Alberto Garcia: 我只是好奇,我觉得这个项目像这样增长的话,它最后会难以移植。
Andrew Poelstra: 把一个项目从Rust移植到一个不安全的,弱类型,数据结构不丰富的语言,在我看来,是鲁莽的和无意义的事情。即使是这样,从Rust项目移植到其它语言应该会比从c/c++项目中移植要简单一些。
Nervos
本文节选自:https://medium.com/@Aimeedeer/why-rust-c877fba0ca94
如果你是一个开发者,你应该已经发现Rust社区非常友善活跃,这会给你很大的信心。新的学习者常常会被Rust编译器教育一阵。然后,当你能适应它时,你就会爱上它。有人说Rust让他重新爱上了编程,因为一旦编译完成,你就不需要额外担心了。
人们爱Rust,因为
性能:无GC,无运行时,内存安全,可以与其它语言方便地集成。
可靠性:所有权模型保证。
生产力:良好的编译器会把你变成一个杰出的开发者。
构建一个加密项目需要涉及到密码学、数学 、博弈论、经济学等等。现在已经有很多前沿的密码学如零知识证明,环签名等已经用Rust实现了,以后还会更多。P2P网络和24/7服务的网络对可靠性和性能也有很高的要求。这些方面的技术进步很快,需要一个伟大的语言来加速区块链的技术迭代和原型验证。
Bitcoin,Zcash, Ethereum 和一些密码学库是C++实现的。Fabric,Ethereum Geth 和 IPFS 是 Go 实现的(其目的是替代C++的实现)。Cardano和Dfinity是用Haskell实现的,因为这个语言强大的类型系统。Python,Kotlin, Java 也在某些方面发挥了作用。
但是我们看到了一个清晰的趋势是,项目和开发者都在从C++转向Rust。
Rust优化了整体系统。性能比肩(甚至超过)C++,编写效率堪比Go。能直接掌控资源,防止内存,数据竞争等问题。总结起来,就是Rust是一门被设计为面向控制的语言。
桌子上有Haskell, Erlang, Java, C++, Go 和 Rust,我们该选哪个?前两个很难,招聘是个问题。Java,Go和C++之间,我们喜欢C++的速度和Go的开发效率。
Rust吸收了历史上很多语言的精华,成为一门现代语言。Nervos团队非常欣赏Rust的理念。我们的哲学是追求完美。不仅是架构上,还有实现细节上,都要做到追求完美。为了追求高性能所以我们不会选择带GC的语言,所以我们选择了Rust。
顺便说一句,之前还有个故事,对我们有重大影响。Ethereum 之前遭受过一次 DDoS 攻击,它影响了所有Go和Rust写的客户端。因为Rust客户端在攻击之后还能正常运行,所以所有的矿节点都转向了Rust客户端,而其中很多到目前为止还在使用Rust客户端。
Rust社区的开放气度和胸襟我们也非常敬佩。Rust的RFC流程非常优秀,所以Nervos也采用了这种模式。
另外,Nervos还在线下定期举办Rust碰面会。
Rust区块链项目介绍
下面是一些比较知名的区块链项目的介绍。
parity
parity 是一个以太坊节点客户端 parity-ethereum(https://github.com/paritytech/parity-ethereum)。Parity Technologies 是他们公司的名称。现在 Parity 旗下已经包含了一套客户端和各种库。
parity-ethereum(https://github.com/paritytech/parity-ethereum)
parity-zcash(https://github.com/paritytech/parity-zcash)
parity-bitcoin(https://github.com/paritytech/parity-bitcoin)
shasper(https://github.com/paritytech/shasper)
也就是说,Parity Technologies 给使用Rust开发区块链提供了一套“全家桶”。
polkadot/substrate
Polkadot 是由Web3基金会发起的一项计划,由 Parity Technologies 负责开发,旨在却不限于使区块链互联。Polkadot 使开发者和企业能够利用其协议建立区块链,即平行链(parachain)。只要这些平行链建立在Polkadot的基础之上,它们将共享同样的权威证明(PoA)共识。由于该类型共识嵌于 Polkadot 中,平行链开发者可以专注于各自区块链的特异性。所有平行链都和一种被称为中继链(relay chain)的通用区块链无缝连接,后者扮演连接所有平行链的角色。
Polkadot 项目由Gavin Wood主导推进,其实跟上面的parity全家桶属于同一家公司,但属于不同的团队在做。
如果你实时关注了 Polkadot 的进展状况,你可能会经常看到“Substrate”这个词。它是 Polkadot 项目的重要组成部分。Parity Substrate 是独立于 Polkadot 的项目。Polkadot 基于 Substrate ,其它基于 Substrate 的项目也能在 Polkadot 网络上运行(形成一个生态)。
那么什么是 Substrate 呢?你可以将其看作类似于 Express 或其他 Web 应用程序的框架,但它是用于构建分布式或去中心化的系统的框架,可以构建例如加密货币项目,或消息总线系统。正如大多数 Web 应用程序不需要重新实现自己的 HTTP 协议一样,对于每一个团队创建新链时,也不需要从头实现网络和共识的代码,这浪费精力。更不用提为了实现业务逻辑,必须雇用密码学家、安全研究员、网络工程师、开发人员(以协调更新)等等了。如果你使用 Substrate 来构建一个新项目,只需要在代码中实现少量的函数回调,就可以轻松快速创建一条链。
https://github.com/paritytech/polkadot
https://github.com/paritytech/substrate
grin
grin是当今区块链界小网红。少数旨在成为真正货币的项目之一。Grin 致力于提供隐私、可扩展性的加密货币,计划在 2019 年初发布。其几个独特的属性:使用名为 MimbleWimble 隐私保护区块链格式;只在区块链中存储少量数据,运行完整节点既便宜又容易;Mimblewimble 由匿名人士开发,团队分布在世界各地;没有任何预挖的 PoW 机制,更平等和去中心化。
grin的出现,预示着回归比特币的一股潮流的出现,也许,这才是这一类项目正确的方向。
参与gin的开发交流,相当令人愉悦。
https://baijiahao.baidu.com/s?id=1622722985158161430&wfr=spider&for=pc
https://github.com/mimblewimble/grin
holochain
Holochain致力于解决Dapp落地的事情,也就是说,它在构建一个云托管网络。
当人们都在研究如何把区块链性能提高的时候,Holochain却在做造汽车的事。有时候思维固化并非好事,换一种思维方式或许就可以找到解决问题的新路径。正如Holochain官网上的文字一样:Think outside the blocks。
Holochain这个项目很有意思,它不是狭义上的区块链。人们研究区块链本质上是在研究通过解决信任问题完成价值传输,从而完成生产关系改变。为了达到最终目的,我们不一定要把眼光仅限于某种特定技术上。无论是区块链、DAG、Holochain,只要能达到我们最终目的,那么都可以认为是好的技术。
区块链中为了保证信息一致性,系统中每个节点都是一个单独的账本,这些账本记录同样的信息。虽然,区块链这种分布式账本技术满足了一致性,但却造成了巨大的信息冗余。
Holochain认为共识是可以分化的,没必要所有的事件都去共识。因此它创新的从另一个角度去解决共识问题。Holochain将一个账本分割成若干份,交给每一个参与节点,并通过DHT技术和密码学技术保证账本之间的一致性。简单来说,我们可以把DHT的作用理解为拼图上的图画,我们可以通过图画来判断这个拼图是否完整。
节点不再需要多账本同步记录,只需要记录与自身相关的内容就可以达成全网共识,这就是Holochain的革新之处。
https://github.com/holochain/holochain-rust
nervos
首先,Nervos 要做什么?官网上说,Nervos 是要 Building a layered infrastructure for the future crypto economy. 分层的方式也是现在区块链主流体系设计,Layer 1 发行原生资产,支持高安全性高去中心化,牺牲效率。而 Layer 2 去做 scalability 的事情。那么 Nervos CKB 作为体系的 Layer 1,主要有以下两个目的:也就是资产的储存和协议的增强(安全性和去中心化)。注意,这也是 Nervos CKB 经济体系设计的原则,即资产储存大于价值交换。
几个有趣的设计亮点:
解决通缩与通胀的问题。
解决手续费的问题Nervos CKB 的一个理念是,智能合约平台的价值除了原生代币外,还应包含平台上发行的其他加密资产的价值。
解决资源的价格问题。
解决利率的发现与调整问题。
https://blog.csdn.net/weixin_42677624/article/details/88387887
https://github.com/nervosnetwork/ckb
exonum
由 Bitbury 出品。是一套使用Rust开发的许可链开发框架。使用exonum,可以方便的搭建联盟链。
https://github.com/exonum/exonum
结语
作为一个刚刚4岁的语言(今天2019年5月15日,是Rust语言正式发布4周年生日),Rust语言正在IT工业各个领域快速发展,而由于区块链本身的特质,区块链领域是较早接纳Rust的领域之一。在区块链领域,Rust正以势如破竹之势占领区块链新兴项目市场,很多著名的老项目也在考虑转向使用Rust重写。
与此同时,WebAssembly技术的飞速发展带来的成果也及时地应用到了区块链中。Rust对WebAssembly提供了一等支持(可能是所有语言中目前为止最好的),具体请参考 https://rustforce.net/article?id=6807cc27-0e6c-4bc9-baa3-8b0c68ae9529。
相信,随着Rust语言的 async/await 特性在今年的稳定,使用Rust进行区块链开发会变成更加轻松方便。选择使用Rust作为第一开发语言的区块链项目也会越来越多,我们会迎来一波的Rust语言学习高潮。
谨以本文作为Rust 4周年的生日礼物,祝Rust生日快乐!
本文由 Rust 中文社区(rust.cc, rustforce.net)Mike 整理撰写,版权所有。
2019-05-15