Sui 实用学习笔记 (3) - PTB
Sui 可编程交易块相关知识。
参考
交易格式
Sui 交易包括如下字段:
- Sender address:交易的发送方地址
- Gas input:一个
sui::coin::Coin<SUI>
object,用来支付 gas - Gas price:非 0 整数,表示 gas 价格
- Maximum gas budget: 类似于 gas limit。Gas input 的 balance 需要大于
Maximum gas budget * Gas price
- Epoch:交易的 Epoch
- Type:交易类型
- Authenticator:公钥及对应的签名
- Expiration:交易失效时间。
PTB
Sui 使用可编程交易块(简称 PTB),简单来说,Sui 的每笔交易可以是多笔交易构成的交易链。链中每个结点的输入是前面结点的输出。利用这个机制可以通过交易实现一些简单的逻辑,而不需要像以太坊等链一下只能通过编写智能合约来实现这种需求。
PTB 的结构:
- inputs:交易的输入列表,输入可以两种类型:
- object:要求是 sender 所 own 的,或者是 shared/immutable。这就保证了每个 object 只有 owner 才能修改,这是 Sui 权限认证的核心机制。
- pure value:基础类型的数据,如 u64, vector
等等
- commands:交易的 command 列表。
- command 代表一种操作,每种 command 的输入参数可以来自交易的 inputs 或者其他 command 的 results。由于 commands 是一维数组。results 使用二维数组来保存。输入有以下几种
Input(u16)
表示来自 inputs 数组GasCoin
表示交易的 Gas objectNestedResult(u16, u16)
表示来自之前 commands 的输出,使用二维形式索引。Result(u16)
相当于NestedResult(u16, 0)
,但会在对应的 commands 返回 value 数量为 0 或大于 1 的情况下报错。
- command 有以下几种:
- TransferObjects 转移一或多个 object 给目标地址。无输出。
- SplitCoins 分割 Coin,要求输入
sui::coin::Coin<_>
类型的 object,输出一或多个同类 object(注:不包括原本的 输入的 object) - MergeCoins 合并 Coin,要求输入是一或多个
sui::coin::Coin<_>
类型的 object。合并到第一个 object 中,无输出。 - MakeMoveVec 构造 vector,输出 vector object。
- MoveCall 发起合约调用,调用 package 的 public/entry 方法,根据方法定义输出返回值。
- Publish 部署 package 并调用每个 module 的 init 方法,输出
sui::package::UpgradeCap
object。 - Upgrade 更新 package。要求有
sui::package::UpgradeCap
,输出sui::package::UpgradeReceipt
object。
- command 对参数的使用类型:根据函数定义,对 object 类参数有不同使用方式。
&mut T
可修改的借用。所谓借用,表示不改变所有权。表示对参数可写。&T
不可修改的借用。表示对参数只读。T
。如果 T 有 copy 能力则复制使用。否则移动使用。在 Sui 中保存在链上的 object 是不可能有 copy 能力的。因为所有 object 都存在sui::object::UID
类型的唯一标识的字段 ID 。
- command 代表一种操作,每种 command 的输入参数可以来自交易的 inputs 或者其他 command 的 results。由于 commands 是一维数组。results 使用二维数组来保存。输入有以下几种
交易完成后,对 inputs 和 results 会进行检查:
- 对 inputs 的检查:
- immutable object 跳过检查,因为不可修改。
- mutable input object 所有权归还 owner。
- pure input 进行 drop。(注:所有 pure 类型都有 copy, drop 能力)
- shared object 仍为 shared 或 deleted。不可 wrap, transfer, freezing。
- 对 results 的检查:
- 有 drop 能力的 drop。
- 有 copy 能力但不含 drop 的,最后一次使用视为 move
- 无 drop 能力的未被使用的 object 报错。(注:利用这个机制可以实现闪电贷)
{
inputs: [
Pure(/* @0x808 BCS bytes */ ...),
Object(SharedObject { /* Marketplace shared object */ id: market_id, ... }),
Pure(/* 100u64 BCS bytes */ ...),
]
commands: [
SplitCoins(GasCoin, [Input(2)]),
MoveCall("some_package", "some_marketplace", "buy_two", [], [Input(1), NestedResult(0, 0)]),
TransferObjects([GasCoin, NestedResult(1, 0)], Input(0)),
MoveCall("sui", "tx_context", "sender", [], []),
TransferObjects([NestedResult(1, 1)], NestedResult(3, 0)),
]
}
执行过程:
- GasCoin 分割出 100
- 调用
some_package::some_marketplace::buy_two(market, Coin<SUI>(100))
买到 2 个 object。 - buy 到的第一个 object 及剩余的 GasCoin 转给 0x808 地址
- 调用
sui::tx_context::sender
得到交易 sender - buy 到的第二个 object 转给 sender