虚拟机

TVM(TRON Virtual Machine)是TRON网络智能合约的运行时环境,网络中的每一个节点都会维护一个TVM实体。TRON网络协议保证了TVM状态的连续性、不可被打断性和操作不可逆性。对于TRON网络中的任何一个的区块,有且只有一个“准确”状态,而TVM定义了从一个区块到另一个区块状态改变的特定规则。

从分布式账本到状态机

“分布式账本”经常被用来描述像比特币这样的区块链网络,它使用密码学工具实现了去中心化货币。加密货币在使用上和常规货币是一样的,因为它的一些规则限制了人们在哪些情况下可以修改分布式账本,比如,一个比特币地址不能花费比余额更多的比特币,这些规则支撑着比特币网络上的所有交易。

TRON也有自己的原生加密货币TRX,遵循和比特币几乎相同的规则。但TRON还支持一个更强大的功能:智能合约。对于这个更复杂的特性,TRON不是一个简单的分布式账本,而是一个分布式状态机。TRON网络的状态是一个大型的数据结构,它不仅包含所有账户信息,而且还包含机器状态,这个机器状态不但可以根据预定义的一组规则从一个区块到另一个区块而变化,而且还可以执行任意的机器码。

状态转换函数

TVM的行为就像一个数学函数:给定一个输入,它产生一个确定性的输出。将这种转换称为状态转换函数。

Y(S, T) = S'

给定一个旧的有效状态(S)和一组新的有效交易(T),TRON状态转换函数Y(S, T)产生一个新的有效输出状态S'。

状态

在TRON网络中,状态是一个被称为"默克尔树"的数据结构,其中存储了所有账户的信息,为了简化状态的存储,仅将默克尔树的根节点哈希值存储在区块头中。

交易

交易是来自账户的加密签名指令。交易分为两大类,系统合约交易和智能合约交易,其中智能合约交易又包括合约调用交易和合约创建交易。

如果合约创建交易执行成功,则会创建出一个包含合约字节码的新的合约账户,每当另一个账户对该合约发出消息调用时,相应的字节码将会在TVM中被执行。

TVM指令

TVM是一种基于堆栈的虚拟机,其栈的深度为1024。为了便于使用256位加密算法(如 Keccak-256 或 secp256k1),TVM选择使用256比特长度的机器码。

编译后的智能合约可执行文件字包含大量的TVM操作码,这些操作码是标准的堆栈操作,例如 XOR、 AND、 ADD、SUB等,另外TVM还实现了一些区块链专属的堆栈操作,如 ADDRESS、BALANCE、BLOCKHASH 等。更多的操作码请参考TRON操作码

下面是TVM的架构图,展示了TVM是如何工作的:

大概流程如下:

  • 编译器将智能合约编译为在TVM上可读和可执行的字节码
  • TVM根据字节码处理数据
  • TVM访问区块链数据并通过互操作层调用外部状态数据接口
  • TVM执行结束后,状态写入区块,用户可以通过API查询执行结果和状态

以太坊虚拟机 EVM 的不同

TVM 基本兼容以太坊 EVM,但在部分特有功能及细节上有所不同

  • TVM 使用 energy 替代 gas 概念, energy 单价, 目前是 420 sun/energy, GASPRICE, BASEFEE 指令在TVM中均返回能量单价

  • DIFFICULTY, GASLIMIT 在 TVM 中目前都返回0

  • VM指令消耗:TVM中多数指令执行的能量消耗等于EVM,少部分指令的能量消耗低于EVM(如SLOAD、CALL);

  • CREATE2指令创建的合约地址计算公式前缀不同:TVM选取0x41作为计算前缀,具体计算公式为 keccak256( 0x41 ++ address ++ salt ++ keccak256(init_code))[12:];

  • 预编译合约Ripemd160(0x03)不同:波场目前对输入做了2次sha256, 后续会提供一个新的预编译合约来实现标准的 Ripemd160 算法;

  • 预编译合约0x09不同:以太坊在该地址为Blake2F,波场为 BatchValidateSign [详见: https://github.com/tronprotocol/tips/blob/master/tip-43.md];

  • 在波场可以通过 Transfer 交易和带有 callValue 的 TriggerSmartContract 交易两种系统交易向合约地址发送 TRX,但是 Transfer 交易不会像 TriggerSmartContract 一样调用目标合约的fallback 函数;

在此基础上,TVM依托于波场网络特有的机制及生态新增了若干新特性

  • 增加了TRC10Token相关操作指令,包含CALLTOKEN(0xd0)指令、TOKENBALANCE(0xd1)指令、CALLTOKENVALUE(0xd2)指令、CALLTOKENID(0xd3)指令

  • 增加判断地址是否为合约地址指令ISCONTRACT(0xd4) TIP-44

  • 增加批量验证签名和验证多签的预编译合约,包含BatchValidateSign(合约地址0x09, TIP-43)、ValidateMultiSign(合约地址0x0a, TIP-60)

  • 增加匿名合约TIP-135及若干librustzcash相关预编译合约,包含verifyMintProof(地址0x1000001)、verifyMintProof(合约地址0x1000002)、verifyMintProof(合约地址0x1000003) TIP-137及merkleHash(合约地址0x1000004, TIP-138)

  • 增加Stake 1.0功能相关的合约质押和解锁balance功能相关指令 TIP-157,包含FREEZE(0xd5)UNFREEZE(0xd6)FREEZEEXPIRETIME(0xd7)指令

  • 增加合约投票功能相关的指令及预编译合约 TIP-271,包含VOTEWITNESS(0xd8)指令、WITHDRAWREWARD(0xd9)指令及RewardBalance(合约地址0x1000006)、IsSrCandidate(合约地址0x1000006)、VoteCount(合约地址0x1000007)、UsedVoteCount(合约地址0x1000008)、ReceivedVoteCount(合约地址0x1000009)、TotalVoteCount(合约地址0x100000a)预编译合约

  • 增加Stake 2.0功能相关的合约质押、解质押、资源代理、取消资源代理等指令及预编译合约TIP-467,包含FREEZEBALANCEV2(0xda)指令、UNFREEZEBALANCEV2(0xdb)指令、CANCELALLUNFREEZEV2(0xdc)指令、WITHDRAWEXPIREUNFREEZE(0xdd)指令、DELEGATERESOURCE(0xde)指令、UNDELEGATERESOURCE(0xdf)指令及GetChainParameter(合约地址0x100000b)、AvailableUnfreezeV2Size(合约地址0x100000c)、UnfreezableBalanceV2(合约地址0x100000d)、ExpireUnfreezeBalanceV2(合约地址0x100000e)、DelegatableResource(合约地址0x100000f)、ResourceV2(合约地址0x1000010)、CheckUnDelegateResource(合约地址0x1000011)、ResourceUsage(合约地址0x1000012)、TotalResource(合约地址0x1000013)、TotalDelegatedResource(合约地址0x1000014)、 TotalAcquiredResource(合约地址0x1000015)预编译合约

关于提供上述差异性的兼容方案目前在讨论中,如您感兴趣请移步相关ISSUE参与讨论,讨论链接接地址ISSUE-272,相关TIP链接地址TIP-272