bips/bip-tap-universe.mediawiki,位于 Roasbeef/bips 的 Taproot 资产宇宙

  • Roasbeef
  • 发布于 2025-04-02 17:16
  • 阅读 20

该文档提出了 Taproot Asset Universe 的概念,旨在为资产的用户/持有者提供一种简便的方法来引导其对给定创世点的识别,以此作为资产的根。Universe 是一个 MS-SMT,它索引到用于跟踪资产移动/转移的已花费输出集合中。Universe 可以包含资产的创世输出集合、多个资产,跟踪单个交易,并用作聚合层。

跳至内容

Roasbeef/ bips 公开

fork 自 bitcoin/bips

折叠文件树

文件

bip-tap

搜索此仓库

/

bip-tap-universe.mediawiki

复制路径

Blame 更多文件操作

Blame 更多文件操作

最近提交

ffranrRoasbeef

ffranr

Roasbeef

bip-tap: 移除上层树值字段中的 asset_group_sum 拼接

打开提交详情

2023年10月16日

a3f98ef · 2023年10月16日

历史

历史

打开提交详情

查看此文件的提交历史。

718 行 (577 loc) · 31.6 KB

/

bip-tap-universe.mediawiki

顶部

文件元数据和控制

  • 预览

  • 代码

  • Blame

718 行 (577 loc) · 31.6 KB

Raw

复制原始文件

下载原始文件

大纲

编辑和原始操作

 BIP: ???
  Layer: Applications
  Title: Taproot Asset Universes
  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
## 目录<br>永久链接:目录<br>- 摘要<br>- 版权<br>- 动机<br>- 设计 <br> - 规范 <br> - 资产宇宙<br> - 根宇宙 & 创世资产验证 <br> - 规范根宇宙状态转换规则<br> - 资产多元宇宙<br> - 袖珍宇宙:链下 Taproot 资产转移压缩 <br> - 袖珍宇宙创建 <br> - 袖珍宇宙动态成员:Taproot 资产虚拟交易图<br> - 加入袖珍宇宙<br> - 袖珍宇宙交易<br> - =离开袖珍宇宙=<br> - 资产宇宙 API & 联邦式同步 <br> - 宇宙 gRPC API<br> - 宇宙 REST API<br> - 简单宇宙同步<br>- 测试向量<br>- 向后兼容性<br>- 参考实现

摘要

永久链接:摘要

Taproot 资产的来源由资产的谱系定义,一直追溯到创世点,即从中派生出唯一资产标识符的输出点。提出了 Taproot 资产宇宙,作为资产的用户/持有者轻松启动他们对给定创世点作为资产根的识别的一种方式。宇宙是一个 MS-SMT,它索引到跟踪资产移动/转移的已花费输出点的集合中。一个宇宙可以包含资产的创世输出点的集合、多个资产、跟踪单个交易,并且还可以用作聚合层。

版权

永久链接:版权

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

动机

永久链接:动机

为了让资产的用户/持有者能够轻松地引导来源,并跟踪给定资产已发行的单位总数,需要一个链上默克尔化索引结构。此外,如果我们定义关于如何更新“规范”宇宙的约束,那么用户可以监视一组链上输出,以便在进一步的链发行时收到通知。继续构建这个结构,如果用户能够与资产的发行者保持信任关系(例如,资产属于一个闭源游戏),那么他们可以将更新权限委托给单个或联邦方,允许他们在单个交易中捆绑多个资产更新,从而扩展链上转移。

设计

永久链接:设计

Taproot 资产宇宙 MS-SMT 与普通 MS-SMT 的不同之处在于,最低树的密钥索引是从一个输出点和`脚本密钥``派生的,而不是从资产脚本密钥派生的,因为给定一个资产_存在_的输出点,资产宇宙映射到 Taproot 资产交易+花费元数据。给定这个输出点索引结构,如果我们创建一个新的“重新创世”(以创建一个虚拟交易图)输出点,那么我们可以构建一个新的虚拟 Taproot 资产交易图,该图可以证明地以链下的方式跟踪资产的移动,依赖于单个或联邦方来处理更新。

规范

永久链接:规范

资产宇宙

永久链接:资产宇宙

资产宇宙是一个公开可审计的默克尔和稀疏默克尔树 (MS-SMT),覆盖一个或多个资产。与正常的 Taproot 资产树不同,宇宙不用于保管 Taproot 资产。相反,宇宙承诺一个或多个资产历史的子集。一个与公共宇宙非常相似的类比是区块浏览器。宇宙可用于:

  • 通过承诺一组创世输出,来引导证明验证。
  • 通过额外的信任假设,生成更紧凑的证明。
  • 审计给定资产存在的单位总数。
  • 跟踪给定资产 ID 的新资产发行。

宇宙还可以用于将一系列转移的历史压缩为单个链上交易。这种变体称为袖珍宇宙。从这个角度来看,袖珍宇宙可以被看作是一种 Taproot 资产通道,其中一方(或由他们组成的联盟/阈值)可以批量更新一棵树,以便在单个链上交易中清除无数的转移。这样的宇宙也可以在多个资产上创建,有效地成为宇宙的宇宙,或者一个多元宇宙

在资产创建期间,创建资产的一方(由其全零 prev_asset_id 值标识)可能还会指定一个 canonical_universe(规范宇宙)字段,该字段指定对产生的输出集合的额外约束。也就是说,如果在资产创建期间指定了此字段,那么创世输出点之后的下一个花费的第一个输出必须提交到一个更新的基础宇宙,该宇宙索引到之前的创世输出点花费(资产创建)。此外,输出使用的内部密钥必须是在资产创建期间指定的 asset_group_key 字段。在每次后续的资产发行事件之后,应该更新此输出以提交到索引链上所有资产发行交易的新的更新的基础宇宙。

指定密钥有效地在链上祝福(bless)一个公钥,允许它用于提交资产的“规范”历史。此外,那些希望收到新资产发行“通知”的人可以监视链上的这个输出,以跟踪任何修改。

根宇宙 & 创世资产验证

永久链接:根宇宙 & 创世资产验证

与正常的 Taproot 资产树不同,给定资产的基础宇宙只提交到资产的创世输出点集合。每个叶子的值包含足够的信息来完全验证创建资产的交易的存在。由于这种类型的宇宙只提交到存在于【开头】的组成资产的集合,所有其他的转移都依赖于这些资产,我们称之为宇宙。

这样的宇宙可以用于引导来源和证明验证,因为假设一方知道要查询哪个宇宙,他们就能够验证一个所谓的有效资产的来源。除了引导来源验证之外,由于【宇宙】树本身就是一个 MS-SMT,它们可以用来审计给定资产的单位总数。

根宇宙是一个 MS-SMT,具有以下结构:

  • MS-SMT 根提交到给定 genesisAssetID 发行的资产总数的总和
    • genesisAssetID 可以是一个普通 assetIDsha256(asset_group_key)。在后一种情况下,树中的所有值必须共享相同的 asset_group_key
    • key: 一个 sha256(outpoint || scriptKey)。给定资产 ID,这唯一地定位了目标输出点中的新铸造事件。
    • value: universe_proof_leaf
    • sum_value: 证明叶子发行的资产单位总数。

根宇宙的密钥是一个序列化的比特币输出点。因此,宇宙结构可以用于查询在给定输出点上扎根的 Taproot 资产的存在。对于根宇宙,跟踪的唯一输出点是创建 Taproot 资产的输出点。

由于 MS-SMT 由 sha256(outpoint || scriptKey) 键控,它可以用于引导所谓的资产的任何证明验证,因为初始链接取决于引用的 genesisOutpoint 的来源(验证从【开头】开始并向后工作)。

universe_proof_leaf:是来自 bip-tap-proof-file.mediawiki 格式的状态转换证明:

  • type: 0 ( prev_out)
    • value:
    • [36*byte: txid || output_index]
  • type: 1 ( block_header)
    • value:
    • [80*byte: bitcoin_header]
  • type: 2 ( anchor_tx)
    • value:
    • [...*byte: serialized_bitcoin_tx]
  • type: 3 ( anchor_tx_merkle_proof)
    • value:
    • [...*byte: merkle_inclusion_proof]
  • type: 4 ( taproot_asset_leaf)
    • value:
    • [tlv_blob: serialized_tlv_leaf]
  • type: 5 ( 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: 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: 6 ( taproot_exclusion_proofs)
    • value:
    • [uint16: num_proofs][...*byte: taproot_asset_taproot_proof]

这与用于向第三方证明资产创建的状态转换证明相同。根宇宙的叶子值允许验证者完全验证基于花费的创世输出点的资产的创建。

规范根宇宙状态转换规则

永久链接:规范根宇宙状态转换规则

为了为给定资产的供应和发行事件提供权威的真相来源,资产可能在首次铸造时指定一个规范根宇宙。如果 canonical_universe TLV 存在于创世资产中,则必须将以下限制应用于花费铸造输出的后续交易:

  • 当铸造输出被花费时,结果交易的第一个输出必须
    • 使用揭示的 asset_group_key 的内部密钥作为 V1 Taproot 见证程序的内部密钥。
    • 新创建的输出的 tapscript 树必须包含一个新的根宇宙承诺,该承诺包括初始铸造事件。
    • 我们将此输出称为 root_asset_commitment
    • 如果在之前的交易中发行了单个 asset_group 中的多个资产,那么根宇宙必须包含所有新资产。
  • 对于使用 asset_group_key 发行的资产,每次发行新资产时:
    • 必须花费最新的未花费的 root_asset_commitment 输出。
    • 这用于链接新的发行事件,并揭示一个新的规范根宇宙哈希。
    • 此花费交易的第一个输出继承了上述要求:
    • 一个新的更新的根宇宙承诺包含在 root_asset_commitment 中。
    • 这个新的 root_asset_commitment 成为该资产新的更新的供应锚点。

上面陈述的规则有效地充当了一个迭代的提交和揭示游戏。每次发行新资产(花费了发行承诺)时,结果交易的第一个输出必须提交到新的根宇宙哈希。所有其他后续发行事件必须然后花费相同的输出,从而更新到根宇宙哈希的承诺。

由于上述链承诺结构,可以使用一系列默克尔证明来验证针对资产的最新规范根宇宙的所有查询:

  • 一个锚定在块头中的默克尔证明,该块头挖掘了具有 root_asset_commitment 的交易。
  • 一个 tapscript 默克尔证明,用于显示根宇宙哈希包含在 tapscript 树中。
  • 一个 MS-SMT 默克尔证明,用于显示正在验证的资产确实是根宇宙承诺链的一部分。

为了强制执行根宇宙哈希承诺的唯一性,我们在 bip-tap.mediawiki 中利用相同的 tapscript 承诺唯一性规则。我们使用修改后的承诺结构:

  • tagged_hash("TapLeaf", leaf_version || universe_marker || universe_version || root_universe_hash)

其中:

  • universe_marker: 是 ascii 字符串 "universe" 的 sha256 哈希值。
  • 由于给定资产的根宇宙可以在初始资产时已知

基于被引用的 &lt;code>universeKey 那些希望跟踪与给定 genesisAssetID 相关的任何新资产发行的人可以监视链上的输出。每次花费输出都表示一个新的铸造事件。因此,客户端能够监视链上选择的输出集合,每个 genesisAssetID 对应一个他们关心的输出点,有效地使用区块链在每次发行资产总额发生变化时收到通知。

资产多元宇宙

永久链接:资产多元宇宙

资产多元宇宙是宇宙的宇宙。多元宇宙不仅仅存储组成资产的集合(genesisOutpoints 的集合),而是提交到几个根 assetIDs,并且还可以提交到资产转移的证明(包括拆分+合并)。因此,多元宇宙实际上是对可能发生过的每一个资产转移的承诺。重要的是,不能证明多元宇宙有完整的历史,因为多元宇宙只能提交到它直接观察到或向它展示的内容。

一个多元宇宙具有以下结构:

  • 与正常的 Taproot 资产承诺类似,多元宇宙本身包含两个嵌套的 MS-SMT 树。上层树提交到观察到的资产组集合,下层树提交到每个资产组的交易历史。
  • 上层树结构:
    • key: asset_idsha256(asset_key_family)
    • value: asset_group_tree_root
    • sum_value: asset_group_sum
  • 下层树结构:
    • key: 一个 sha256(outpoint || scriptKey),以 txid:vout 结构序列化,就像我们在比特币中发现的那样。
    • value: universe_proof_leaf
    • sum_value: 证明叶子发行的资产单位总数。

因此,多元宇宙提交到已知的创世 ID 集合,并在第二个层次提交到每个被监视资产的完整宇宙树集合。

有了这个结构,多元宇宙的维护者也可以存储主观上完整的转移历史集合。此外,这个结构可以用来追踪给定资产的转移/谱系集合。请注意,我们有效地提交到与资产相关联的所有已创建输出的集合,其中第一个花费是 genesisOutpoint 花费。因此,一个【资产的完整来源证明】仅仅是在 SMT 最低层存储的一系列密钥,验证者遵循树中从一个输出点到另一个输出点的转移。

使用上面提出的特性,人们可以创建一个平面文件,通过简单地从一个多元宇宙树中提取选择的分支,并枚举验证需要断言的密钥集合,来证明一个资产的来源。

袖珍宇宙:链下 Taproot 资产转移压缩

永久链接:袖珍宇宙:链下 Taproot 资产转移压缩

多元宇宙中的所有叶子本身都是对链上发生的事件的承诺:一个 Taproot 资产转移。唯一资产的证明有一个很好的特性,即它们在资产转移的数量上线性地缩放(你不能拆分/合并,所以相同的单位被转移到不同的所有者集合)。普通资产提供了更大的灵活性,但缩放得更差,因为持有的单个资产实际上可能是几个 Taproot 资产 UTXO 的合并,从而增加了证明大小作为资产历史中的拆分/合并数量的函数。袖珍宇宙是一种链下转移压缩系统,它允许一个联盟对在“想象的”宇宙中发生的资产转移进行盖时间戳。

为了进一步降低验证成本,验证者可以选择只验证一个输入拆分,一直追溯到创世输出点。这实现了一种简单的概率验证形式,因为每个未验证的拆分无效的可能性呈指数级下降。

袖珍宇宙类似于一个承诺链。一个单独的一方,或一组方,承诺到主链中的一组转移,这些转移本身锚定到一个初始的可验证的 genesisOutpoint。因此,袖珍宇宙是一个扩展工具,由于链上有一个新的承诺,实质上无限量的转移可以在链中被盖时间戳。袖珍宇宙可能在一方发行了资产的情况下有用,这些资产只能在发行者的帮助下使用,例如,游戏中的资产。尽管袖珍宇宙依赖于一个联邦,但在发生审查事件的情况下,单方面存在是可能的,给定一个审查事件的证明。

袖珍宇宙创建

永久链接:袖珍宇宙创建

为了创建一个新的空袖珍宇宙,袖珍宇宙协调器首先在 segwit v1 输出(Taproot)中创建一个新的唯一 tapscript 承诺,具有以下结构:

  • tagged_hash("TapLeaf", leaf_version || pocket_universe_marker || pocket_universe_version || pocket_universe_hash)

其中:

  • pockt_universe_marker: 是 ascii 字符串 "pocket universe" 的 sha256 哈希值。
  • pocket_universe_version: 是使用的宇宙承诺的版本。
  • pocket_universe_hash: 是袖珍宇宙的根哈希值。
    • 袖珍宇宙是一个普通的 Taproot 资产 MS-SMT,例外的是,每个资产的 prev_id 引用的先前输出点只存在于 Taproot 资产虚拟交易图中。

这用于创建一个新的空袖珍宇宙,因为 pocket_universe_hash 将仅仅是空的 MS-SMT 哈希,因为袖珍宇宙中目前没有内容。

因此,承诺到袖珍宇宙创建的输出点被称为 pocketGenesisOutpoint。然后,可以从这个输出点导出一个 NUMS 点,计算为 M = NUMS(pocketGenesisOutpoint)。可以使用传统的“哈希和递增”方法来生成 NUMS 点,或者可以使用任何其他变体。由于性能不是问题,因此在实践中可能会使用简单的方法。

####### 袖珍宇宙动态成员:Taproot 资产虚拟交易图

永久链接:袖珍宇宙动态成员:Taproot 资产虚拟交易图

在袖珍宇宙中,不是引用承诺的资产的链上位置,而是创建一个新的虚拟交易图,该图以 pocketGenesisOutpoint 为根。为了加入袖珍宇宙,必须首先【暂停】一个资产。一旦暂停,它们可以使用 pocketGenesisOutpoint 作为_新的_铸造/发行事件添加到袖珍宇宙承诺中。随后的转移将引用虚拟交易输出点(如在 VM 中计算的那样)作为先前的输入。

资产也可以由协调器_直接_铸造到袖珍宇宙中。为此,协调器创建一个普通的创世资产,但在新的袖珍宇宙叶子中使用正常的【全零】的 prev ID。

####### 加入袖珍宇宙

永久链接:加入袖珍宇宙

为了加入袖珍宇宙,持有资产 A 的一方执行以下步骤:

  • 在同一个交易中,发送到袖珍宇宙 NUMS 密钥
  • 在袖珍宇宙中为该输出创建一个新条目
  • 在新的叶子中,引用袖珍宇宙输出点

资产可以被移动到一个袖珍宇宙,袖珍宇宙是主 Tapscript 树中的另一个承诺,方法是【发送】输出点集合到一个特殊的 NUMS 资产密钥,该密钥从给定资产的 genesisOutpoint 派生而来。

一旦资产从基础宇宙的角度【进入】,一个新的并行袖珍宇宙承诺就可以被创建,它将上面转移交易创建的_新_输出点作为第一个花费输入。从这里,可以创建新的转移,重新冻结【创建的虚拟 Taproot 资产 VM 验证交易的输出点】。结果是有效地【冻结】了锚定在主链中的资产,这允许它们在维护的袖珍宇宙中被批量处理和转移。

####### 袖珍宇宙交易

永久链接:袖珍宇宙交易

####### =离开袖珍宇宙=

永久链接:=离开袖珍宇宙=

资产宇宙 API & 联邦式同步

永久链接:资产宇宙 API & 联邦式同步

一个宇宙服务器使用标准的宇宙 API 与客户端和其他宇宙服务器通信。由于宇宙是一个基于树的结构,它非常适合于基于二分法的协调协议。一组宇宙服务器可以相互对等,以形成一个宇宙联盟。用户向联盟的一个子集提交发行和转移证明,渐进的基于树的协调将最终同步跨联邦宇宙服务器集合的新状态。

宇宙 gRPC API

永久链接:宇宙 gRPC API

宇宙 gRPC API 由以下标准 gRPC 服务实现:

service Universe {
    /*
    AssetRoots 查询与每个已知资产相关联的已知宇宙根。
    这些根代表每个已知资产的供应/审计状态。
    */
    rpc AssetRoots (AssetRootRequest) returns (AssetRootResponse);

    /*
    QueryAssetRoots 尝试定位特定资产的当前宇宙根。
    该资产可以通过其资产 ID 或组密钥来标识。
    */
    rpc QueryAssetRoots (AssetRootQuery) returns (QueryRootResponse);

    /*
    AssetLeafKeys 查询与给定 asset_id 或 group_key 相关联的宇宙密钥集合。
    每个密钥采用以下形式:(outpoint, script_key),其中 outpoint 是比特币区块链中的一个输出点,它锚定了一个有效的 Taproot 资产承诺,而 script_key 是给定 asset_id 或 group_key 的 Taproot 资产承诺中的资产的脚本密钥。
    */
    rpc AssetLeafKeys (ID) returns (AssetLeafKeyResponse);

    /*
    AssetLeaves 查询给定 asset_id 或 group_key 的资产叶子(宇宙 MS-SMT 树中的值)集合。
    这些代表资产发行事件(它们具有创世见证)或链上发生的资产转移。
    这些叶子包含一个普通的 Taproot 资产证明,以及资产的详细信息。
    */
    rpc AssetLeaves (ID) returns (AssetLeafResponse);

/ QueryProof 尝试基于给定的资产的 UniverseKey 查询该资产的发行证明。 UniverseKey 由 Universe ID (asset_id/group_key) 和叶子 key (outpoint || script_key) 组成。 如果找到,则返回发行证明,其中包括到已知 Universe 根的包含证明, 以及所述资产的 Taproot Asset 状态转换或发行证明。 / rpc QueryProof (UniverseKey) returns (AssetProofResponse);

/*
InsertProof 尝试将新的发行证明插入到 UniverseKey 指定的 Universe 树中。
如果有效,则将证明插入到数据库中,并为更新后的 asset_id/group_key 返回新的 Universe 根。
*/
rpc InsertProof (AssetProof) returns (AssetProofResponse);

}


该服务允许用户获取完整的资产根集,获取给定资产的 Universe 根,
获取叶子/key集,并尝试向目标 Universe 服务器添加新的发行/转移证明。

以下是每个 proto 消息的定义:

message AssetRootRequest {}

message MerkleSumNode { // 分支节点的 MS-SMT 根哈希。 bytes root_hash = 1;

// 分支节点的根和。该值与左右 sibling一起哈希以创建根哈希。
// 该值表示资产的总已知供应量。
int64 root_sum = 2;

}

message ID { oneof id { // 32 字节的资产 ID。 bytes asset_id = 1;

    // 编码为十六进制字符串的 32 字节资产 ID。
    string asset_id_str = 2;

    // 32 字节的资产组 key。
    bytes group_key = 3;

    // 编码为十六进制字符串的 32 字节资产组 key。
    string group_key_str = 4;
}

}

message UniverseRoot { ID id = 1;

// 与上述 universe ID 关联的 merkle sum sparse merkle tree 根。
MerkleSumNode mssmt_root = 3;

}

message AssetRootResponse { // 每个资产的已知 universe 根集的映射。 // 映射中的 key 是 32 字节的 asset_id 或组 key 哈希。 map<string, UniverseRoot> universe_roots = 1; }

message AssetRootQuery { // 用于唯一标识 Universe 根的 ID 值。 ID id = 1; }

message QueryRootResponse { // 给定资产 ID 或组 key 的资产根。 UniverseRoot asset_root = 1; }

message Outpoint { // 作为十六进制编码(和反转!)字符串的输出。 string hash_str = 1;

// 输出的索引。
int32 index = 2;

}

message AssetKey { // 资产 key 的 outpoint,可以是单个十六进制编码字符串,也可以是展开的 outpoint。 oneof outpoint { string op_str = 1;

    Outpoint op = 2;
}

// 资产的 script key。
oneof script_key {
    bytes script_key_bytes = 3;

    string script_key_str = 4;
}

}

message AssetLeafKeyResponse { // 给定资产 ID 或组 key 的资产叶子 key 集。 repeated AssetKey asset_keys = 1; }

message AssetLeaf { // 叶子中包含的资产。 taprpc.Asset asset = 1;

// TODO(roasbeef): 仅用于显示?可以从下面的证明中获得 ^

// 资产发行证明,证明上面指定的资产已正确发行。
bytes issuance_proof = 2;

}

message AssetLeafResponse { // 给定资产 ID 或组 key 的资产叶子集。 repeated AssetLeaf leaves = 1; }

message UniverseKey { // 要查询的资产的 ID。 ID id = 1;

// 要查询的资产 key。
AssetKey leaf_key = 2;

}

message AssetProofResponse { // 发行证明的原始请求。 UniverseKey req = 1;

// 包含此资产叶的 Universe 根。
UniverseRoot universe_root = 2;

// 下面包含的资产叶的包含证明。该值是发行证明本身,和值为资产的数量。
bytes universe_inclusion_proof = 3;

// 资产叶本身,包括资产和发行证明。
AssetLeaf asset_leaf = 4;

}

message AssetProof { // 要插入证明的资产的 ID。 UniverseKey key = 1;

// 要插入到 Universe 树中的资产叶。
AssetLeaf asset_leaf = 4;

}

enum UniverseSyncMode { // 一个同步节点,指示仅应同步新的资产创建(铸造)证明。 SYNC_ISSUANCE_ONLY = 0;

// 一种同步模式,指示应同步所有资产证明。
// 这也包括常规转移。
SYNC_FULL = 1;

}

message SyncTarget { ID id = 1; }

message SyncRequest { string universe_host = 1;

// 同步模式。这决定了要同步的证明类型。
UniverseSyncMode sync_mode = 2;

// 要同步的资产集。如果未指定,则同步所有资产。
repeated SyncTarget sync_targets = 3;

}

message SyncedUniverse { // 已同步资产的旧 Universe 根。 UniverseRoot old_asset_root = 1;

// 已同步资产的新 Universe 根。
UniverseRoot new_asset_root = 2;

// 已同步的新资产叶集。
repeated AssetLeaf new_asset_leaves = 3;

}

message SyncResponse { // 已同步的资产 Universe 集。 repeated SyncedUniverse synced_universes = 1; }


###### Universe REST API

[Permalink: Universe REST API](https://github.com/Roasbeef/bips/blob/bip-tap/bip-tap-universe.mediawiki#universe-rest-api)

除了 gRPC API 之外,Universe 服务器还遵守匹配的 REST API。
REST API 是 gRPC API 的镜像,其结构旨在支持以类似于在区块浏览器中的方式来熟悉地访问 Universe 信息。

以下 yaml 描述了 Universe 服务器的 REST 接口:

type: google.api.Service config_version: 3

http: rules:

  • selector: universerpc.Universe.AssetRoots get: "/v1/taproot-assets/universe/roots"

  • selector: universerpc.Universe.QueryAssetRoots get: "/v1/taproot-assets/universe/roots/asset-id/{id.asset_id_str}"

  • selector: universerpc.Universe.QueryAssetRoots get: "/v1/taproot-assets/universe/roots/group-key/{id.group_key_str}"

  • selector: universerpc.Universe.AssetLeafKeys get: "/v1/taproot-assets/universe/keys/asset-id/{asset_id_str}"

  • selector: universerpc.Universe.AssetLeafKeys get: "/v1/taproot-assets/universe/keys/group-key/{group_key_str}"

  • selector: universerpc.Universe.AssetLeaves get: "/v1/taproot-assets/universe/leaves/asset-id/{asset_id_str}"

  • selector: universerpc.Universe.AssetLeaves get: "/v1/taproot-assets/universe/leaves/group-key/{group_key_str}"

  • selector: universerpc.Universe.QueryProof get: "/v1/taproot-assets/universe/proofs/asset-id/{id.asset_id_str}/{leaf_key.op.hash_str}/{leaf_key.op.index}/{leaf_key.script_key_str}"

  • selector: universerpc.Universe.QueryProof get: "/v1/taproot-assets/universe/proofs/group-key/{id.group_key_str}/{leaf_key.op.hash_str}/{leaf_key.op.index}/{leaf_key.script_key_str}"

  • selector: universerpc.Universe.InsertProof post: "/v1/taproot-assets/universe/proofs/asset-id/{key.id.asset_id_str}/{key.leaf_key.op.hash_str}/{key.leaf_key.op.index}/{key.leaf_key.script_key_str}" body: "*"

  • selector: universerpc.Universe.InsertProof post: "/v1/taproot-assets/universe/proofs/group-key/{key.id.group_key_str}/{key.leaf_key.op.hash_str}/{key.leaf_key.op.index}/{key.leaf_key.script_key_str}" body: "*"

  • selector: universerpc.Universe.SyncUniverse post: "/v1/taproot-assets/universe/sync" body: "*"

例如,为了查询位于 outpoint `txid:vout` 的,资产 ID 为 `x` 的任何已发行资产,用户可以访问以下端点: `/v1/taproot-assets/universe/keys/asset-id/x/txid/vout `

Simple Universe Sync

Permalink: Simple Universe Sync

如上所述,Universe 服务器的基于树的结构很容易进行基于对分法的集合协调。 在这种情况下,key 构成要同步的集合。

在本节中,我们将描述一个简单的线性算法,用于将本地 Universe 与远程 Universe 服务器同步:

sync_with_universe(local_universe: UniverseServer, remote_universe: UniverseServer) -> None
    // 首先从本地 + 远程服务器获取根集。
    local_roots = local_universe.asset_roots()
    remote_roots = remote_universe.asset_roots()

    // 如果本地根与远程根匹配,则完成。
    if local_roots == remote_roots:
       return

    // 否则,对于每个根,我们将找出我们缺少哪些叶子。
    for i, remote_root in range(remote_roots):
        if remote_roots == local_roots[i]:
            continue

        remote_asset_keys = remote_universe.asset_leaf_keys(remote_root.id)
        local_asset_keys = local_universe.asset_leaf_keys(local_root.id)

        missing_keys = set(remote_asset_keys) - set(local_asset_keys)

        for missing_key in range missing_keys:
            missing_leaf = remote_universe.query_issuance_proofs(missing_key)

            local_universe.insert_issuance_proof(missing_leaf)

通过首先递归获取不匹配的 sibling,直到达到可接受的深度,然后再获取终端子树中的所有叶子,可以增强简单的同步。 每个步骤都有助于将需要发送以协调状态的 key 总数减半。

Test Vectors

Permalink: Test Vectors

TBD

Backwards Compatibility

Permalink: Backwards Compatibility

Reference Implementation

Permalink: Reference Implementation

github.com/lightninglabs/taproot-assets/universe

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

0 条评论

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