消息概览
TON 是一个异步区块链,其结构与其他区块链非常不同。因此,新开发者经常对 TON 中的低级事物有疑问。在本文中,我们将探讨与消息传递相关的一个问题。
什么是消息?
消息是在actor(用户、应用程序、智能合约)之间发送的数据包。它通常包含指导接收方执行某种操作的信息,如更新存储或发送新消息。
这种通信方式让人想起将卫星发射到太空。我们知道我们构成的消息,但在发射后,需要进行单独的观察来找出我们将获得什么结果。
什么是交易?
TON 中的一笔交易包括以下内容:
- 最初触发合约的传入消息(存在特殊的触发方式)
- 由传入消息引起的合约行动,例如更新合约的存储(可选)
- 发送给其他参与者的所生成的传出消息(可选)
技术上,合约可以通过特殊功能如 Tick-Tock 触发,但这个功能更多用于 TON 内部的区块链核心合约。
并非每笔交易都会导致传出消息或对合约存储的更新——这取决于合约代码所定义的操作。
在异步系统中,您无法在同一笔交易中从目标智能合约获得响应。合约调用可能需要几个区块来处理,具体取决于来源和目的地之间的路由长度。
为了实现无限分片范式,必须确保完全并行化,这意味着每笔交易的执行都独立于其他交易。因此,与其进行影响和改变多个合约状态的交易,不如每笔 TON 交易只在单个智能合约上执行,智能合约通过消息进行通信。这样,智能合约只能通过调用它们的函数与特殊消息相互作用,并稍后通过其他消息获得响应。
为了实现无限分片范式,必须确保完全并行化,这意味着每笔交易的执行都独立于其他交易。因此,与其进行影响和改变多个合约状态的交易,不如每笔 TON 交易只在单个智能合约上执行,智能合约通过消息进行通信。这样,智能合约只能通过调用它们的函数与特殊消息相互作用,并稍后通过其他消息获得响应。
交易布局 页面上有更详细准确的说明。
交易结果
严格保证由消息产生的交易将具有大于消息的 lt 的 lt。同样,某笔交易中发送的消息的 lt 严格大于引起它的交易的 lt。此外,从一个账户发送的消息和在一个账户上发生 的交易也是严格有序的。
要确定交易是否成功,应使用 tx.description.action.success && tx.description.compute_ph.success:
"transactions": [
{
"description": {
. . . . . . . .
"action": {
"valid": true,
"success": true,
. . . . . . . .
},
. . . . . . . .
"destroyed": false,
"compute_ph": {
"mode": 0,
"type": "vm",
"success": true,
由此,对于每个账户,我们总是知道交易、接收消息和发送消息的顺序。
- 成功,退出代码为 0 或 1
- 失败,
aborted: true
未执行 - Fail, exit code,
aborted: true
.
aborted: true
是 TON 中心字段,事务中没有此类字段
什么是逻辑时间?
否则,尝试同步交付将需要在处理一个分片之前知道所有其他的状态,从而破坏了并行并破坏有效的分片。
对于每个区块,我们可以将 lt 范围定义为从第一笔交易开始,到区块中最后一个事件(消息或交易)的 lt 结束。区块的排序方式与 TON 中的其他事件相同,因此如果一个区块依赖于另一个区块,它具有更高的 lt。一个分片中的子区块的 lt 高于其父区块。一个主链区块的 lt 高于它所列出的分片区块的 lts,因为主区块依赖于所列分片区块。每个分片区块包含对创建分片区块时最新(创建分片区块时)主区块的有序引用,因此分片区块的 lt 高于引用的主区块的 lt。
幸运的是,TON 的工作方式是任何内部消息都一定会被目标账户接收。消息不会在来源和目的地之间的任何地方丢失。外部消息有点不同,因为它们被接受到区块中是由验证者自行决定的,但是,一旦消息被接受进入传入消息队列,它将被传递。
此外,如果账户 A 向账户 B 发送了两条消息,可以保证具有较低 lt 的消息将被更早处理:
因此,看起来 lt 解决了消息传递顺序的问题,因为我们知道具有较低 lt 的交易将首先被处理。但这并不适用于每个场景。
假设有两个合约 - A 和 B。A 收到一个外部消息,触发它向 B 发送两个内部消息,我们称这些消息为 1 和 2。在这个简单的情况下,我们可以 100% 确定 1 将在 2 之前被 B 处理,因为它具有较低的 lt。
但这只是一个简单的案例,当我们只有两个合约时。我们的系统在更复杂的情况下是如何工作的?
对于每个区块,我们可以将 lt 范围定义为从第一笔交易开始,到区块中最后一个事件(消息或交易)的 lt 结束。区块的排序方式与 TON 中的其他事件相同,因此如果一个区块依赖于另一个区块,它具有更高的 lt。一个分片中的子区块的 lt 高于其父区块。一个主链区块的 lt 高于它所列出的分片区块的 lts,因为主区块依赖于所列分片区块。每个分片区块包含对创建分片区块时最新(创建分片区块时)主区块的有序引用,因此分片区块的 lt 高于引用的主区块的 lt。
消息传递
为了更清晰,假设我们的合约在 msg1
和 msg2
由 B
和 C
合约执行后发送回消息 msg1'
和 msg2'
。结果将在合约 A
上实现 tx2'
和 tx1'
。我们有两种可能的交易路径,
传递顺序
假设有两个合约 - A 和 B。A 收到一个外部消息,触发它向 B 发送两个内部消息,我们称这些消息为 1 和 2。在这个简单的情况下,我们可以 100% 确定 1 将在 2 之前被 B 处理,因为它具有较低的 lt。
假设有两个合约 - A 和 B。A 收到一个外部消息,触发它向 B 发送两个内部消息,我们称这些消息为 1 和 2。在这个简单的情况下,我们可以 100% 确定 1 将在 2 之前被 B 处理,因为它具有较低的 lt。
同样,当两个合约 B 和 C 向一个合约 A 发送消息时,情况也是如此。即使 B -> A
的消息在 C -> A
之前发送,我们也无法知道哪一个将先被送达。B -> A
的路由可能需要更多的分片链转运。
多个智能合约
在多个智能合约互动的许多可能的场景中,消息传递顺序可能是任意的。唯一的保证是,来自任何合约 A 到任何合约 B 的消息将按照它们的逻辑时间顺序处理。下面是一些示例。
为了更清楚起见,假设在 B
和 C
合约执行了 msg1
和 msg2
之后,我们的合约发回了 msg1'
和 msg2'
消息。因此,它将在 A
合约上应用 tx2'
和 tx1'
。
我们有两种可能的交易跟踪、
- 第一种可能的顺序是
tx1'_lt < tx2'_lt
:
- 第二种可能的顺序是
tx2'_lt < tx1'_lt
:
同样,当两个合约 B 和 C 向一个合约 A 发送消息时,情况也是如此。即使 B -> A
的消息在 C -> A
之前发送,我们也无法知道哪一个将先被送达。B -> A
的路由可能需要更多的分片链转运。
在多个智能合约互动的许多可能的场景中,消息传递顺序可能是任意的。唯一的保证是,来自任何合约 A 到任何合约 B 的消息将按照它们的逻辑时间顺序处理。下面是一些示例。
结论
TON 区块链的异步结构为消息传递保证带来挑战。逻辑时间有助于确定事件和交易顺序,但由于分片链中的路由不同,它并不能保证多个智能合约之间的消息传递顺序。尽管存在这些复杂性,TON 仍然能够确保内部消息的传递,维护网络的可靠性。开发人员必须适应这些细微差别,以充分利用 TON 的潜力构建创新的去中心化应用程序。