虚拟机
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查询执行结果和状态
TVM vs EVM
TVM与EVM基本兼容,但在细节上存在一些差异:
- TVM 使用的是能量(Energy)模型,与以太坊的 Gas 模型不同。其中,energyPrice(能量价格)是一个可以通过委员会提议调整的网络参数,当前在主网(Mainnet)的设定值为 100 sun。不像 EVM 的 gas 价格会一直变化,也没有
basefee。在TVM中,GASPRICE和BASEFEE都返回energyprice - TVM 中的大多数操作码的能耗与 EVM 中的能耗相同,其中一些更低(例如,
SLOAD、CALL) CREATE2创建的合约地址前缀与 EVM 不同:TVM 选择0x41作为前缀。公式为:keccak256(0x41++ address ++ salt ++ keccak256(init_code))[12:]- 有两种方式可以将 TRX 发送到合约:转账和带有
callValue的TriggerSmartContract。Transfer 不会调用合约中的fallback函数。
指令的不同
| 指令 | TVM | EVM |
|---|---|---|
DIFFICULTY (0x44) | 返回 0 | 返回当前区块难度 |
GASLIMIT (0x45) | 返回 0 | 返回当前区块的 gaslimit |
GASPRICE (0x3A) | 返回 energyPrice | 返回当前的gasPrice |
BASEFEE (0x48) | 返回 energyPrice | 返回当前区块的 baseFee |
CREATE2 (0xf5) | 前缀为0x41 | 前缀为 0xff |
预编译合约的不同
| 预编译合约 | TVM | EVM |
|---|---|---|
Ripemd160 (0x03) | 计算 SHA-256 两次 | 计算 SHA-256 一次 |
| 0x09 | BatchValidateSign 批量验证签名 | Blake2F |
TVM的新特性
指令
| 指令 | 功能 |
|---|---|
| TRC-10 | |
CALLTOKEN (0xd0) |
调用 TRC-10 token,和CALL类似 |
TOKENBALANCE (0xd1) |
查询 TRC-10 token 余额 |
CALLTOKENVALUE (0xd2) |
获取当前的 call toke value |
CALLTOKENID (0xd3) |
获取当前的 TRC-10 token ID |
| TIP-44 | |
ISCONTRACT (0xd4) |
判断地址是否属于合约地址 |
| TIP-157 freeze/Unfreeze Functions | |
FREEZE(0xd5) |
冻结 TRX 获取资源 |
UNFREEZE(0xd6) |
解冻 TRX 释放资源 |
FREEZEEXPIRETIME(0xd7) |
查询冻结过期时间 |
| TIP-467 freezeV2/UnfreezeV2 Functions | |
FREEZEBALANCEV2 (0xda) |
冻结 TRX 获取资源(V2) |
UNFREEZEBALANCEV2 (0xdb) |
解冻 TRX 释放资源(V2) |
CANCELALLUNFREEZEV2 (0xdc) |
取消解冻(V2) |
WITHDRAWEXPIREUNFREEZE(0xdd) |
取回到期的已解冻 TRX |
DELEGATERESOURCE (0xde) |
代理资源 |
UNDELEGATERESOURCE (0xdf) |
取消代理资源 |
| TIP-721 Contract Voting Related Functions | |
VOTEWITNESS (0xd8) |
投票 |
WITHDRAWREWARD (0xd9) |
提取投票收益 |
预编译合约
| 预编译合约 | 功能 |
|---|---|
| TIP-60 | |
ValidateMultiSign (0x0a) |
多签验证 |
| TIP-43 | |
BatchValidateSign (0x09) |
批量验证签名 |
| TIP-271 合约投票相关功能 | |
RewardBalance (0x1000005) |
投票奖励余额 |
IsSrCandidate (0x1000006) |
查询一个地址是否为srCandidate |
VoteCount (0x1000007) |
查询某个地址给某个 Super Representative (SR) 投的票数 |
| TIP-467 freezeV2/UnfreezeV2 功能 | |
GetChainParameter(0x100000b) |
获取指定的 chain parameter |
AvailableUnfreezeV2Size (0x100000c) |
查询目标地址可用的unfreeze队列长度(V2) |
UnfreezableBalanceV2 (0x100000d) |
查询目标地址指定资源的可解冻余额(V2) |
ExpireUnfreezeBalanceV2(0x100000e) |
查询目标地址可提取的解冻金额(V2) |
DelegatableResource(0x100000f) |
查询目标地址指定资源的可代理数量 |
ResourceV2(0x1000010) |
查询目标地址从指定地址代理的指定资源的数量(V2) |
CheckUnDelegateResource(0x1000011) |
查询合约是否可以从指定地址回收指定数量的资源 |
ResourceUsage(0x1000012) |
查询目标地址指定资源的用量和恢复时间 |
TotalResource(0x1000013) |
查询目标地址指定资源的可用余额 |
TotalDelegatedResource (0x1000014) |
查询目标地址指定资源代理出去的数量 |
TotalAcquiredResource (0x1000015) |
查询目标地址指定资源通过代理得到的总数量 |
关于提供上述差异性的兼容方案目前在讨论中,如您感兴趣请移步相关 ISSUE 参与讨论,讨论链接地址为 ISSUE-272,相关 TIP 链接地址为 TIP-272。
Updated 17 days ago