bips/bip-tap-proof-file.mediawiki,位于 bip-tap · Roasbeef/bips

  • Roasbeef
  • 发布于 2025-05-10 23:41
  • 阅读 15

该文档定义了一种扁平文件证明格式,作为打包 Taproot Asset 证明的标准方法。该证明格式本身是给定资产先前谱系的仅附加日志。证明锚定在给定资产的初始“创世输出”处。单个 Taproot Asset 状态转换的证明包括比特币默克尔证明、Taproot Asset 默克尔和稀疏默克尔树 (MS-SMT) 包含证明,最后是一组有效的状态转换见证人。

跳转至内容

Roasbeef/ bips Public

forked from bitcoin/bips

收起文件树

文件

bip-tap

Search this repository

/

bip-tap-proof-file.mediawiki

复制路径

BlameMore file actions

BlameMore file actions

最近提交

halsethRoasbeef

halseth

and

Roasbeef

bip-tap proof file: also first transition now requires witness valida…

打开提交详情

Oct 16, 2023

6652661 · Oct 16, 2023

历史

历史

打开提交详情

View commit history for this file.

343 lines (297 loc) · 19.5 KB

/

bip-tap-proof-file.mediawiki

Top

File metadata and controls

  • Preview

  • Code

  • Blame

343 lines (297 loc) · 19.5 KB

Raw

Copy raw file

Download raw file

Outline

Edit and raw actions

 BIP: ???
  Layer: Applications
  Title: Taproot Asset Flat File Proof Format
  Author: Olaoluwa Osuntokun <laolu32@gmail.com>
  Comments-Summary: No comments yet.
  Comments-URI: https://git
  Status: Draft
  Type: Standards Track
  Created: 2021-12-10
  License: BSD-2-Clause
## Table of Contents<br>Permalink: Table of Contents<br>- Abstract<br>- Copyright<br>- Motivation<br>- Design <br> - Specification <br> - File Serialization<br> - Proof Verification <br> - Ownership proof<br>- Test Vectors<br>- Backwards Compatibility<br>- Reference Implementation

Abstract

Permalink: Abstract

本文档定义了一种平面文件证明格式,作为打包 Taproot Asset 证明的一种标准化方法。证明格式本身是给定资产先前沿袭的仅追加日志。证明锚定在给定资产的初始“创世输出”处。单个 Taproot Asset 状态转换的证明包括 Bitcoin merkle 证明、Taproot Asset merkle-sum sparse merkle tree (MS-SMT) 包含证明,最后是状态转换的一组有效见证。

Copyright

Permalink: Copyright

本文档根据 2-clause BSD 许可证获得许可。

Motivation

Permalink: Motivation

Taproot Asset 协议是一种覆盖协议,可以在基础 Bitcoin 区块链上表示和传输资产。由于 Bitcoin 是一个基于 UTXO 的系统,因此每个资产本身都以初始“创世”交易为根,这标志着该资产的创建。因此,资产由其创世输出定义,因为它标志着其沿袭。为了确保实现能够验证整个生态系统中的出处证明,提出了一种标准化的证明格式。证明格式是状态转换的线性日志,允许简单地将新的传输/转换附加到失败的末尾。

Design

Permalink: Design

为了证明资产的出处,需要在资产过去历史的每个点上提供以下参数:

  • 资产的第一个快照以创世输出为根,如规范 Universe 所规定。
  • 一个有效的 merkle 证明,证明了创世输出和由此产生的已创建资产的包含。
  • 在创世输出之外的每个步骤/转换中:
    • 一个有效的 merkle 证明,证明了花费先前步骤中引用的输出的交易。
    • 一个有效的 MS-SMT opening,证明了资产新位置的承诺。
    • 一个有效的资产见证状态转换,从先前的输出到新的位置。
    • 给定资产存在有效的规范 Taproot Asset 承诺。
    • 如果锚定状态转换的交易具有其他 Taproot (P2TR) 输出,则需要一个有效的 tapscript 排除证明,以证明承诺不会在其他地方重复。

Specification

Permalink: Specification

Taproot Asset 证明文件是一个平面文件,用于记录要验证的给定资产的每个相关状态转换。该文件以增量方式进行验证,如果遇到无效的状态转换或证明,则验证会停止。

文件是一系列以给定创世输出为根的包含和状态转换证明。

File Serialization

Permalink: File Serialization

单个包含和状态转换证明具有以下格式,是一个具有以下格式的 TLV blob:

  • type: 0 ( version)
    • value:
    • [ uint32: version]
  • type: 1 ( prev_out)
    • value:
    • [ 36*byte: txid || output_index]
  • type: 2 ( block_header)
    • value:
    • [ 80*byte: bitcoin_header]
  • type: 3 ( anchor_tx)
    • value:
    • [ ...*byte: serialized_bitcoin_tx]
  • type: 4 ( anchor_tx_merkle_proof)
    • value:
    • [ ...*byte: merkle_inclusion_proof]
  • type: 5 ( taproot_asset_asset_leaf)
    • value:
    • [ tlv_blob: serialized_tlv_leaf]
  • type: 6 ( taproot_asset_inclusion_proofs)
    • value:
    • [ ...*byte: taproot_asset_taproot_proof]
      • type: 0 ( output_index
      • value: [ int32: index]
      • type: 1 ( internal_key
      • value: [ 33*byte: y_parity_byte || schnorr_x_only_key]
      • type: 2 ( taproot_asset_proof)
      • value: [ ...*byte: asset_proof]
        • type: 0 ( taproot_asset_proof)
        • value: [ ...*byte: asset_inclusion_proof]
        • type: 0
          • value: [ uint32: proof_version]
        • type: 1
          • value: [ 32*byte: asset_id]
        • type: 2
          • value: [ ...*byte: ms_smt_inclusion_proof]
        • type: 1 ( taproot_asset_inclusion_proof)
        • value: [ ...*byte: taproot_asset_inclusion_proof]
        • type: 0
          • value: [ uint32: proof_version]
        • type: 1
          • value: [ ...*byte: ms_smt_inclusion_proof]
        • type: 2 ( taproot_sibling_preimage)
          • value: [ byte: sibling_type][ varint: num_bytes][ ...*byte: tapscript_preimage]
      • type: 3 ( taproot_asset_commitment_exclusion_proof
      • value: [ ...*byte: taproot_exclusion_proof]
        • type: 0 ( tap_image_1)
        • value: [ ...*byte: tapscript_preimage]
        • type: 1 ( tap_image_2)
        • value: [ ...*byte: tapscript_preimage]
        • type: 2 ( bip_86)
        • value: [ byte 0x00/0x01: bip_86]
  • type: 7 ( taproot_exclusion_proofs)
    • value:
    • [ uint16: num_proofs][ ...*byte: taproot_asset_taproot_proof]
  • type: 8 ( split_root_proof)
    • value:
    • [ ...*byte: taproot_asset_taproot_proof]
  • type: 9 ( meta_reveal)
    • value:
    • [ ...*byte: asset_meta_reveal]
      • type: 0 ( meta_type
      • value: [ uint8: type]
      • type: 1 ( meta_data
      • value: [ *byte: meta_data_bytes]
  • type: 10 ( taproot_asset_input_splits)
    • value:
    • [ ...*byte: nested_proof_map]
  • type: 11 ( challenge_witness)
    • value:
    • [ ...*byte: challenge_witness]
  • type: 12 ( block_height)
    • value:
    • [ uint32: block_height]
  • type: 12 ( asset_genesis)
    • value:
    • [ 32*byte: first_prev_out_hash]
    • [ u32: first_prev_out_index]
    • [ BigSize: tag_len]
    • [ tag_len*byte: tag]
    • [ BigSize: metadata_len]
    • [ metadata_len*byte: metadata]
    • [ u32: output_index]
    • [ u8: type]
  • type: 13 ( asset_group_key_reveal)
    • value:
    • [ 64*byte: pub_key || asset_group_script_root]

where:

  • version: 是单次 mint 或转换证明的版本,当前固定为值 0
  • prev_out: 是 Taproot Asset 承诺输出的 36 字节 outpoint,该输出正在被花费。如果这是第一个证明,那么该值将是给定资产的“创世 outpoint”。
  • block_header: 是包含上述 outpoint 花费的 80 字节区块头。
  • merkle_inclusion_proof: 是花费 previous_outpoint 的交易的 merkle 包含证明。它使用 BigSize 长度前缀序列化为:
    • proof_node_count || serialized_proof || proof_direction_bits
    • where:
    • proof_node_count 是一个 BigSize 整数,用于指定证明中的节点数。
    • serialized_proofproof_node_count*32 字节,用于证明路径。
    • proof_direction_bits 是一个大小为 length_of_proof 的位域,值为 0 表示左方向,值为 1 表示右方向。
  • anchor_tx: 是花费 previous_outpoint 的交易。此交易在其输出之一中至少提交给一个 Taproot Asset 树。
  • taproot_asset_taproot_proof: 是一个嵌套的 TLV,可用于证明 Taproot Asset 的包含或不存在,或者通过 taproot_asset_commitment_exclusion_proof 证明缺少 Taproot Asset 承诺。
  • taproot_exclusion_proofs: 是一系列 排除 证明,用于证明交易中的其他输出没有提交给有效的 Taproot Asset。这会重复使用 taproot_asset_taproot_proof 结构,但只会包含 taproot_asset_commitment_exclusion_proof 值,而不会同时包含 taproot_asset_taproot_proof 值。
  • split_root_proof: 是一个可选的 taproot_asset_taproot_proof,用于证明在资产拆分的情况下,拆分承诺的根资产的包含。
  • taproot_asset_input_splits: 是一个可选的嵌套完整证明列表,用于在结果资产中找到的任何其他输入。
  • asset_meta_reveal: 是一个强制字段(对于创世资产),用于显示资产 TLV 中包含的 asset_meta_hash 的 pre-image。
    • meta_type 字段可用于指示如何解析/呈现元数据 pre-image。
    • 当前定义的元类型有:
      • 0:没有真正的类型,只是指定一个不透明的数据 blob。
    • meta_data 是原始元数据本身。
    • 如果包含的资产是创世资产(具有有效的创世见证),则验证者应验证:`sha256(tlv_encode(meta_reveal)) == asset_meta_hash`。
    • 此字段必须仅存在于创世资产证明中。
  • challenge_witness 是一个可选的资产见证,通过一个明确定义的资产状态转换,证明了资产当前所在的 script_key 的所有权。
  • block_height: 是包含 prev_out outpoint 花费的区块的区块高度。
  • asset_genesis: 是创世资产的强制字段。asset_genesis 表示 asset_id 的 pre-image。
    • 此字段必须仅存在于创世资产证明中。
  • asset_group_key_reveal: 是 (对于具有组密钥的创世资产) 的强制字段,它揭示了推导资产组密钥所需的原始内部签名密钥和脚本根:asset_raw_group_key = asset_group_key_reveal[0:32]asset_group_script_root = asset_group_key_reveal[32:64]
    • asset_raw_group_key: 是一个 32 字节的公钥,由 BIP-340 定义。原始公钥在创世时被揭示,以便验证者检查组密钥的推导。当 mint 资产时,相应私钥的所有者能够使用密钥花费路径为组密钥签名。
    • asset_group_script_root: 是一个 32 字节的 tapscript 根,由 BIP-341 定义。根在创世时被揭示,以便验证者检查组密钥的推导。根可以保存任意脚本,这些脚本强制执行 mint 资产的条件。
    • 如果包含的资产是创世资产(具有有效的创世见证),则验证者应根据 [bip-tap] 验证:asset_group_key == GroupKey(asset_id, asset_raw_group_key, asset_group_script_root)
    • 此字段必须仅存在于具有组密钥的创世资产证明中。

最终的平面证明文件具有以下格式:

  • [ u32: file_version] 证明文件格式的版本,当前固定为 0
  • [ BigSize: num_proofs] 文件中包含的证明数量
  • [ num_proof*proof: proofs] 编码的证明
    • [ BigSize: proof_len] 编码证明的长度
    • [ proof_len*byte: proof_tlv_bytes] 单个证明编码为 TLV 流,如上所述
    • [ 32*byte: proof_checksum] 证明的校验和,它是 SHA256(prev_hash || proof_tlv_bytes),其中 prev_hash 是先前证明的校验和,对于第一个证明,则为零哈希。
Proof Verification

Permalink: Proof Verification

证明文件的验证从第一个条目(创世输出创建)开始,并向前推进,依次验证每个状态转换和包含证明。如果发现任何状态转换无效,则资产证明无效。否则,如果在没有任何违规的情况下完全使用该文件,则该证明被认为是有效的。

给定资产的证明文件 f_proof,创世 outpoint g,验证定义如下:

  1. 验证证明文件的完整性:
    1. 对于每个证明,提取 proof_lenproof_len 个字节作为 proof_tlv_bytes 和 32 个字节 proof_checksum
    2. 计算 SHA256(prev_hash || proof_tlv_bytes),其中 prev_hash 是先前证明的 proof_checksum,对于文件中的第一个证明,则为 32 字节的零哈希。
    3. 如果此计算值与 proof_checksum 不匹配,则验证失败。
  2. 验证每个包含证明和状态转换:
    1. 从平面文件中解析下一个证明块。
    2. 如果这是要验证的第一个证明:
      1. previous_outpoint 存储为创世 outpoint。
    3. 否则,验证 anchor_transaction 是否具有花费 先前 previous_outpoint 的输入。
    4. 给定 anchor_transaction,验证包含的 merkle_inclusion_proof 是否以 block_header 的 merkle 根为根有效。
    5. 解析 tlv_proof_map
    6. 如果 anchor_transaction 没有 至少 asset_output_pos 个输出,则验证失败。
    7. 验证 asset_leaf_proof 是否使用指定的 internal_keytaproot_asset_leaf 嵌入到以 asset_output_pos 为根的输出中,以计算 taproot 承诺。
    8. 验证在 taproot_asset_leafprev_asset_witness 字段中包含的资产见证是否基于特定的 asset_script_version 有效。
    9. 如果存在 split_commitment_opening,则验证包含的 leaf 是否是以 taproot_asset_leafsplit_commitment_root 字段为根的有效 opening。
    10. 如果存在 split_commitment_opening,则验证 split_root_proof 中是否存在 split_commitment_root's leaf 的包含证明。
    11. 如果资产是创世资产,并且存在 asset_meta 字段,则验证 sha256(asset_meta) == asset.asset_meta_hash

以下是平面文件验证的伪代码例程:

verify_asset_file_proof(file_proof []byte, genesis_outpoint OutPoint,
    assetID [32]byte) -> bool

    genesis_outpoint, prev_outpoint = None
    file_reader = new_bytes_reader(file_proof)
    prev_hash = bytes(32)
    while file_reader.len() != 0:
        proof_block = parse_proof_block(file_reader)

        sha_sum = sh256(prev_hash + proof_block.bytes())
        if proof_block.proof_checksum != sha_sum:
            return false

        if genesis_outpoint is None:
            genesis_outpoint = proof_block.previous_outpoint

        txn = proof_block.txn
        if genesis_outpoint is not None:
           if !spends_prev_out(txn):
               return false

        if !verify_merkle_proof(
            proof_block.block_header, proof_block.merkle_inclusion_proof, txn,
        ):
            return false

        proof_tlv_map = proof_block.tlv_map

        if len(txn.outputs) &lt; proof_tlv_map.asset_output_pos:
            return false

        if !verify_asset_tree_proof(
            txn, proof_tlv_map.taproot_asset_leaf, proof_tlv_map.asset_leaf_proof,
        ):
            return false

        if !verify_taproot_asset_state_transition(proof_tlv_map.taproot_asset_leaf):
            return false

        if proof_tlv_map.challenge_witness is not None:
            new_leaf = clone_unique_leaf(proof_tlv_map.taproot_asset_leaf)
            new_leaf.script_key = NUMS_key
            new_leaf.prev_witnesses = {{
                prev_id: {
                    asset_id:   proof_tlv_map.taproot_asset_leaf.asset_id
                    outpoint:   00000000...0000000:0
                    script_key: proof_tlv_map.taproot_asset_leaf.script_key
                }
                tx_witness: proof_tlv_map.challenge_witness
            }}

            if !verify_taproot_asset_state_transition(new_leaf):
                return false

        if proof_tlv_map.split_commitment_opening is not None:
            if !verify_split_commitment(
                proof_tlv_map.taproot_asset_leaf,
                proof_tlv_map.split_commitment_opening,
            ):
                return false

            if !verify_asset_tree_proof(
                txn,
                proof_tlv_map.split_commitment_opening.split_commitment_root,
                proof_tlv_map.split_root_proof,
            ):
                return false

        has_meta_reveal = proof_tlv_map.meta_reveal is not None
        has_meta_hash = proof_tlv_map.asset.meta_hash is not None
        is_genesis_asset = is_genesis_asset(proof_tlv_map.asset)
        match:
            case has_meta_reveal && !is_genesis_asset:
                return false

            case has_meta_reveal && is_genesis_asset:
                meta_hash := sha256(meta_reveal)
                if meta_hash != proof_tlv_map.asset.meta_hash:
                    return false

            case has_meta_hash && is_genesis_asset && !has_meta_reveal:
                return false

            case !has_meta_reveal && is_genesis_asset:
                return false

    return true
Ownership proof

Permalink: Ownership proof

可以通过 challenge_witness 字段将可选的所有权证明添加到证明中。该见证必须是有效的资产 tx_witness,通过明确定义的资产状态转换,将资产的全部金额花费到 NUMS 密钥。可以使用以下步骤创建状态转换:

  1. 创建要证明的所有权的资产的深层副本。
  2. prev_witnesses 列表截断为仅一个元素。
  3. prev_witnesses[0].prev_id.out_point 设置为空的 outpoint (所有 zero hash 和 zero index)。
  4. prev_witnesses[0].prev_id.script_key 设置为资产的脚本密钥。
  5. 将资产的 script_key 设置为 NUMS 密钥。
  6. 使用交互式流程(无拆分墓碑)创建资产状态转换的签名。
  7. 仅从签名的状态转换中提取 prev_witnesses[0].tx_witness,并将其作为 challenge_witness 附加到证明中。

Test Vectors

Permalink: Test Vectors

File Serialization 的测试向量可以在这里找到:

一些测试向量由以下位置自动生成 Taproot Assets GitHub 存储库中的\ 单元测试

Backwards Compatibility

Permalink: Backwards Compatibility

Reference Implementation

Permalink: Reference Implementation

github.com/lightninglabs/taproot-assets/tree/main/proof

  • 原文链接: github.com/Roasbeef/bips...
  • 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
Roasbeef
Roasbeef
江湖只有他的大名,没有他的介绍。