本文档描述了在 Taproot Asset 状态转换交易的“部分签名比特币交易 (PSBT, BIP-0174)”格式中使用的自定义字段。定义了用于表示虚拟资产交易的新字段,并解释了如何将一个或多个虚拟资产交易映射并提交到单个比特币链上“锚”交易中。
forked from bitcoin/bips
bip-tap
在此仓库中搜索
/
复制路径
Blame更多文件操作
Blame更多文件操作
和
bip-tap-psbt: add bip-tap-psbt test vectors
Oct 16, 2023
b9dffde · Oct 16, 2023
打开提交详情
484 行 (444 loc) · 20.1 KB
/
顶部
预览
代码
Blame
484 行 (444 loc) · 20.1 KB
复制原始文件
下载原始文件
轮廓
编辑和 raw 操作
BIP: ???
Layer: Applications
Title: Taproot Assets PSBT
Author: Oliver Gugger <gugger@gmail.com>
Olaoluwa Osuntokun <laolu32@gmail.com>
Comments-Summary: No comments yet.
Comments-URI: https://git
Status: Draft
Type: Standards Track
Created: 2023-02-24
License: BSD-2-Clause
## 目录<br>Permalink: 目录<br>- 摘要<br>- 版权<br>- 设计<br>- 规范<br>- 用于 Taproot Asset 虚拟交易的自定义 PSBT 字段 <br> - 全局类型<br> - 输入类型<br> - 输出类型<br> - PSBT_OUT_TAP_TYPE 的值<br>- 将 Taproot Asset 虚拟交易提交到 BTC 级别锚交易中<br>- BTC 级别锚交易的自定义 PSBT 字段 <br> - 输入类型<br> - 输出类型<br>- 测试向量<br>- 参考实现 |
本文档描述了 Partially\ Signed Bitcoin Transaction (PSBT, BIP-0174) 格式中用于 Taproot Asset 状态转换交易的自定义字段。
本文档采用 2-clause BSD 许可证。
Taproot Asset 状态转换交易也称为“虚拟交易”或资产转移交易。“虚拟”一词用于区分这些仅在链下资产覆盖上下文中发生的资产转移,与“锚”交易(即 BTC 级别的链上交易,它将许多资产级别转移提交到 Bitcoin 链)相对。
虚拟交易与其 Bitcoin 线上传输交易副本有很多相似之处,因为它花费一个或多个资产输入(资产 UTXO 或资产“币”),并创建一个或多个新的资产输出。
与 Bitcoin 交易的主要区别在于,虚拟资产交易不会将满足每个输入的先前输出脚本的见证放在输入本身中,而是使用专用输出的 prev_asset_witnesses
字段,该输出容纳了拆分根资产。这允许将多输入多输出的虚拟交易压缩为 1 输入 1 输出的交易(如 bip-tap-vm 中所述),以便在 Taproot Asset 虚拟机中进行验证。
为了组装满足每个输入的先前输出脚本的完整见证堆栈,交易可能需要由多个参与者和/或设备签名。这需要虚拟交易在多个参与者之间传递,每个参与者都向其添加自己的部分(例如签名)。鉴于虚拟交易与现有 Bitcoin 交易的相似之处,PSBT 格式被选为虚拟资产状态转移的交换格式,并具有一组新的 PSBT <keytype>
,如本文档中所定义。
虚拟交易只能包含彼此之间可互换的资产的输入和输出。如果资产具有相同的 genesis ID(在同一批次中铸造)或引用相同的 group_key
(在不同的批次中铸造),则认为资产是可互换的。
在具有相同 genesis ID 的虚拟交易中,多个输入(资产币)可以以与 Bitcoin 输入可以合并相同的方式合并和拆分并再次拆分。具有不同 genesis ID(但具有相同 group_key
)的可互换资产可以在同一虚拟交易中使用,以满足付款请求,但不允许将两个可互换资产(具有不同的资产 ID)合并到同一资产 UTXO 中。有关更多详细信息,请参见 bip-tap-vm。
虚拟交易输出的构造必须遵循不同的规则,具体取决于接收方是以交互方式还是非交互方式接收输出:
交互式: 接收方将看到完整的虚拟交易(例如,作为 PSBT),包括完全签名的新资产叶。他们拥有能够完全构造 BTC 级别锚输出 Taproot 密钥(包括完整的资产见证以及可能在单个 BTC 级别锚输出中提交的多个资产叶)以观察链上入站传输所需的所有信息。因此,在完整发送叶子(完整值发送)的情况下,不需要“拆分墓碑”(见下文)。
非交互式: 接收方已创建 Taproot Asset 地址,并且仅在链上监视该 Taproot 输出密钥。必须将资产作为拆分资产提交到树中,并在序列化之前先修剪拆分承诺,以使生成的 Taproot Asset 树对于接收方而言是完全可预测的。拆分承诺和根资产证明将在证明文件中交付。完整值发送也必须创建为拆分,发送方创建一个零值“拆分墓碑”输出,该输出以 NUMS 点作为脚本密钥(见下文)。
TODO(guggero): 一旦定义了以非交互方式处理可互换资产的方式,请对其进行描述。
在拆分资产 UTXO 时,将创建一个拆分承诺(如 bip-tap-vm 中所述)。拆分根放置在其中一个输出中(通常是返回给资产发送者的找零输出),并标有 `IsSplitRoot` 标志。如果拆分的剩余找零为 0,则拆分根资产输出的 script_key
应该是众所周知的 NUMS 点(使用字符串“taproot-assets”和传统的“哈希和增量”方法来生成该点),以证明该输出不能进一步花费。所谓的“拆分墓碑”对于非交互式发送(发送到 Taproot Asset 地址)币的全部价值是必需的。在接收方了解完整的根资产叶(包括 TX 见证)并且可以正确构造承诺树的交互场景中,可以修剪这些零值墓碑输出。
Permalink: 用于 Taproot Asset 虚拟交易的自定义 PSBT 字段
BIP-0174 大致定义了 6 个全局、24 个输入和 7 个输出 keytype
。这为新的 BIP 指定其他类型留出了足够的空间,而不会有很大的冲突风险。专有类型 0xFX
不适用于这种情况,因为它适用于应用程序/供应商特定的数据,而不是在 BIP 中声明的字段。
为了进一步降低与其他(正在进行的)BIP 的密钥类型发生冲突的风险,我们从每个新密钥类型部分的(任意选择的)值 0x70
开始。
名称 | <keytype> |
<keydata> |
<keydata> 描述 |
<valuedata> |
<valuedata> 描述 |
---|---|---|---|---|---|
虚拟交易标记 | PSBT_GLOBAL_TAP_IS_VIRTUAL_TX = 0x70 |
无 | 无密钥数据 | <byte 0x01> |
0x01 的静态标记,用于将此交易标识为<br>Taproot Asset 虚拟交易。 |
Taproot Asset 链 HRP | PSBT_GLOBAL_TAP_CHAIN_HRP = 0x71 |
无 | 无密钥数据 | <string HRP> |
Taproot Asset 链标识符的人类可读前缀,如<br>bip-tap-addr 中指定。 |
Taproot Asset PSBT 版本 | PSBT_GLOBAL_TAP_PSBT_VERSION = 0x72 |
无 | 无密钥数据 | <byte version> |
Taproot Asset PSBT 格式的版本。目前,0x00 是<br>唯一已知的和受支持的版本。 |
名称 | <keytype> |
<keydata> |
<keydata> 描述 |
<valuedata> |
<valuedata> 描述 |
---|---|---|---|---|---|
先前的资产叶 | PSBT_IN_TAP_PREV_ID = 0x70 |
无 | 无密钥数据 | <tlv_blob prev_asset_id> |
先前的资产叶(由<br>prev_outpoint || asset_id || asset_script_hash 标识),格式为 TLV,如<br>bip-tap 资产叶格式 中定义。 |
锚输出值 | PSBT_IN_TAP_ANCHOR_VALUE = 0x71 |
无 | 无密钥数据 | <64-bit big endian int value> |
BTC 级别锚输出的 satoshi 值,该输出提交到<br>正在花费的资产输入。 |
锚输出 pkScript |
PSBT_IN_TAP_ANCHOR_PK_SCRIPT = 0x72 |
无 | 无密钥数据 | <bytes pkScript> |
BTC 级别锚输出的 pkScript ,该输出提交到<br>正在花费的资产输入。 |
锚输出 Sighash 类型 | PSBT_IN_TAP_ANCHOR_SIGHASH_TYPE = 0x73 |
无 | 无密钥数据 | <64-bit big endian int sighash type> |
64 位大端无符号整数,指定用于<br>BTC 级别锚输出的 sighash 类型,该输出提交到正在花费的资产输入。 |
锚输出 Taproot 内部密钥 | PSBT_IN_TAP_ANCHOR_TAP_INTERNAL_KEY = 0x74 |
无 | 无密钥数据 | <32-byte xonlypubkey> |
用作 BTC 级别锚输出内部密钥的 X-only 公钥,该输出<br>提交到正在花费的资产输入。 |
锚输出 Taproot Merkle 根 | PSBT_IN_TAP_ANCHOR_TAP_MERKLE_ROOT = 0x75 |
无 | 无密钥数据 | <32-byte hash> |
BTC 级别锚输出的 32 字节 Merkle 根哈希,该输出提交到<br>正在花费的资产输入。 |
锚输出 BIP-0032 派生路径 | PSBT_IN_TAP_ANCHOR_BIP32_DERIVATION = 0x76 |
<bytes pubkey> |
公钥 | <4 byte fingerprint> <32-bit little endian uint path element>* |
由 BIP-0032 定义的主密钥指纹与<br>用于 BTC 级别锚输出的公钥的派生路径连接在一起,该输出提交到资产输入。派生路径表示为彼此连接的 32 位 unsigned integer 索引。<br>公钥是签署此输入所需的那些密钥。 |
锚输出 Taproot 密钥 BIP 32 派生路径 | PSBT_IN_TAP_ANCHOR_TAP_BIP32_DERIVATION = 0x77 |
<32 byte xonlypubkey> |
参与此输入的 32 字节 X-only 公钥。它可能是输出密钥、<br>内部密钥或叶子脚本中存在的密钥。 | <compact size uint number of hashes> <32 byte leaf hash>*<br><4 byte fingerprint> <32-bit little endian uint path element>* |
一个紧凑大小的无符号整数,表示叶子哈希的数量,<br>后跟叶子哈希列表,后跟 4 字节主密钥指纹与公钥的派生路径连接在一起。派生路径<br>表示为彼此连接的 32 位小端无符号整数索引。公钥是花费此输出所需的那些密钥。叶子哈希是涉及此公钥的叶子的哈希。内部密钥没有<br>叶子哈希,因此可以用 hashes len 为 0 表示。Finalizer 应该在<br>PSBT_IN_FINAL_SCRIPTWITNESS 构造后删除此字段。 |
锚输出 Tapscript 同级 | PSBT_IN_TAP_ANCHOR_TAPSCRIPT_SIBLING = 0x78 |
无 | 无密钥数据 | <byte sibling_type><compact size num_bytes><bytes tapscript sibling preimage> |
与 Taproot 处于同一级别的 tapscript 同级的原像<br>Asset 承诺,该承诺已提交到锚中。如果不存在,则<br>Taproot Asset 承诺是树中唯一的脚本叶。 |
Taproot Asset 资产 | PSBT_IN_TAP_ASSET = 0x79 |
无 | 无密钥数据 | <tlv_blob asset> |
正在花费的完整输入资产叶,格式为 TLV,如<br>bip-tap 资产叶格式 中定义。 |
Taproot Asset 证明 | PSBT_IN_TAP_ASSET_PROOF = 0x7a |
无 | 无密钥数据 | <tlv_blob proof> |
正在花费的输入资产的最后一个证明,格式为 TLV,如<br>bip-tap-proof-file 文件序列化 中定义。 |
名称 | <keytype> |
<keydata> |
<keydata> 描述 |
<valuedata> |
<valuedata> 描述 |
---|---|---|---|---|---|
类型 | PSBT_OUT_TAP_TYPE = 0x70 |
无 | 无密钥数据 | <byte output_type> |
一个 uint8 值,指示虚拟输出的类型。有效<br>值为:0x00(Simple )、0x01(SplitRoot )、<br>0x02(PassiveAssetsOnly )、0x03(PassiveSplitRoot ),请参见<br>下面的描述。 |
是否交互式 | PSBT_OUT_TAP_IS_INTERACTIVE = 0x71 |
无 | 无密钥数据 | <byte 0x00/0x01> |
一个布尔值,指示输出的接收者是否知道他们正在接收的完整资产叶(=交互式),或者不知道(=非交互式)。在<br>非交互式情况下,接收者将期望此输出是一个拆分<br>输出。 |
锚输出索引 | PSBT_OUT_TAP_ANCHOR_OUTPUT_INDEX = 0x72 |
无 | 无密钥数据 | <64-bit big endian int value> |
此资产输出将<br>被提交到的 Bitcoin 级别锚交易输出索引。 |
锚输出 Taproot 内部密钥 | PSBT_OUT_TAP_ANCHOR_TAP_INTERNAL_KEY = 0x73 |
无 | 无密钥数据 | <32-byte xonlypubkey> |
用作 BTC 级别锚输出内部密钥的 X-only 公钥,该密钥<br>会将资产输出提交到。 |
锚输出 BIP-0032 派生路径 | PSBT_OUT_TAP_ANCHOR_BIP32_DERIVATION = 0x74 |
<bytes pubkey> |
公钥 | <4 byte fingerprint> <32-bit little endian uint path element>* |
由 BIP-0032 定义的主密钥指纹与<br>将用于 BTC 级别锚<br>输出的公钥的派生路径连接在一起,该输出提交到资产输出。派生路径表示为彼此连接的 32 位 unsigned integer 索引。<br>公钥是签署此输入所需的那些密钥。 |
锚输出 Taproot 密钥 BIP-0032 派生路径 | PSBT_OUT_TAP_ANCHOR_TAP_BIP32_DERIVATION = 0x75 |
<32 byte xonlypubkey> |
参与此输入的 32 字节 X-only 公钥。它可能是输出密钥、<br>内部密钥或叶子脚本中存在的密钥。 | <compact size uint number of hashes> <32 byte leaf hash>*<br><4 byte fingerprint> <32-bit little endian uint path element>* |
一个紧凑大小的无符号整数,表示叶子哈希的数量,<br>后跟叶子哈希列表,后跟 4 字节主密钥指纹与公钥的派生路径连接在一起。派生路径<br>表示为彼此连接的 32 位小端无符号整数索引。公钥是花费此输出所需的那些密钥。叶子哈希是涉及此公钥的叶子的哈希。内部密钥没有<br>叶子哈希,因此可以用 hashes len 为 0 表示。Finalizer 应该在<br>PSBT_IN_FINAL_SCRIPTWITNESS 构造后删除此字段。 |
Taproot Asset | PSBT_OUT_TAP_ASSET = 0x76 |
无 | 无密钥数据 | <tlv_blob asset> |
正在创建的完整输出资产叶,格式为 TLV,如<br>bip-tap 资产叶格式 中定义。 |
Taproot Asset 拆分资产 | PSBT_OUT_TAP_SPLIT_ASSET = 0x77 |
无 | 无密钥数据 | <tlv_blob split_asset> |
如果 PSBT_OUT_TAP_ASSET 中序列化的资产是拆分<br>根(PSBT_OUT_TAP_IS_SPLIT_ROOT=0x01 ),则此字段容纳在根定位器处创建的拆分资产,该根定位器包含拆分承诺见证。这<br>仅用于验证,并且未提交到任何树中。如果存在,则<br>拆分资产以 TLV 格式编码,如<br>bip-tap 资产叶格式 中定义。 |
锚输出 Tapscript 同级 | PSBT_OUT_TAP_ANCHOR_TAPSCRIPT_SIBLING = 0x78 |
无 | 无密钥数据 | <byte sibling_type><compact size num_bytes><bytes tapscript sibling preimage> |
与 Taproot 处于同一级别的 tapscript 同级的原像<br>Asset 承诺,该承诺已提交到锚中。如果不存在,则<br>Taproot Asset 承诺是树中唯一的脚本叶。 |
PSBT_OUT_TAP_TYPE
的值Permalink: PSBT_OUT_TAP_TYPE 的值
PSBT_OUT_TAP_TYPE
字段描述了虚拟输出的类型。此类型会影响资产的签名方式,或者输出中是否根本没有资产。定义了以下值:
Simple(0x00
)是一个普通的完整值或拆分输出,它不是拆分根,也不携带被动资产。对于拆分,此输出的资产具有拆分承诺。
SplitRoot(0x01
)是一个拆分根输出,它携带来自拆分的找零或来自非交互式完整值发送输出的墓碑。在任何一种情况下,此输出的资产都具有 tx 见证。
PassiveAssetsOnly(0x02
)表示此输出仅携带被动资产,因此此输出中的资产为 nil。被动资产本身在其自己的虚拟交易中签名,并且不存在于此数据包中。
PassiveSplitRoot(0x03
)是一个拆分根输出,它携带来自拆分的找零或来自非交互式完整值发送输出的墓碑,以及被动资产。
Permalink: 将 Taproot Asset 虚拟交易提交到 BTC 级别锚交易中
以上部分定义了用于表示虚拟资产交易的新字段。本节说明了如何将一个或多个虚拟资产交易映射到单个 Bitcoin 级别链上“锚”交易中并提交到该交易中。
应采取以下步骤将一个或多个 Taproot Asset 虚拟交易提交到单个 BTC 锚交易中:
PSBT_IN_TAP_ANCHOR_*
)。PSBT_OUT_TAP_ANCHOR_*
)。PSBT_IN_TAP_PREV_ID.prev_outpoint
)是否相同,因为所有字段都应引用同一个链上未花费的输出。PSBT_OUT_TAP_ANCHOR_OUTPUT_INDEX
)是否相同,因为所有字段都应引用正在创建的同一个链上输出。PSBT_IN_TAP_PROOF
)。pkScript
。script_key
为键(字段 PSBT_OUT_TAP_PROOF
)。一旦 BTC 级别锚交易附加了额外信息,就可以将其传递给所有签名者,以生成必要的签名以使其最终确定。
Permalink: BTC 级别锚交易的自定义 PSBT 字段
名称 | <keytype> |
<keydata> |
<keydata> 描述 |
<valuedata> |
<valuedata> 描述 |
---|---|---|---|---|---|
Taproot Asset 证明 | PSBT_IN_TAP_PROOF = 0x70 |
<32 byte xonlyscriptkey> |
正在花费的输入资产的 32 字节 X-only 脚本密钥。 | <tlv_blob proof> |
正在花费的输入资产的最后一个证明,格式为 TLV,如<br>bip-tap-proof-file 文件序列化 中定义。 |
名称 | <keytype> |
<keydata> |
<keydata> 描述 |
<valuedata> |
<valuedata> 描述 |
---|---|---|---|---|---|
Taproot Asset 证明 | PSBT_OUT_TAP_PROOF = 0x70 |
<32 byte xonlyscriptkey> |
正在花费的输入资产的 32 字节 X-only 脚本密钥。 | <tlv_blob proof> |
在此输出中创建的新资产的新转换证明。 |
用于 Taproot Asset 虚拟交易的自定义 PSBT 字段 的测试向量可以在这里找到:
测试向量由 Taproot Assets GitHub 存储库 中的单元测试自动生成。
github.com/lightninglabs/taproot-assets/tree/main/tappsbt
- 原文链接: github.com/Roasbeef/bips...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!