人人都能懂的新公链 Aptos 技术深度揭秘
R Labs 聚焦于 Web3 深度行研、投融资及孵化,致力于为更多人打开 Web3 世界的大门。
公链又火了。
在今年3月份和7月份相继完成由a16z和Framework Ventures分别领投的两轮共计3.5亿美元融资之后,据媒体报道,Aptos近期又得到了Binance Labs的一轮战略投资。作为炙手可热的Move系新公链的代表,Aptos频频占据了媒体头条,在熊市燃起了一把热火。在近期顺利完成了AIT3阶段的激励测试网测试之后,Aptos也即将迎来主网正式上线的时刻。这家脱胎于Facebook Diem的公链,在主网上线之前已经汇集了200多个项目基于其生态进行建设,让人不禁要问,这条让投资人和开发者趋之若鹜的公链到底有什么魅力。
Aptos以安全性和高性能著称,其背后离不开强大的技术实力。相比于目前主流的以太坊等区块链,Aptos的诞生相对较晚,也因此能够利用区块链行业在多年的发展过程中积累下的经验,进行有针对性的系统设计,力求用技术创新解决Web3应用大面积推广所面临的瓶颈问题。
本文是R Labs对Aptos的系列研究文章的第一篇,将对Aptos区块链的技术特点一探究竟。
Aptos白皮书详尽阐释了其所采用的技术,总的来说可以概括为以下六个方面。
1)使用Move语言(编程层面的安全保障)
Aptos区块链原生地集成和使用Move语言,以使transaction的执行更快速,更安全。Aptos的Move验证机(Move prover)会对使用Move语言编写的智能合约进行验证,提供了额外的安全保障。
2)更安全的用户体验(用户角度的安全保障)
Aptos提供灵活的密钥管理功能,比如用户可以轮换(rotate)密钥。
Aptos提供transaction预执行的功能,使用户可以在对transaction真正签名之前提前预知transaction的执行结果,保证了结果的透明性。
3)高吞吐量低延迟
Aptos将transaction的处理过程(transaction processing)细分为了五个模块:transaction传播(transaction dissemination)、区块元数据排序(block metadata ordering)、transaction并行执行(parallel transaction execution)、批量存储(batch storage)、账本验证(ledger certification)。这种模块化加上流水线的处理方式,提高了整个transaction处理过程的并行程度。
4)Block-STM并行执行引擎
在transaction并行执行模块,Aptos使用了Block-STM引擎,在无需由程序员预先声明数据读写操作特征的情况下,实现了支持原子性的最大程度的并行执行。
5)支持升级
Aptos的模块化(modular)架构设计,提供了嵌入式的链上变动管理协议,使得升级可以非常方便的得以实现。
6)分片(sharding)
Aptos的模块化设计和并行执行引擎都很自然的支持分片,便于Aptos吞吐量的横向扩展。
R 观点:
Aptos的以上特点可谓正中要害,切中了目前阻碍Web3领域发展的底层基础设施的痛点。例如在用户安全方面,在目前的很多应用场景中,用户经常需要对一串无法识读的编码进行签名,这带来了信任和安全方面的一系列问题,因为用户无从知道自己签名授权的行为到底是什么。然而Aptos的transaction预执行功能,可以让用户明确transaction的后果之后,再进行签名,这极大降低了信任的门槛,方便了用户的使用。
接下来,R Labs将选取Aptos在安全性和高性能方面的特点,展开进行剖析。
在监管政策之外,区块链自身的安全和性能,是目前Web3世界中引发关注最多的问题之一。
2022年上半年,全网发生了187起区块链安全事件,总损失高达19.76亿美元。另一方面,由于区块链的性能与目前市场上爆发的大量需求的不匹配,使用区块链作为底层基础设施仍然非常昂贵。以以太坊为例,即使是在合并之后,以太坊上的平均交易费(average transaction cost)仍然高达0.9美元。所有人都期待,Web3世界的IT基础设施性能,也能像摩尔定律所描述的那样不断提升。在这样的背景之下,Aptos在提升安全性和性能方面的技术特点就尤为重要。在众多特性之中,我们把关注的重点放到了Move语言和Aptos的并行执行引擎Block-STM。
Move作为一门编程语言,其诞生非常具有结果导向性。当Facebook的团队在开发区块链时,他们认为市面上没有一款能完美契合区块链开发的计算机编程语言。诸如C++、Java等传统编程语言自不必说,即使像Solidity这样流传甚广的区块链开发语言,在Facebook的工程师团队看来,仍不尽完美。于是他们从第一性的原理出发,分析了区块链这种新的IT基础设施架构对编程语言提出的要求。
适用于区块链的编程语言必须具备以下特性
确定性(deterministic)。区块链是一个分布式状态机,每一段代码的执行都必须形成确定性的结果,才能保证所有节点所维持的账本处于一致的状态。
类型和内存安全(type and memory safe)。区块链是一个开放的平台,任何人都可以调用智能合约。如果没有类型和内存安全的保障,那么区块链就会很容易受到攻击。
可度量的执行(metered execution)。为了确保所有使用区块链的用户能合理的使用网络、计算和存储资源,必须对区块链执行的所有操作进行度量。例如以太坊等区块链使用Gas的机制来度量和约束用户对系统的操作。
除了以上必备的特性之外,一个更好的区块链语言还应该具备以下特点
对定制化资产的语言层面的支持(language support for custom asset)。目前很多区块链都支持定制化资产,例如在以太坊上构建的项目可以发行自己的项目代币。但是在编程语言层面,支持这种定制化资产的特性仍然十分匮乏。
代码跨合约复用(code reuse across contracts)。智能合约代码如果像传统编程语言中的代码一样,可以在不同的模块之间复用,那么就可以极大的提升生产力。
语言跨平台复用(language reuse across platforms)。如果一门编程语言能够在多个不同的区块链上使用,那么程序员的学习成本就会大大降低。
R 观点:
Move从以上角度出发进行设计,是更适用于区块链的编程语言。R Labs认为,在基于区块链技术所构建的Web3世界,加密资产是一大核心。Move语言对定制化资产的支持,也是其最有代表性的特点。
对于资产来说,最重要的属性之一是稀缺性。在物理世界中,实物资产自然而然具有稀缺性。例如,当人们使用贵金属进行交易时,贵金属从买方转移到卖方,发生了物理上的转移。但是在传统的计算机虚拟世界里,资产仅仅被用数字进行表示,资产的增减就对应于数字的加减,所有的合理性都依赖于程序员编写代码时的谨慎。然而随着系统复杂度的提升,这种谨慎是难以保证的。物理世界中资产的稀缺性,并不能通过计算机中的数值来简单的模拟,资产的安全性也就随之大打折扣。接下来,R Labs将通过一段简单易懂的代码,来展示Move与其他区块链编程语言在抽象化资产时的不同处理方式。
我们以Solidity为例,下面的一段Solidity代码实现了转账的功能。这段代码实现了地址A对地址B的转账,实现的方式是对A和B各自对应账户的余额数字进行加减。
下面的代码是另一个错误的版本,在这个错误版本中,转入方的账户余额数字的确增加了,但是转出方的账户余额数字并没有减少。这是一个低级的错误,如果程序员没有仔细审查代码,这种错误就会成功通过编译被部署上线。
一般而言,程序员用高级编程语言所写的代码要经过编译器,转变为计算机指令,才能由计算机识别和执行。而在编译的过程中,编译器会检查代码中有没有语法错误。Solidity程序也遵循类似的过程。但是由于在上述的Solidity程序中,资产仅以普通的数值类型(integer)进行表示,那么只要是符合数值运算的操作,都能通过编译器的编译。编译器并不会检查资产是否凭空增加或减少了。
针对这种潜在的问题,Move语言内置了一种特殊的数据类型,Resource。程序员可以在代码中定义一种Resource类型的资产。例如下面这段代码中定义了一种名为Coin的Resource。
虽然最终,这个资产的多少仍然是以内部变量value的数值来衡量,但是代码中对Resouce类型实例的任何操作,都会经过Move编译器的审查,而编译器会禁止对资产的不当操作。如下图所示的复制、双花和隐式的销毁,在未特殊声明的情况下,都会被编译器阻止。
在使用Move语言编写合约的时候,最重要的事情就是思考如何定义 Resource 的属性。Move 编程语言抽象了资源的四个属性,可复制 ( copy )、可索引 ( key )、可毁灭 ( drop )、可储存 ( store )。通过这四个属性的不同组合,用户可以方便的定义出任何类型的资源。这种针对 Resource 的设计天然就保证了一些常见的安全问题,比如复制增发,不会再出现。
Move 通过对资源操作权限的抽象,使得用户可以明确定义资源可被操作的行为,从而将自己的注意力转移至其他更应该被关注的地方,编写正确的业务逻辑,实现正确的访问控制策略等等。
如前文所述,Aptos采取了多种技术来提升transaction处理的效率。
transaction执行(execution)是整个transaction处理过程中最核心的环节。为了保证区块链上各个节点执行区块中的transaction后所得结果的一致性,目前大部分区块链使用的是线性执行的方式,这大大限制了transaction的执行效率,也就限制了区块链的性能。突破性能瓶颈的关键,就在于如何提升transaction执行的并行性。
Aptos团队设计并实现了一个高效的,多线程的,基于内存的并行执行引擎。该引擎把STM(software transactional memory)技术与一种新型的协作调度机制结合,最终实现了每秒钟可以执行超过160,000条Move transaction的性能。
STM并不是一门新的技术,早在1995年,Shavit和Touitou就提出了STM。相比较于HTM(hardware transactional memory),STM不依赖于硬件实现,也曾是一项令人激动的技术创新。
STM是一种乐观并发控制技术,用来解决多线程系统中的并发问题。在一个多线程并发执行的系统中,如果多个线程共同访问同一块内存地址,有可能会引起冲突,进而导致数据出现不一致的问题。
要理解Block-STM,需要先理解多线程系统的并发控制问题,以及STM的解决思路。接下来,R Labs以一个简单的例子来进行解释。
在一个银行系统中,银行同时收到了客户的两笔支付请求,分别需要支付1万元,总共2万元。为了提高处理速度,银行让两位员工同时来处理,每一个员工负责处理一笔支付请求。在这里,两个员工可以类比于计算机系统中的两个线程。银行员工必须按照银行的工作手册规定的流程来服务客户,工作手册可以类比于计算机程序代码。为了处理客户的支付请求,银行员工需要查询唯一一本银行账本,银行账本可类比于计算机的内存。
在一种可能的错误场景中,两位银行员工同时去读取银行账本,读到客户的账户余额均为10万元。两位员工各自按照工作手册,为客户进行支付操作,各自将客户余额在10万元的基础上减去1万元,两位员工得到的结果都是“客户余额还剩9万元”。之后,两位员工将各自得到的支付结果(余额9万元)写回了银行账本。在这个例子里,客户明明花掉了2万元,但是因为银行的工作流程中使用了多线程(两名员工同时处理),却没有做好同步控制,导致最终在账本上记下了一个错误的数据。
为了解决这种问题,常见的做法是用“锁”的方式来进行并发控制。对于像访问银行账本这种“竞争性资源”的操作,我们可以在系统中规定,每次只有一位员工能访问。我们把唯一的银行账本放入保险柜中,任何一位员工需要进行账本相关的操作时,都需要先将账本从保险柜中取到自己的工位,完成工作之后,再将账本放回保险柜。这种机制保证了在同一时间,只有一位员工可以访问银行账本。但是,可想而知,如果银行业务中涉及大量访问账本的工作,那么业务员就需要在保险柜前排起长队了。
STM试图去提高并发控制系统的效率,采用的是一种乐观的方式。STM假设,大部分的银行员工来访问银行账本的时候,都是在服务不同的客户,各自的任务在账本上发生冲突的可能性比较小。如果是这种情况,那么把账本锁在保险柜,每次只允许一个人操作的规定,就显得有些浪费资源了。STM允许所有员工同时访问账本,并要求每个员工在读取账本的时候,在自己所读取的数据旁边贴一个小标签;每个员工在自己的草稿本上进行计算等工作,当员工要将计算结果写回账本时,先检查自己之前读的数据或将要写的数据旁边,有没有别人贴过的标签,此过程称为验证(validation);如果没有,则可以顺利将自己的计算结果写回,并撕掉自己之前贴过的标签;如果有,则意味着有其他员工正在访问自己所操作的数据,为了避免这种访问冲突造成错误的账本数据,就需要废弃(abort)自己本次所做的工作,等待稍后重新执行(re-execution)。
STM的思路看上去很美丽,但是在实际应用中,由于访问冲突时常存在,废弃(abort)和重新执行(re-execution)也导致了很大的系统开销。因此,STM在实际的生产环境中很少被使用。
在区块链世界中,时常会发生用户对热门智能合约的集中大量访问,例如在有套利机会出现时。因此链上的transaction实际上也可能会产生大量的访问冲突,这似乎与STM适用场景的假设相背离。然而,事物皆有两面,Aptos团队对区块链的特征进行了深入的分析,发现区块链的另外一些特征也给STM的应用打开了一扇门:
1)区块链中无须逐条提交transaction
在通用的STM系统中(general purpose STM),每个线程都会及时提交(commit)执行过的transaction。而在区块链中,状态的更新是以区块为单位的,因此可以对一个区块中的transaction一次性批量延迟提交,从而避免逐条提交transaction所带来的同步的成本。采用这种方式,虚拟机的垃圾回收也将变得非常的简明直白——区块一旦被提交,对应的内存就可以清理掉了。
2)虚拟机为乐观内存访问提供了安全性
智能合约是用Move这样的高级编程语言声明的,而transaction的执行是运行在Move虚拟机中的。虚拟机会把transaction的执行封装起来,提供了更高层面的安全保证。
3)预定义的顺序减少了同步性
通用STM系统(general purposee STM)是用于解决非确定性系统中的并发控制问题,而把确定性视为一种制约,其性能也相应地受到限制。这也使得通用STM系统不适合应用于区块链,因为验证者们执行同一个区块可能会导致不一样的最终状态。然而如果设计一种运行在区块链上的STM系统,区块链内在要求的确定性(保证并行执行最终结果能匹配transaction按固定的预设顺序的线性执行结果)反而有利于性能。这背后的原因是,对一个特定序列达成一致,会减少执行过程中所要求的同步的数量。
基于以上分析,Aptos团队结合STM的思想和一种新型的调度器,实现了Block-STM,一种在区块链上使用乐观并发控制的并行执行引擎。transaction在Block-STM中的生命周期被分为execution,validation和commit三个阶段。Block-STM的核心思想包括以下几个方面:
1)多版本数据结构(multiversion data structure)
Block-STM使用一个多版本的数据结构来避免写操作之间的冲突。所有对相同地址的写操作与其版本被一同存储,包括transaction ID和这个执行写操作的transaction被乐观地重复执行的次数。当有一个transaction读取一个内存地址的时候,它会从多版本数据结构中获取预设顺序中出现在它之前的最早的transaction,以及与其关联的版本信息。
2)transaction的执行和验证
在execution阶段,transaction会记录一个内存读集和内存写集(即这条transaction在执行时所读或者写的内存数据)。在验证期间,内存读集中的所有内存地址上即刻的数值都会被读取,读到的版本会与存储在读集中的相应的版本做比较。如果发现不一致,则意味着transaction执行时所读到的数据过期了,那么这条transaction有可能需要被重新执行。
3)协调调度
调度器为区块中排序较为靠前的transaction赋予了较高的执行优先级,并使用计数器(counter),而非有序集(ordered set)或优先队列(priority queue)的方式进行了实现。
4)动态依赖预估(dynamic dependency estimation)
当一条transaction在验证过程中失败时,这条transaction最近一次执行的所有的写操作会在多版本数据结构中被标注出来,作为一个预估。当另一个transaction从多版本数据结构中读到一条被标记为“预估”的值,它就等待,而非立即执行,以免后续需要返工。
Aptos团队对Block-STM引擎进行了测试,结果体现在下图中。蓝色曲线代表使用Block-STM并在测试数据中设置1万个账户的情况(读写冲突较多),黑色线条代表线性执行的情况。在使用32个线程所进行的测试中,使用Block-STM引擎实现的TPS达到了160k,是线性执行引擎的TPS(10k)的16倍。
R 观点:
Aptos团队的研究让STM这项技术焕发了新的生机。从比特币区块链的诞生到现在,虽然已经过去了十多年的时间,但与整个计算机科学相比,区块链仍然是一种非常年轻的架构,未来也一定会有更多基于计算机科学的深厚积累上的创新。像Aptos一样,我们相信公链领域仍然会有激动人心的机会。
公链是整个Web3最重要的基础架构,公链的性能能否扩展决定了整个生态的发展。得性能者得天下。资本的加持、开发者的汇聚也会逐渐形成马太效应。这一轮,Aptos已经赢得了先机。
Aptos的技术亮点还有很多,本文从编程语言方面和事务执行引擎方面,选取了Aptos最具代表性的技术特点进行了分析。
互联网诞生到现在已经经历了50年,从web1和web2时代的信息互联网,到即将迎来的web3时代的价值互联网,网络所发挥的功能和创造的价值发生了巨大的变化,而每一个重要节点的背后,都离不开技术的创新、更迭。Aptos深厚的技术功底是它能够吸引众多关注的根本原因。
在R Labs对Aptos的系列研究文章的下一篇中,我们将深度剖析Aptos自身的生态建设,以及宏观对比Move系列的其他新公链,继续从多个角度全面解读Aptos。
telegram
R Labs 聚焦于Web3深度行研、投融资及项目孵化。我们为Web3领域所迸发的一切创新感到激动,也坚信认知是一切投资的基石。
欢迎有idea的innovator和有志投资于Web3的investor联系我们,共赴新的星辰大海。
微信扫码关注该文公众号作者