该文档定义了一种扁平文件证明格式,作为打包 Taproot Asset 证明的标准方法。该证明格式本身是给定资产先前谱系的仅附加日志。证明锚定在给定资产的初始“创世输出”处。单个 Taproot Asset 状态转换的证明包括比特币默克尔证明、Taproot Asset 默克尔和稀疏默克尔树 (MS-SMT) 包含证明,最后是一组有效的状态转换见证人。
forked from bitcoin/bips
bip-tap
Search this repository
/
复制路径
BlameMore file actions
BlameMore file actions
and
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
/
Top
Preview
Code
Blame
343 lines (297 loc) · 19.5 KB
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 |
本文档定义了一种平面文件证明格式,作为打包 Taproot Asset 证明的一种标准化方法。证明格式本身是给定资产先前沿袭的仅追加日志。证明锚定在给定资产的初始“创世输出”处。单个 Taproot Asset 状态转换的证明包括 Bitcoin merkle 证明、Taproot Asset merkle-sum sparse merkle tree (MS-SMT) 包含证明,最后是状态转换的一组有效见证。
本文档根据 2-clause BSD 许可证获得许可。
Taproot Asset 协议是一种覆盖协议,可以在基础 Bitcoin 区块链上表示和传输资产。由于 Bitcoin 是一个基于 UTXO 的系统,因此每个资产本身都以初始“创世”交易为根,这标志着该资产的创建。因此,资产由其创世输出定义,因为它标志着其沿袭。为了确保实现能够验证整个生态系统中的出处证明,提出了一种标准化的证明格式。证明格式是状态转换的线性日志,允许简单地将新的传输/转换附加到失败的末尾。
为了证明资产的出处,需要在资产过去历史的每个点上提供以下参数:
Taproot Asset 证明文件是一个平面文件,用于记录要验证的给定资产的每个相关状态转换。该文件以增量方式进行验证,如果遇到无效的状态转换或证明,则验证会停止。
文件是一系列以给定创世输出为根的包含和状态转换证明。
单个包含和状态转换证明具有以下格式,是一个具有以下格式的 TLV blob:
version
)
uint32
: version
]prev_out
)
36*byte
: txid || output_index
]block_header
)
80*byte
: bitcoin_header
]anchor_tx
)
...*byte
: serialized_bitcoin_tx
]anchor_tx_merkle_proof
)
...*byte
: merkle_inclusion_proof
]taproot_asset_asset_leaf
)
tlv_blob
: serialized_tlv_leaf
]taproot_asset_inclusion_proofs
)
...*byte
: taproot_asset_taproot_proof
]
output_index
int32
: index
]internal_key
33*byte
: y_parity_byte || schnorr_x_only_key
]taproot_asset_proof
)...*byte
: asset_proof
]
taproot_asset_proof
)...*byte
: asset_inclusion_proof
]uint32
: proof_version
]32*byte
: asset_id
]...*byte
: ms_smt_inclusion_proof
]taproot_asset_inclusion_proof
)...*byte
: taproot_asset_inclusion_proof
]uint32
: proof_version
]...*byte
: ms_smt_inclusion_proof
]taproot_sibling_preimage
)
byte
: sibling_type
][ varint
: num_bytes
][ ...*byte
: tapscript_preimage
]taproot_asset_commitment_exclusion_proof
...*byte
: taproot_exclusion_proof
]
tap_image_1
)...*byte
: tapscript_preimage
]tap_image_2
)...*byte
: tapscript_preimage
]bip_86
)byte 0x00/0x01
: bip_86
]taproot_exclusion_proofs
)
uint16
: num_proofs
][ ...*byte
: taproot_asset_taproot_proof
]split_root_proof
)
...*byte
: taproot_asset_taproot_proof
]meta_reveal
)
...*byte
: asset_meta_reveal
]
meta_type
uint8
: type
]meta_data
*byte
: meta_data_bytes
]taproot_asset_input_splits
)
...*byte
: nested_proof_map
]challenge_witness
)
...*byte
: challenge_witness
]block_height
)
uint32
: block_height
]asset_genesis
)
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
]asset_group_key_reveal
)
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
proof_node_count
是一个 BigSize
整数,用于指定证明中的节点数。serialized_proof
是 proof_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
是原始元数据本身。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 资产的条件。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
是先前证明的校验和,对于第一个证明,则为零哈希。证明文件的验证从第一个条目(创世输出创建)开始,并向前推进,依次验证每个状态转换和包含证明。如果发现任何状态转换无效,则资产证明无效。否则,如果在没有任何违规的情况下完全使用该文件,则该证明被认为是有效的。
给定资产的证明文件 f_proof
,创世 outpoint
g
,验证定义如下:
proof_len
、proof_len
个字节作为 proof_tlv_bytes
和 32 个字节 proof_checksum
。SHA256(prev_hash || proof_tlv_bytes)
,其中 prev_hash
是先前证明的 proof_checksum
,对于文件中的第一个证明,则为 32 字节的零哈希。proof_checksum
不匹配,则验证失败。previous_outpoint
存储为创世 outpoint。anchor_transaction
是否具有花费 先前 previous_outpoint
的输入。anchor_transaction
,验证包含的 merkle_inclusion_proof
是否以 block_header
的 merkle 根为根有效。tlv_proof_map
。anchor_transaction
没有 至少 asset_output_pos
个输出,则验证失败。asset_leaf_proof
是否使用指定的 internal_key
将 taproot_asset_leaf
嵌入到以 asset_output_pos
为根的输出中,以计算 taproot 承诺。taproot_asset_leaf
的 prev_asset_witness
字段中包含的资产见证是否基于特定的 asset_script_version
有效。split_commitment_opening
,则验证包含的 leaf 是否是以 taproot_asset_leaf
的 split_commitment_root
字段为根的有效 opening。split_commitment_opening
,则验证 split_root_proof
中是否存在 split_commitment_root
's leaf 的包含证明。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) < 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
可以通过 challenge_witness
字段将可选的所有权证明添加到证明中。该见证必须是有效的资产 tx_witness
,通过明确定义的资产状态转换,将资产的全部金额花费到 NUMS 密钥。可以使用以下步骤创建状态转换:
prev_witnesses
列表截断为仅一个元素。prev_witnesses[0].prev_id.out_point
设置为空的 outpoint (所有 zero hash 和 zero index)。prev_witnesses[0].prev_id.script_key
设置为资产的脚本密钥。script_key
设置为 NUMS 密钥。prev_witnesses[0].tx_witness
,并将其作为 challenge_witness
附加到证明中。File Serialization 的测试向量可以在这里找到:
一些测试向量由以下位置自动生成 Taproot Assets GitHub 存储库中的\ 单元测试。
Permalink: Backwards Compatibility
Permalink: Reference Implementation
github.com/lightninglabs/taproot-assets/tree/main/proof
- 原文链接: github.com/Roasbeef/bips...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!