跳到主要内容

TVM 概述

所有 TON 智能合约都在其自己的 TON 虚拟机(TVM)上执行。TVM 基于 栈原理 构建,这使得它高效且易于实现。

本文提供了TVM如何执行交易的概览。

提示

交易和阶段

当 TON 链中的某个帐户发生某些事件时,它会引发一个交易。最常见的事件是"接收某个消息",但一般来说还可能有 tick-tockmergesplit 和其他事件。

每个交易包含最多 5 个阶段:

  1. Storage phase - 在此阶段,由于合约占用链状态中的某些空间而积累的存储费用被计算。阅读更多信息 存储费用
  2. Credit phase - 在此阶段,根据(可能的)传入消息值和收集的存储费用计算合约的余额。
  3. Compute phase - 在此阶段,TVM 执行合约(见下文),合约执行的结果是 exit_codeactions(动作序列的序列化列表)、gas_detailsnew_storage 等的聚合。
  4. Action phase - 如果 Compute phase 成功,在此阶段处理来自 Compute Phase 的 actions。特别是,动作可能包括发送消息、更新智能合约代码、更新库等。请注意,在处理过程中某些动作可能失败(例如,如果我们尝试发送比合约拥有的 TON 更多的消息),在这种情况下整个交易可能会回滚或跳过此动作(这取决于动作的模式,换句话说,合约可能会发送 send-or-reverttry-send-if-no-ignore 类型的消息)。
  5. Bounce phase - 如果 Compute Phase 失败(它返回 exit_code >= 2),在此阶段为由传入消息发起的事务形成 反弹消息

Compute phase

在此阶段,执行 TVM。

TVM 状态

在任何给定时刻,TVM 状态由 6 个属性完全确定:

  • Stack - (见下文)
  • Control registers - (见下文)简单地说,这意味着最多可在执行期间直接设置和读取的 16 个变量
  • Current continuation - 描述当前执行的指令序列的对象
  • Current codepage - 简单地说,这表示当前正在运行的 TVM 版本
  • Gas limits - 一组 4 个整数值;当前 gas 限制 gl、最大 gas 限制 gm、剩余 gas gr 和 gas 信用 gc
  • Library context - 可以由 TVM 调用的库的哈希映射

TVM 是堆栈机

TVM 是一个后进先出的堆栈机。总共有 7 种类型的变量可以存储在堆栈中 — 三种非cell类型:

  • Integer(整数) - 有符号的 257 位整数
  • Tuple(元组) - 由最多 255 个元素组成的有序集合,具有任意值类型,可能是不同的。
  • Null(空)

以及四种不同的cell类型:

  • Cell(cell) - TON 区块链用于存储所有数据的基本(可能是嵌套的)不透明结构
  • Slice(切片) - 一种特殊的对象,允许从cell中读取
  • Builder(构建器) - 一种特殊的对象,允许您创建新的cell
  • Continuation(延续对象) - 一种特殊的对象,允许您将cell TVM 指令的源

控制寄存器

  • c0 — 包含下一个 continuation 或返回 continuation(类似于常规设计中的子例程返回地址)。此值必须是一个 Continuation。
  • c1 — 包含备用(返回) continuation ;此值必须是一个 Continuation。
  • c2 — 包含异常处理程序。此值是一个 Continuation,在触发异常时调用。
  • c3 — 支持寄存器,包含当前字典,本质上是一个包含程序中使用的所有函数的代码的哈希映射。此值必须是一个 Continuation。
  • c4 — 包含持久数据的根,或简单地说,合约的 data 部分。此值是一个 Cell。
  • c5 — 包含输出动作。此值是一个 Cell。
  • c7 — 包含临时数据的根。它是一个 Tuple。

TVM 的初始化

TVM 在事务执行到达 Compute Phase 时初始化,然后从 当前 continuation 执行命令(操作码),直到没有更多的命令要执行(并且没有用于返回跳转的 continuation)。

可以在这里找到初始化过程的详细说明:TVM 初始化

TVM 指令

TVM 指令列表可以在这里找到:TVM 指令

TVM 执行的结果

除了 exit_code 和消耗的 gas 数据之外,TVM 还间接输出以下数据:

  • c4 寄存器 - 将作为智能合约的新 data 存储的cell(如果执行不会在此阶段或以后的阶段回滚)
  • c5 寄存器 - (输出动作列表)列表中最后一个动作和对先前动作的引用的cell(递归)

所有其他寄存器值都将被忽略。

请注意,由于最大cell深度 <1024 以及特别是 c4 和 c5 深度 <=512 的限制,一次 tx 中的输出动作数量将受到限制 <=255。如果合约需要发送的消息超过这个限制,它可以发送带有请求 continue_sending 的消息给自己,并在随后的交易中发送所有必要的消息。

参见