Ton与ETH的一些独特的区别


前言

TON区块链是一个现代化的区块链,它为智能合约开发带来了一些全新的理念。它是在以太坊推出后设计的,有机会学习EVM模型中哪些做得好,哪些可以改进。

如果你有智能合约的经验,你可能熟悉以太坊的Solidity语言和EVM。在学习TON开发时,你应该知道一些设计差异,这些差异使得TON的行为与你预期的不同。本文的目的是突出这些差异,并给你一些关于它们为何存在的想法。

TON的主要目标是将区块链带到全球每个人的手中,这意味着需要处理大规模的数据——每天数十亿用户发送数十亿笔交易。这可以看作是从数据到大数据的转变。当你需要存储一家餐厅的菜单时,SQL数据库是一个很好的选择,因为它可以运行强大且灵活的查询。但当你需要存储全球每个人的Facebook帖子时,SQL数据库可能就不是最佳选择了,这些大数据必须被积极地分片,这限制了你可以运行的查询的灵活性。

以下是TON区块链的六个独特方面,这些方面可能会让大多数Solidity开发者感到惊讶:

  1. 智能合约需要支付租金并向用户收费:以太坊的区块链费用模型类似于银行,发送交易需要支付交易费。但在TON中,智能合约需要为自己的资源成本付费,每个智能合约都持有TON代币余额,并用这个余额支付租金。如果智能合约的资金用尽,它最终将被删除。

  2. 智能合约之间的调用是异步且非原子的:在以太坊上,合约之间的调用是同步的,可以原子性地执行一系列操作。但在TON中,智能合约之间的通信是异步的,类似于微服务之间的通信,这使得维护一致性变得更加困难。

  3. 智能合约不能运行其他合约的getter方法:在以太坊上,一个合约可以直接读取另一个合约的状态。但在TON中,智能合约只能通过发送异步消息来通信,无法直接读取其他合约的数据。

  4. 智能合约代码不是不可变的,可以轻松修改:与以太坊上的智能合约代码一旦部署就不可更改不同,TON上的智能合约可以自由地修改自己的代码。

  5. 合约状态中不应该有无界的数据结构:在TON中,无界数据结构可能会导致垃圾信息攻击,因此建议避免在状态中使用无界数据结构。

  6. 钱包是合约,一个公钥可以部署多个钱包:在以太坊上,用户的钱包等同于他们的地址。但在TON上,钱包是必须部署的独立智能合约,用户可以部署多个钱包,每个钱包都有自己的地址。

这些设计差异使得TON在处理大规模用户和交易时更加灵活和可扩展。

  1. 智能合约需要支付租金并收取用户费用
    TON的智能合约需要为自己的存储空间支付租金,这类似于现实世界中的房产租赁。如果合约的余额不足以支付租金,它最终可能会被删除。这种费用模型鼓励开发者创建高效的合约,并为用户提供更好的服务。开发者可以选择自己支付TON代币来补贴用户,或者向用户收取费用以支付租金。

  2. 从数据到大数据的转变
    TON旨在处理大规模的数据和用户。这就像从使用SQL数据库存储餐厅菜单,转变为存储全球Facebook用户的帖子。在TON上,数据必须被分割(分片),这限制了可以运行的查询的灵活性,但更适合大规模数据处理。

  3. 异步消息传递
    在TON上,智能合约之间的通信是异步的,这意味着一个合约对另一个合约的调用会在未来的某个区块中被处理,而不是立即执行。这种设计增加了编程的复杂性,但提高了系统的可扩展性。

  4. 智能合约不能运行其他合约的getter方法
    与以太坊不同,TON上的智能合约不能直接调用其他合约的getter方法。这意味着合约无法立即获取其他合约的状态信息。getter方法只能被链下客户端调用,类似于以太坊钱包通过Infura这样的全节点来查询智能合约状态。

  5. 费用模型
    TON的费用模型与即时通讯应用(如Facebook Messenger)类似,而不是传统银行账户。在TON上,智能合约本身需要支付资源成本,包括存储和消息传递的费用。

  6. 智能合约的生命周期管理
    TON上的智能合约需要管理自己的生命周期,包括支付租金和处理用户费用。这要求开发者在设计合约时考虑更多的经济因素。

TON的这些特点使其成为一个高度可扩展且适合大规模应用的区块链平台。然而,这些设计决策也意味着开发者需要适应新的编程模型和最佳实践。随着TON生态系统的发展,我们可以期待看到更多创新的去中心化应用和服务的出现。

一、智能合约需要收取租金。

在TON区块链上,智能合约需要为其存储空间支付租金,这是一种独特的费用模型。与以太坊不同,TON的智能合约不仅要在部署时支付一次性费用,还需要定期支付租金以保持其数据在区块链上的状态。这种模型鼓励开发者创建高效的合约,并为用户提供更好的服务。

例如,假设你开发了一个去中心化的应用程序(DApp),它需要存储用户的数据。在TON上,你的智能合约将持有TON代币余额,并使用这个余额来支付租金。如果智能合约的资金耗尽,它最终可能会被删除,但所有数据都是可恢复的。这种费用结构意味着,如果你只在短时间内持有数据,你将支付较少的费用。这与矿工的成本更加一致,因此更容易扩展。

开发者有很大的自由度来选择如何资助其合约的操作。开发者可以自掏腰包用TON代币资助合约,从而补贴用户;或者,他们可以对用户执行的不同操作收取费用,并将这些费用保留在合约余额中,用于未来的租金支付。这种模式类似于Facebook Inc(或Meta Inc)在Facebook Messenger上发送消息的成本由公司承担,而不是由发送消息的用户承担。

这种设计使得TON区块链非常适合大规模应用,因为它考虑到了数据存储和处理的长期成本,并通过持续的费用模型来确保网络的可持续性。开发者需要在设计智能合约时考虑到这一点,并实现相应的逻辑来管理资金和支付租金。这种模式也意味着用户在使用DApp时可能会遇到不同的费用结构,因为这些费用可能会被转嫁到他们身上。

二、从数据到大数据的转变

在以太坊上,智能合约之间的调用是同步且具有原子性的,这是构建强大去中心化金融(DeFi)生态系统的关键因素之一。在单笔交易中,你可以将一些WBTC作为抵押品提供给Compound的合约,然后借用USDC,再将这些USDC与Uniswap的合约交易以换取更多的WBTC,从而增加你的WBTC头寸。整个过程甚至是原子性的——如果这些步骤中的任何一个失败,即使是最后一个,整个交易就会像从未发生过一样回滚。

当你的智能合约调用另一个智能合约的方法时,该调用会在同一笔交易中立即处理。在这方面,以太坊非常类似于在单一服务器上运行整个后端。你的后端的每个部分都能够同步访问任何其他部分——这是一种非常容易理解的方法。但它有一个缺点,它只能增长到适合在一个地方为止。

将单一服务器转移到微服务集群

如果你将以太坊想象成运行在单一服务器上的单体应用程序,TON则更像是一组微服务。想象一下,每个智能合约可能在不同的机器上运行。如果两个智能合约想要相互调用,就像两个微服务通过网络通信一样,它们可以通过网络发送消息。这个消息需要一些时间来传递,因此通信突然变得异步了!这意味着当你的智能合约调用另一个智能合约的方法时,这个调用将在交易终止后,在某个不同的未来区块中被处理。

这种情况更难以理解。如果消息发送和接收之间的条件发生了变化,会发生什么?例如,调用合约的余额在发送消息时是一个值,但等到第二个合约处理这个调用时,余额已经改变了。保持一致性变得更加困难,可能会出现错误。那么原子性呢?如果你链接了三个调用,但只有最后一个失败了怎么办?如果你需要回滚所有的更改,你将不得不手动进行。

举例说明:

假设在TON区块链上,我们有两个智能合约:ContractAContractB

  1. ContractA 想要调用 ContractB 的一个方法,并且传递一些TON币作为支付。
  2. ContractA 发送了一个消息给 ContractB,包含了调用的方法和支付的TON币。
  3. 由于通信是异步的,ContractB 可能在几个区块之后才收到这个消息。
  4. 在等待 ContractB 处理期间,ContractA 的余额可能已经因为其他交易而发生了变化。
  5. ContractB 尝试处理这个调用时,它可能会发现 ContractA 的余额不再足够支付之前承诺的金额。
  6. 如果 ContractB 依赖于 ContractA 的余额来执行某些操作(比如释放代币或执行某些逻辑),那么这个操作可能会失败,因为它依赖的状态已经改变。
  7. 如果需要回滚这个操作,ContractB 必须实现额外的逻辑来检测这种情况并执行回滚,这可能涉及到手动干预或复杂的错误处理逻辑。

在这种情况下,开发者需要在设计智能合约时考虑到异步通信的复杂性,并实现额外的逻辑来确保操作的原子性和一致性。这可能包括使用事务管理器、状态通道或其他机制来确保跨合约调用的一致性和正确性。


三、智能合约不能运行其他合约的getter方法

在TON区块链上,智能合约不能调用其他合约的getter方法,这是与以太坊同步调用不同智能合约特性的另一个方面。在以太坊上,合约之间的调用是同步的,从一个不同的智能合约读取数据是直接的。比如说,我的合约有USDC的余额。由于USDC本身也是一个合约,为了知道它自己的余额,我的合约将不得不调用USDC合约的getBalance方法。

回想一下在单一服务器上运行的单体应用?这种方法的一个巨大好处是每个服务都可以直接读取每个其他服务的状态内存。

当我们在不同机器上运行独立的微服务时,跨服务读取状态内存突然变得不可能。TON上的智能合约只能通过发送异步消息来通信。如果你需要从另一个合约查询数据,并且你需要立即得到答案,那你就不走运了。

情况实际上变得更加奇怪。如果你在TON智能合约上看到getter方法,比如getBalance——这些方法不能从其他智能合约中访问。Getter方法只能被链下客户端调用,类似于你的以太坊钱包可以使用像Infura这样的全节点来查询任何智能合约的状态。

举例说明:

假设在以太坊上,你有一个名为MyToken的代币合约,它有一个balanceOf(address _owner)的getter方法,可以查询任何账户的余额。如果你在以太坊上有一个名为MyContract的合约,它想要获取一个账户在MyToken合约中的余额,它可以直接调用MyToken(balanceOf: address _owner)方法来获取这个信息。

在TON上,情况就不同了。假设你有两个TON智能合约,ContractAContractBContractB有一个getBalance方法,可以返回与合约相关联的余额。如果ContractA想要获取自己的ContractB余额,它不能直接调用ContractB.getBalance()。相反,ContractA需要发送一个消息给ContractB并等待异步响应。这个响应可能需要几个区块的时间,并且ContractA不能保证在它需要的时候立即得到这个信息。

因此,TON上的智能合约开发者必须考虑到这种异步通信的复杂性,并可能需要实现额外的逻辑来处理状态的不确定性和延迟。这可能包括使用事件、日志记录或其他机制来跟踪和验证跨合约调用的结果。

四、合约不是无法改变的

在以太坊上,智能合约的代码是不可变的,这一点最初是受到律师起草的法律文件的启发——因此被称为“智能合约”。开发者将法律合同的条款编写成代码,而代码,正如你所知,就是法律。当现实世界中的双方签订合同时,合同是不可变的。如果任何一方想要改变合同条款,他们会起草一份新的合同。

多年来,开发者社区已经学会了克服这一限制,并生成了一些繁琐的模式,这些模式依赖于一些技巧,比如使用代理合约指向不同的合约,以实现升级。

与律师不同,软件工程师被教导说,每段代码都有错误。即使错误永远不会发生,需求仍然会随着时间的推移而变化,代码也必须经常升级和修改。

在TON中,合约应该是不可变的借口被完全抛弃了。智能合约可以自由地修改自己的代码,就像编写任何其他状态变量一样。如果合约写入代码变量,那么它是可变的,如果没有,那么它是不可变的。这在实践中并不是一个大的变化,它只是使繁琐的代理模式变得多余。

举例说明:

假设在以太坊上,你有一个名为LendingContract的智能合约,它实现了一个借贷平台的逻辑。随着时间的推移,你发现了合约中的一些漏洞,或者你想添加一些新功能。在以太坊上,你不能直接修改LendingContract的代码,而是需要部署一个新的合约,比如LendingContractV2,然后让用户迁移到新合约。

在TON上,你可以简单地修改现有的LendingContract合约。例如,你可以编写一个新的升级函数upgradeContract,这个函数可以更改合约的状态或逻辑。如果合约需要更新其代码,它可以调用这个函数来实现自我升级,而不需要部署一个新的合约。

// 这是一个简化的TON智能合约示例,展示了如何实现自我升级
contract LendingContract {
    var code : Cell; // 存储新代码的变量

    // 升级合约的函数
    function upgradeContract(newCode : Cell) {
        self.code = newCode;
        // 实现升级逻辑,可能包括调用内置函数来更新合约代码
    }

    // 其他合约逻辑...
}

// 假设这是新版本的代码
Cell newCode = ...;

// 调用升级函数来更新合约
LendingContract.upgradeContract(newCode);

在这个例子中,LendingContract合约有一个upgradeContract函数,它允许合约自我更新其代码。这种方式简化了合约升级的过程,因为开发者不需要部署新的合约,用户也不需要迁移到新合约。这种灵活性使得TON上的智能合约更加适应不断变化的需求和市场条件。

五、Ton取消了无限制的数据结构

在TON区块链中,智能合约的状态中不应该有无界的数据结构,这是因为无界数据结构可以无限增长,可能会导致一些问题。例如,如果一个攻击者试图通过不断添加更多的条目来滥用合约,他们可能会发动拒绝服务(DoS)攻击,从而阻止其他用户使用该合约。在以太坊上,智能合约开发者不需要太担心这个问题,因为以太坊的费用模型规定写入新状态数据的用户需要支付费用,这使得垃圾信息攻击在经济上不可行。然而,在TON中,情况就不同了。

TON的“Bag of Cells”架构要求开发者维护由1023位块(称为“cells”)组成的合约状态。映射是作为单元树实现的,写入树的叶子需要沿着整个树的高度写入新的哈希。如果攻击者在映射中垃圾信息攻击键,一些用户余额可能会被推到树的深处,以至于更新它们会超过gas限制。因此,TON的最佳实践是避免在状态中使用无界数据结构,以保护合约免受DoS漏洞的攻击。如果需要处理可能无限增长的数据,如USDC合约中的用户余额,应该将单个合约拆分为多个子合约,每个子合约保存单个用户的余额。这种方法可以避免无界数据结构带来的问题,并保持合约的可扩展性和安全性。

例如,如果一个USDC代币合约需要维护每个用户地址的余额映射,而不是在单个合约中无限增长这个映射,开发者应该创建多个子合约,每个子合约只处理一个用户的余额。这样,即使某个子合约受到攻击或垃圾信息攻击,也不会影响到整个系统的稳定性。这种设计方法在TON上是推荐的,因为它有助于避免由于无界数据结构导致的潜在问题。

六、钱包和地址具有独立性

在以太坊上,用户的钱包等同于他们的地址,地址直接由公钥(及其对应的私钥)派生。这是一个一对一的关系,一个公钥对应一个地址,一个地址对应一个公钥。只要用户知道他们的私钥,他们就永远不会丢失他们的钱包。

此外,在以太坊上,用户无需采取任何特殊措施就可以拥有钱包。以太坊地址就是钱包。地址可以持有原生货币ETH,地址可以持有ERC20代币和NFT,地址可以直接向其他智能合约发送和签署交易。

从地址到合约

在TON上,钱包不是隐含的,它们是必须像任何其他智能合约一样部署的独立智能合约。当新用户想要开始使用TON区块链时,他们的第一步将是在链上部署一个钱包。这个钱包的地址是从钱包合约代码和各种初始化参数(如用户的公钥)派生的。

这意味着用户可以部署多个钱包,每个钱包都有自己的地址。这些钱包可以在它们的代码上有所不同(基金会不时发布不同的官方代码版本)或者在它们的初始化参数上有所不同(其中一个参数通常是序列号)。这也意味着即使用户知道他们的私钥,他们仍然必须刻意记住他们的钱包地址(或用于构建的初始化参数)。

向TON上的某个dapp发送交易涉及使用用户的私钥签署消息。与以太坊不同,这个交易不是发送到dapp智能合约,而是发送到用户的钱包合约,后者将转发消息到dapp智能合约。

这种设计方法为TON开辟了一个新的灵活维度。社区随着时间可以发明新的钱包合约,例如考虑一个没有nonce(交易序列号)的钱包,允许从不同客户端并行发送多个交易而无需事先同步。此外,特殊钱包如多重签名钱包(即使在以太坊上也需要部署特殊智能合约),表现就像它们的常规对应物一样。

举例说明:

假设用户Alice想要在TON区块链上部署一个新的钱包。她首先选择一个钱包合约的代码,这可能是TON基金会提供的官方版本,也可能是社区开发的一个新版本。Alice还需要提供一些初始化参数,比如她的公钥和一个序列号。

  1. Alice使用她的私钥对初始化参数进行签名,生成一个部署交易。
  2. 她将这个交易发送到TON网络,网络中的节点验证交易并将其打包进一个区块。
  3. 一旦交易被确认,Alice的新钱包合约就被部署在链上,并且她获得了一个新的钱包地址。
  4. Alice可以使用这个钱包地址来接收和发送资金,以及与TON上的其他智能合约进行交互。

如果Alice想要部署另一个钱包,她可以重复这个过程,使用不同的初始化参数或不同的钱包合约代码。这样,她就可以拥有多个钱包,每个钱包都有自己的地址和功能。

这种模式提供了极大的灵活性,但也要求用户更加注意管理他们的钱包地址和相关的初始化参数。同时,这也为创新的钱包解决方案提供了空间,比如可以实现更复杂的资产管理和交易功能的特殊钱包合约。

  • 36
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值