详述TON的技术特点与智能合约开发范式

转载
199 天前
2492
马里奥看Web3

文章转载来源: 马里奥看Web3

作者@Web3Mario

引言:随着币安上线TON生态最大的游戏Notcoin以及由全流通token经济模型所引发的巨量财富效应,TON在短时间内即取得了极大的关注。和朋友聊了下得知TON的技术门槛比较高,而且DApp开发范式与主流公链协议有很大的差异,因此花了一些时间深入研究了一下相关课题,有些心得体会,与诸君分享。简而言之,TON的核心设计理念是以一种“自下而上”的方式重构传统的区块链协议,并以舍弃互操作性为代价,实现对高并发和高可扩展性的极致追求。

TON的核心设计思想——高并发与高可扩展性

可以这么说,TON中所有复杂的技术选型的目的都来自于对高并发与高可扩展性的追求,当然从其诞生的背景我们也不难理解这一点。TON,即The Open Network,是一个去中心化的计算网络,包含一个L1区块链和多个组件。TON最初由Telegram的创始人Nikolai Durov及其团队共同开发,而发展到现在则由全球独立贡献者的社区支持并维护。其诞生要追溯到2017年,Telegram团队开始为自己探索区块链解决方案。由于当时没有现有的L1区块链能够支持Telegram的九位数用户基础,他们决定设计自己的区块链,当时称为Telegram Open Network。时间来到了2018年,为了获得实现TON所需的资源,Telegram在2018年第一季度发起了Gram代币(后来改名为Toncoin)的销售。2020年由于监管问题,Telegram团队退出了TON项目。随后,一小部分开源开发者和Telegram比赛获胜者接手了TON的代码库,将项目名称更名为The Open Network,并继续积极地开发区块链至今,且遵循原始TON白皮书中概述的原则。

那么既然是以作为Telegram的去中心化执行环境作为设计目标,自然要面对两个问题,高并发请求与海量数据,我们知道随着技术发展到现在,号称TPS最高的Solana实测最高TPS也只有65000,这显然不足以支撑百万级TPS要求的Telegram生态。与此同时随着Telegram的大规模应用,其产生的数据量早已突破天际,而区块链作为一个极度冗余的分布式系统,若要求网络中每个节点都保存一份完整的数据,这也是不现实的。

因此为了解决上述两个问题,TON对主流的区块链协议做出了两个方面的优化:

  • 通过采用“无限分片范式”(Infinite Sharding Paradigm)设计系统,解决数据冗余问题,使其可以承载大数据,同时缓解性能瓶颈问题;
  • 通过引入基于Actor模型的完全并行执行环境,极大的提升网络TPS;

做区块链的链——通过无限分片能力让每个账户都有一条专属的账户链

当下我们知道,分片(sharding)已经成为了大部分区块链协议提升性能降低成本的主流方案,而TON则将这点做到了极致,并提出了无限分片范式,所谓无限分片范式,指的是允许区块链根据网络负载动态地增加或减少分片数量。这种范式使得TON能够在保持高性能的同时,处理大规模的交易和智能合约操作,理论上TON可以为每个账户都建立一条专属的账户链,并通过一定的规则保证这些链之间的一致性,

抽象的来理解,在TON中一共存在四层链结构:

  • 账户链(AccountChain):该层链表示与某个账户相关的一系列交易所组成的链,之所以交易可以组成链式结构,是因为对于一个状态机来说,只要执行规则一致,状态机在接收到相同顺序的指令后得到的结果是一致的,因此所有区块链分布式系统中都需要对交易进行链式排序,TON也不例外。账户链是TON网络中最基本的组成单元,通常情况下账户链是一个虚拟的概念,不太可能真正存在一个独立的账户链。
  • 分片链(ShardChain):在大部分的语境下,分片链才是TON中实际的组成单元,所谓分片链,即为一组账户链的集合。
  • 工作链(WorkChain):也可以叫做一组有自定义规则的分片链,例如创建一个基于EVM的工作链,在其上运行Solidity智能合约。理论上,社区中的每个人都可以创建自己的工作链。事实上,构建它是一个相当复杂的任务,在此之前还要支付创建它的(昂贵)费用,并获得验证者的2/3的票数来批准创建你的工作链。
  • 主链(MasterChain):最后在TON中有一条特殊的链被称为主链,该链负责为所有分片链带来最终性。一旦分片链的区块的哈希值被合并到主链的区块中,该分片链区块及其所有父区块被认为具有最终性,这意味着它们可以被认为是固定且不可变的内容,而被所有分片链的后续区块引用。

通过采用这样的范式,使TON网络具备以下三个特点:

  • 动态分片: TON可以自动拆分和合并分片链以适应负载的变化。这意味着新块总是快速生成,而交易不会产生很长的等待时间。
  • 高度可扩展:通过无限分片范式,TON能够支持几乎无限数量的分片,理论上可以达到2的60次方个工作链。
  • 自适应性: 当网络中的某个部分负载增加时,该部分可以被细分成更多的分片来处理增加的交易量。相反,当负载减少时,分片可以合并以提高效率。

那么这样一个多链系统,首先需要面临的就是跨链通信问题,尤其是由于具有无限分片的能力,当网络中的分片数量达到一定量级后,链与链之间的信息路由将成为一件困难的事情。试想一下网络中共有4个节点,每个节点负责维护1条独立的工作链,其中链接关系表示该节点除了负责自身的工作链中交易排序工作之外,还需要监听并处理目标链中状态变化,在TON中具体通过监听输出队列的消息实现,

假设工作链1中的账户A希望向工作链3中的账户C发送一个消息。则需要设计到消息路由问题,在这个例子中有两条路由路径,工作链1 -> 工作链2-> 工作链3,工作链1 -> 工作链4 -> 工作链3。

当面临更复杂的情况时,就需要一个高效且低成本的路由算法快速完成消息通信,TON选择了所谓“超立方体路由算法”来实现跨链消息通信路由发现。所谓超立方体结构指的是一种特殊的网络拓扑结构,一个n维超立方体是由2^n个顶点组成的,每个顶点都可以通过一个n位的二进制数来唯一标识。在这个结构中,任意两个顶点如果在二进制表示中只有一位不同,那么它们就是相邻的。例如,在一个3维超立方体中,顶点000和顶点001是相邻的,因为它们只在最后一位上不同。而上述例子即是一个2维超立方体。

在超立方体路由协议中,消息将从源工作链到目标工作链的路由过程是通过比较源工作链和目标工作链地址的二进制表示来进行的。路由算法会找到这两个地址之间的最小距离(即二进制表示中不同位的数量),并通过相邻工作链逐步转发信息,直到达到目标工作链。这种方法能够确保数据包沿着最短路径传输,从而提高了网络的通信效率。

当然为了简化这个过程,TON也提出了一个乐观技术方案,当用户可以提供对某个路由路径的有效证明,这通常是某个merkle trie root,节点即可直接承认该用户提交的消息的可信性,这也被称为即时超立方体路由。

因此我们可以看到TON中的地址和其他区块链协议有着明显的区别,其他主流区块链协议大都采用椭圆加密算法生成的公私钥中公钥对应的哈希作为地址,因为地址只是做唯一性区分,而不需要承载路由寻址的功能,而TON中的地址有两部分组成,(workchain_id, account_id),其中workchain_id即按照超立方体路由算法地址进行编码,在这里就不详细展开了。

还有一个容易产生疑问的点,你可能已经发觉到主链和每个工作链均有链接关系,那么所有跨链信息均通过主链做中继不就可以了么,就像是cosmos那样。在TON的设计理念中,主链仅用于处理最关键的任务,即维护众多工作链的最终性,将消息通过主链做路由也不是不行,只是由此产生的手续费用将十分昂贵。

最后简单提一下其共识算法,TON采用了BFT+PoS的方式,即任意staker均有机会参与区块打包,TON的选举治理合约会每隔一段时间,从所有Stakers中随机选择一个打包的验证者集群,被选中称为验证者的节点将通过BFT算法打包出块,若打包错误信息或作恶,其stake的token将会被罚没,反之将得到出块奖励。这基本上已经是一个比较常见的选择了,因此不在这里展开介绍。

基于Actor模型的智能合约和完全并行执行环境

TON中另一个与主流区块链协议不同的点是其智能合约执行环境。为了突破主流区块链协议TPS的限制,TON采用了自下而上的设计思路,采用Actor模型重构了智能合约及其执行方式,使其具备了完全并行执行的能力。

我们知道主流的区块链协议大都采用的是单线程串行的执行环境,以Ethereum为例,其执行环境EVM是一个以交易作为输入的状态机,当出块节点通过打包区块完成对交易的排序后,将以该顺序通过EVM执行交易,整个过程是完全串行并单线程的,即某个时刻只能有一笔被执行,这样做的好处是只要确认了交易顺序,执行的结果在广泛的分布式集群中就具有一致性,与此同时由于同时只有一笔交易被串行执行,这就意味着在执行过程中,不可能存在其他交易对某待访问状态数据进行修改,这样就实现了智能合约之间的互操作性。例如我们通过Uniswap使用USDT购买ETH,当该交易被执行时,该交易对中LP的分布情况即为一个确定值,这样就可以通过某些数学模型得出对应的结果,但假设情况不是这样的,在执行某bonding curve的计算时,有其他LP添加了新的流动性,那么计算结果将会是一个过时的结果,这显然是不可接受的。

但是这种架构也有明显的局限性,那就是TPS的瓶颈,而这个瓶颈在当前多核处理器下显得很老旧,就像你用一个最新的PC去玩一些老的电脑游戏,比如红警,当作战单位多到一定数量后,依然会发现卡的不行,这就是软件架构的问题。

你可能会听到一些协议已经在关注这个问题,并提出了自己的并行方案,以当前号称TPS最高的Solana为例,也具备并行执行的能力。只不过其设计思路与TON不同,在Solana中,其核心思想是将所有交易按照执行依赖关系分为几组,不同组之间不共享任何状态数据。即不存在相同的依赖,这样不同组内的交易就可以并行执行而不用担心出现冲突的情况,而对于同组内的交易,则还是沿用传统的串行方式执行。

而在TON中,其完全舍弃了串行执行的架构,转而采用了一个专为并行而生的开发范式,Actor模型来重构执行环境。所谓Actor模型是由Carl Hewitt在1973年首次提出,目的是通过消息传递来解决传统并发程序中共享状态的复杂性问题。每个Actor都有自己的私有状态和行为,且与其他Actor之间不共享任何状态信息。Actor模型是一种并发计算的计算模型,它通过消息传递来实现并行计算。在这个模型中,"Actor"是基本的工作单元,它能够处理接收的消息、创建新的Actor、发送更多消息、决定如何响应接下来的消息。Actor模型需要具备以下几个特性:

  • 封装和独立性:每个Actor在处理消息时都是完全独立的,可以并行处理消息而不会互相干扰。
  • 消息传递:Actor之间仅通过发送和接收消息进行交互,消息传递是异步的。
  • 动态结构:Actor可以在运行时创建更多的Actor,这种动态性使得Actor模型能够根据需要扩展系统。

 

TON采用了这个架构,来设计智能合约模型,这就意味着在TON中,每个智能合约都是一个Actor模型,其具备完全独立的存储空间。因为不依赖任何外部数据。除此之外,对同一个智能合约的调用还是按照接收队列中消息的排序进行执行,因此TON中的交易将可以被高效的并行执行,而不需要担心冲突问题。

然而这样的设计方案也带来了一些全新的影响,对于DApp开发者来说,其习惯的开发范式将被打破,具体如下:

1.智能合约之间的异步调用:在TON的智能合约内部是无法原子性的调用外部合约或访问外部合约数据的,我们知道在Solidity中,合约A的function1中调用合约B的function2,或者通过合约C的只读function3访问某状态数据,整个过程是原子性的,在一笔交易中被执行,这是一件非常容易的事情,然而在TON中,这将不可能实现,任何与外部智能合约的交互都将通过打包新的交易异步执行,这种由智能合约发起的交易也被称为内部消息。且执行过程中无法阻塞以获得执行结果。

例如我们开发一个DEX,如果采用EVM中常见的范式,通常会有一个统一的router合约用于管理交易路由,而每个Pool都单独管理某个交易对相关的LP数据,那么假设当前有两个池子USDT-DAI和DAI-ETH。当用户希望通过USDT直接购买ETH,就可以通过router合约在一笔交易中顺序请求这两个池子,完成原子性交易。然而在TON中就没有这么容易实现了,需要思考新的开发范式,若仍然复用该该范式的话,那信息流可能是这样的,这个请求将伴随一个由用户发起的external message和三个internal messages完成(注意这是用于说明差异性的,真实的开发中甚至连ERC20的范式也要重新设计)。

2.需要仔细考虑跨合约调用时出现执行错误情况的处理流程,为每个合约间调用设计相应的弹回(bounce)函数。我们知道在主流的EVM中,当交易执行时遇到问题时,整个交易将会被回滚,即被重置到执行最初时的状态。这在串行单线程模型中是容易理解的。然而在TON中,由于合约间调用采用了异步的方式执行,即使后续某环节出错,由于前面已经被成功执行的交易已经被执行并确认,这就有可能造成问题。因此TON中设置了一种特殊的消息类型,叫做弹回消息,即当某内部消息触发的后续执行过程出现错误时,被触发合约可以通过触发合约预留的弹回函数将触发合约中的某些状态重置。

3.在某些复杂情况下,先被接收的交易不一定先被执行完毕,因此不可以预设这种时序关系。在这样一个异步和并行智能合约调用的系统中,定义处理操作顺序可能很难。这就是为什么 TON 中的每个消息都有它的逻辑时间Lamport time(后面简称 lt)。它用于理解哪个事件引发了另一个以及验证者首先需要处理什么。对于一个简单的模型,先被接收的交易一定先被执行完成。

在这个模型中,A和B分别表示两个智能合约,则有如果 msg1_lt < msg2_lt,则tx1_lt < tx2_lt的时序关系。

然而在较为复杂的情况下,这个规则就会被打破。在官方文档中有这样的例子,假设我们有三个合约A、B和C。在一笔交易中,A发送两个内部消息msg1和msg2:一个给B,另一个给C。尽管它们是按确切顺序创建的(先msg1,然后是msg2),但我们无法确定msg1 将在msg2之前被处理。这是因为从 A 到 B 和从 A 到 C 的路由可能在长度和验证者集中有所不同。如果这些合约位于不同的分片链中,其中一条消息可能需要几个区块才能到达目标合约。即我们有两种可能的交易路径,如图所示。

4.在TON中,其智能合约的持久化存储采用了一个以Cell为单元的有向无环图作为数据结构,数据将按照编码规则紧凑的压缩为一个Cell,同时按照有向无环图的方式向下延伸,这与EVM中状态数据基于hashmap的结构组织不同,由于数据请求算法的不同,TON中为不同深度的数据处理设置了不同的Gas价格,越深的Cell数据处理所需要的Gas越高,因此在TON中存在一种DOS攻击的范式,即某些恶意用户通过发送大量垃圾消息占用某个智能合约中所有的浅层Cell,这就意味着诚实用户的存储成本将越来越高。而在EVM中,由于hashmap的查询复杂度为o(1),因此有着相同的Gas,不会有类似问题。所以TON Dapp开发者应该尽量避免智能合约中出现无界数据类型。当出现无界数据类型时,应通过分片的方式将其打散。

5.还有一些特征则不那么特殊了,例如智能合约需要为存储支付租金,在TON中智能合约天然是可升级的,以及原生的抽象账户功能,即在TON中所有钱包地址均为智能合约,只是未被初始化等,这些需要开发者小心留意。

以上是这段时间我学习TON相关技术的一些心得,与诸君分享,有写错的地方还望大家指正,与此同时,我认为凭借着Telegram天量的流量资源,TON生态一定会为Web3带来一些全新的应用,有对TON DApp开发感兴趣的小伙伴也可以联系我,和我们一起讨论。

X Links: https://x.com/web3_mario