TON生态中最大的玩法Notcoin上线,加上全流通代币经济模型引发的巨大财富效应,使得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 也只有 6.5 万,这显然不足以支撑百万级 TPS 需求的 Telegram 生态。同时,随着 Telegram 的大规模应用,其产生的数据量早已突破天际,而区块链作为一个极其冗余的分布式系统,要求网络中的每个节点都保存一份完整的数据,这也是不现实的。
因此,为了解决上述两个问题,TON对主流区块链协议做了两点优化:
- 采用“无限分片范式”设计系统,解决了数据冗余问题,从而可以承载大数据,缓解性能瓶颈问题;
- 通过引入基于Actor模型的全并行执行环境,大幅提升网络TPS;
做一条区块链——通过无限分片能力,每个账户都有一条专属的账户链
现在我们知道,分片已经成为大多数区块链协议提高性能、降低成本的主流方案,而 TON 则将这一点发挥到了极致,提出了无限分片范式。所谓无限分片范式,是指允许区块链根据网络负载动态增加或减少分片的数量。该范式使得 TON 能够在保持高性能的同时处理大规模交易和智能合约操作。理论上,TON 可以为每个账户建立一条专属的账户链,并通过一定的规则保证这些链之间的一致性。
抽象来说,TON 的链结构有四层:
- AccountChain:这一层链代表与某个账户相关的一系列交易组成的链。交易之所以能形成链式结构,是因为对于状态机来说,只要执行规则一致,状态机在接收到相同顺序的指令后,就会得到相同的结果。因此,所有区块链分布式系统都需要将交易以链式排序,TON 也不例外。账户链是 TON 网络中最基本的组成单元。通常,账户链是一个虚拟的概念,不太可能真正存在独立的账户链。
- ShardChain:在多数情况下,分片链是TON的实际组成单位,所谓分片链,就是账户链的集合。
- 工作链:也可以称为一组具有自定义规则的分片链,例如创建基于 EVM 的工作链并在其上运行 Solidity 智能合约。理论上,社区中的每个人都可以创建自己的工作链。实际上,构建它是一项相当复杂的任务,在此之前你必须支付(昂贵的)费用来创建它并获得 2/3 的验证者投票来批准创建你的工作链。
- 主链:最后,TON 中有一条称为主链的特殊链,它负责为所有分片链带来最终性。一旦分片链的区块的哈希值合并到主链的区块中,分片链区块及其所有父区块都被视为最终区块,这意味着它们可以被视为固定且不可变的内容,并被所有分片链的后续区块引用。
通过采用这样的范式,TON 网络具有以下三个特点:
- 动态分片:TON 可以自动拆分和合并分片链以适应负载变化。这意味着新区块总是可以快速生成,交易不会产生长时间的等待。
- 高度可扩展:通过无限分片范式,TON 能够支持几乎无限数量的分片,理论上最多可支持 2 的 60 次方个工作链。
- 适应性:当网络某部分的负载增加时,可以将此部分细分为更多分片,以处理增加的交易量。反之,当负载减少时,可以合并分片以提高效率。
那么这样的多链系统首先需要面对跨链通信的问题,尤其是因为无限分片的能力。当网络中的分片数量达到一定程度时,链间信息路由将成为一项艰巨的任务。想象一下网络中有 4 个节点,每个节点负责维护一条独立的工作链。链上的关系表明节点除了负责自己工作链中的交易排序工作外,还需要监视和处理目标链中的状态变化。在 TON 中,这是通过监视输出队列中的消息来实现的。
假设工作链 1 中的账户 A 想要发送一条消息给工作链 3 中的账户 C,那么就需要设计消息路由问题,在这个例子中,有两条路由路径,工作链 1 -> 工作链 2 -> 工作链 3,以及工作链 1 -> 工作链 4 -> 工作链 3。
当面对更加复杂的情况时,需要一种高效、低成本的路由算法来快速完成消息通信。TON选择了所谓的“超立方体路由算法”来实现跨链消息通信路由发现。所谓超立方体结构,是指一种特殊的网络拓扑结构。一个n维超立方体由2^n个顶点组成,每个顶点都可以用n位二进制数唯一标识。在这种结构中,任何两个顶点如果在二进制表示中仅相差一位,则它们是相邻的。例如,在3维超立方体中,顶点000和顶点001是相邻的,因为它们仅在最后一位不同。上面的例子是一个2维超立方体。
在超立方体路由协议中,消息从源工作链到目标工作链的路由过程是通过比较源工作链的二进制表示和目标工作链地址来进行的。路由算法找到两个地址之间的最小距离(即二进制表示中不同的位数),并通过相邻的工作链逐步转发信息,直至到达目标工作链。这种方法保证了数据包沿最短路径传输,从而提高了网络的通信效率。
当然,为了简化这个过程,TON 也提出了一个乐观的技术方案,当用户能够提供某条路由路径的有效证明,这个证明通常是一个 merkle trie 根时,节点就能直接识别出用户提交的消息的可信度,这也叫即时超立方体路由。
因此我们可以看出TON中的地址与其他区块链协议有显著不同,其他主流区块链协议大多采用椭圆加密算法生成的公私钥中公钥对应的哈希作为地址,因为地址仅用于唯一性区分,并不需要承载路由寻址的功能。TON中的地址由两部分组成,(workchain_id, account_id),其中workchain_id是按照超立方体路由算法地址进行编码的,这里就不再赘述了。
还有一点很容易让人产生怀疑,大家可能已经发现,主链和各工作链是相通的,那么所有跨链信息都可以通过主链进行中转,就像Cosmos一样。在TON的设计理念中,主链只用来处理最关键的任务,也就是维护众多工作链的最终性。通过主链路由消息也不是不可以,但产生的手续费会非常昂贵。
最后简单提一下它的共识算法。TON 采用的是 BFT+PoS 的方式,也就是任何一个 Staker 都有机会参与区块打包。TON 的选举治理合约会定期从所有 Staker 中随机选择一个打包的验证者集群,被选为验证者的节点通过 BFT 算法进行区块打包,如果打包错误或者恶意打包,其 Stake 的代币会被没收,否则会获得区块奖励。这个基本都是常见的选择,这里就不介绍了。
基于Actor模型的智能合约和完全并行执行环境
TON 与主流区块链协议的另一个不同之处在于其智能合约执行环境。为了突破主流区块链协议的 TPS 限制,TON 采用自下而上的设计方式,利用 Actor 模型重构智能合约及其执行方式,使其具备完全并行执行的能力。
基于Actor模型的智能合约和完全并行执行环境
TON 与主流区块链协议的另一个不同之处在于其智能合约执行环境。为了突破主流区块链协议的 TPS 限制,TON 采用自下而上的设计方式,利用 Actor 模型重构智能合约及其执行方式,使其具备完全并行执行的能力。
我们知道,主流区块链协议大多采用单线程串行执行环境。以以太坊为例,其执行环境EVM是一个以交易为输入的状态机。当出块节点通过打包区块完成交易排序后,就会按照这个顺序通过EVM执行交易。整个过程完全是串行、单线程的,也就是同一时刻只能执行一笔交易。这样做的好处是,只要确认了交易顺序,那么在广泛分布的集群中,执行结果就是一致的。同时,由于同一时刻只有一笔交易是串行执行的,意味着在执行过程中,其他交易不可能修改要访问的状态数据,从而实现智能合约之间的互操作性。比如我们通过Uniswap用USDT购买ETH,交易执行时,交易对中LP的分布是一定的值,因此可以通过一定的数学模型得到相应的结果。但如果不是这样,在执行联合曲线计算时,其他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中通用的范式,通常会有一个统一的路由器合约来管理交易路由,而各个Pool会分别管理某个交易对相关的LP数据。那么假设目前有两个池USDT-DAI和DAI-ETH,当用户想用USDT直接购买ETH时,可以通过路由器合约在一笔交易中依次请求这两个池,完成原子交易。但在TON中实现起来并不是那么容易,我们需要思考一个新的开发范式,如果还是复用这个范式,信息流可能是这样的,这个请求会伴随着一个用户发起的外部消息和三条内部消息(注意这里是为了说明区别,现实开发中,哪怕是ERC20范式也需要重新设计)。
2、跨合约调用时需要慎重考虑执行错误的处理流程,为每一次合约间调用设计相应的弹回函数。我们知道在主流的EVM中,当交易执行过程中出现问题时,整个交易都会被回滚,也就是重置到开始执行时的状态,这在串行单线程模型下很容易理解。但是在TON中,由于合约间调用是异步执行的,即使后续某个环节出现错误,由于之前成功执行的交易已经执行并确认,这也可能引发问题。因此在TON中设置了一种特殊的消息类型,称为弹回消息,即当内部消息触发的后续执行过程中出现错误时,被触发的合约可以通过触发合约预留的弹回函数,触发合约重置某些状态。
3.在一些复杂的情况下,先收到的交易可能不会先执行,因此这种时序关系无法预设。在这种异步和并行智能合约调用的系统中,可能很难定义处理操作的顺序。这就是为什么 TON 中的每条消息都有其逻辑时间 Lamport 时间(以下简称 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 中所有钱包地址都是智能合约,但并未初始化等,开发者需要注意。