BUPT3分享13—Taproot 和 BRC-20 拆解

Hacker Dōjo Workshop
资助金额:100 USDT
分享者:北邮在读硕士 Syshems
本项目由Hacker Dōjo资助,文章转载请联系
Telegram: @DoraDojo0
WeChat: @HackerDojo0

Taproot 是自 SegWit 以来最重要的比特币升级,Taproot 通过用 Schnorr 取代目前的 ECDSA 算法,将众多签名批量化为一个签名,使区块链上的数据存储更有效率。BRC-20 其实是利用了 Taproot 升级后的「善意bug」,基于链下客户端对链上数据进行解读。本研究旨在揭示 Taproot 升级细节,以及升级前后给比特币生态带来的优缺点,从技术角度去解读(曾经)火热的 BRC-20 。

一、Taproot 升级细节

1、什么是 Taproot?

Taproot 由 Bitcoin Core 贡献者 Gregory Maxwell 于 2018 年首次提出。Taproot 可以让复杂交易(多签、时间锁)像单个比特币交易那样执行。Taproot 升级包括三个重要的技术变化(概念),用来增强比特币的可扩展性、隐私性和灵活性。

  • P2SH
  • MAST
  • Schnorr 签名

我们将从技术层面讨论这三个概念,从而了解 Taproot 升级会给比特币用户带来哪些好处。

2、P2SH

比特币地址是一个包含字母和数字的字符串,用户可以将其分享给其他人,以便从后者那里接收 BTC。比特币交易主要有两大标准:Pay-to-PubKeyHash (P2PKH) 和 Pay-to-ScriptHash (P2SH)。

2.1 基础知识

在讨论 P2SH (Pay To Script Hash) 和 P2PKH (Pay-To-PubKey Hash) 这两个概念之前,我们首先熟悉一下关于比特币的背景知识:

  • 在比特币网络中,比特币的形式是 UTXO,即比特币交易执行后形成的面额不定的单元。例如,你的比特币钱包里有 10 BTC,你想要转 5 BTC 给朋友。比特币区块链会把 10 BTC(全部余额)都花掉,将 5 BTC 转入你朋友的钱包,剩下 5 BTC(10 BTC - 5 BTC = 5 BTC)转入你自己的钱包。这下,你和你的朋友各持有未花费的 5 BTC。
  • 比特币使用**脚本(几行代码)**来规定花费 BTC/UTXO 的条件,脚本被用作一种锁定机制。
  • BTC 锁定在脚本中,当脚本返回成功(即条件得到满足)时,BTC 就会解锁。
  • 任何人都可以向任意比特币地址发送 BTC。只有当脚本中定义的某些条件得到满足时,锁定的 BTC 才可以被花费出去。脚本决定了接收方可以如何花费收到的 BTC。发起交易时,发送方会在交易中放入一个叫作 “PubKey Script(又称锁定脚本)”的脚本。接收方(在日后花费时)需要生成一个 “scriptSig(又称解锁脚本)” ,是满足 PubKey 脚本的数据参数的集合。

2.2 P2PKH(Pay-to-PubKeyHash)

Pay-to-PubKeyHash 是一种传统的比特币地址格式。其地址以数字 1 开头。只有 P2PKH 地址的所有者才能通过提供公钥哈希值和私钥签名来解锁 PubKey 脚本并花费收到的 BTC。私钥是用来证明公钥哈希值的所有权的。

2.2.1 验证流程是如何运作的?

接收方首先生成 PubKey 脚本并将其分享给发送方。发送方在发送 BTC 时将该 PubKey 脚本 添加到交易中。收到 BTC 时,如果接收方想要解锁这些 BTC UTXO,就要提供公钥哈希和私钥签名,并满足 PubKey 脚本中提到的条件。解锁的条件可以是:

  • 解锁 BTC 至少需要两个签名。
  • 提供口令(password)才能解锁。
  • BTC 需要等待一段时间才能解锁。

2.2.2 P2PKH 存在的缺陷

  • 发送比特币时,发送方需要在交易中包含「PubKey 脚本」,这会增加交易的体积,产生的交易费比普通交易高出 5 倍左右。
  • 发送方必须承担额外的成本。

2.3 Pay-to-ScriptHash (P2SH)

在 P2SH 交易标准下,发送方不需要将很长的 PubKey 脚本放到他们的交易中,而是被替换为了「赎回脚本哈希值」。可以帮助发送方免去额外的成本,并将这一责任(额外成本)转移到真正需要使用锁定脚本中规定条件的接收方身上。

  • Pay-to-ScriptHash 比特币地址是以数字 3 开头的。
  • 赎回脚本(redeem script)哈希值由赎回脚本计算而来。赎回脚本与 PubKey 脚本类似,包含接收方在花费 UTXO 之前必须满足的条件。发送方只需在交易中注明赎回脚本的哈希值,赎回脚本哈希可以翻译成标准比特币地址,发送方无需进行任何特殊操作或支付额外费用即可将 BTC 发送到这些地址。
  • 接收方想要解锁这个 P2SH 地址上的 BTC 时,需要生成具有相同哈希值的赎回脚本并将其包含到交易内。因此,接收方用来解锁 UTXO 的交易大小会增加,执行交易的成本也会增加。

例如,Alice 想要发送 10 BTC 给 Bob。Alice 必须将「赎回脚本哈希」包含到交易内。

  • 首先,Bob 先生成一个赎回脚本,然后将赎回脚本的哈希值发送给 Alice。
  • 然后,Alice 将该哈希添加到交易内并发起交易。
  • 如果 Bob 想要花费该 UTXO,必须生成相同哈希值的解锁脚本,并满足脚本中提到的条件。

2.4 Pay-to-ScriptHash 的优势

  • 降低 sender 的交易负担:使用哈希值取代冗长的脚本,减少数据量。
  • 更好的隐私性:发送方可以在不知道脚本中规定的花费条件的情况下,在交易中放入任意数量的赎回脚本哈希值。

3、MAST(默克尔抽象语法树)

MAST 是 Merklized Abstract Syntax Tree(默克尔抽象语法树)的缩写,MAST 是「默克尔树」和「抽象语法树」的结合体。正如 Pay To ScriptHash (P2SH) 是给哈希值为某某的脚本付款那样,MAST 是给哈希值为某某的默克尔根付款。MAST 是把一个大的条件集合中的各个条件组装成一棵哈希树(所谓的默克尔树),而默克尔树的根值是一个哈希值,由所有条件哈希而成。

3.1 为什么要使用 MAST?

如果你想花费 P2SH 地址里的 BTC,你必须生成具有相同哈希值的赎回脚本并将其包含到交易中。如果脚本中规定的花费条件太多,交易体积会变得格外庞大。MAST 可以很好的解决这一问题。

3.2 默克尔根和哈希树是如何生成的?

首先分别对所有脚本(条件)做哈希计算;然后将计算得到的哈希值与相邻哈希值组合起来进行哈希计算,生成一组新的哈希值。不断重复这个两两哈希计算的过程,直到计算出最后一个哈希值为止。这个哈希值就是默克尔根。

例如:假设共有四组条件。首先,分别计算出这四组条件的哈希值;再将这四个哈希值两两配对,计算出两个哈希值;最后,把这两个哈希值组合起来做哈希计算,生成最终的哈希值。最后这个哈希值就是默克尔根。

这个默克尔根可以翻译成一个能够接收付款的有效比特币地址,即,默克尔比特币地址(Merklized Bitcoin address)。默克尔比特币地址有很多优点,最主要的优点是无需知晓所有脚本单元就能验证某个脚本是否位于这棵默克尔树上。这个技术叫作默克尔证明(Merkle Proof),可以用来轻松验证一个比特币 UTXO 是否包含某些解锁条件。

在 MAST 中,BTC 与一棵默克尔树绑定。这棵默克尔树指定了可以解锁未花费 BTC 的所有复杂条件。每个叶节点都代表着一个条件。为了解锁 BTC,你必须生成一个满足默克尔树上某个分支所代表的条件的脚本。仅使用默克尔根即可验证这个条件是否属于原始条件集合(即验证某个叶节点是否在这棵默克尔树上)。一旦比特币区块链网络发现某个脚本(及其所代表的条件)属于这个默克尔根,网络就会知道这个脚本是这些比特币的锁定条件并开始验证解锁脚本。因此,我们无需生成完整的脚本并将其包含到交易内,即可花费以 MAST 锁定的 BTC。这有助于减少 BTC 交易的体积。

3.3 MAST 的优势

MAST 在 P2SH 的基础上迈出了一大步,其提升效果首先体现在隐私性上:原本在 P2SH 中,合约在使用时就一定要公开全部的脚本内容,不论那些内容用到没用到,都必须公开;现在,有了 MAST,用户就只需要公开需要用到的解锁条件,无需公开全部内容了;同时,别人也根本不知道你还有多少个条件。

其次,它还在效率上有所提升:用户只需提供需要用到的部分脚本,及其默克尔证据,在整个脚本比较庞大时,这种体积节约的效果会非常明显。

由此,未来的比特币用户可以编写条件非常多的合约,获得更好的控制效果而只需支付更少的手续费;甚至,可以有意包含一些垃圾条件来充实默克尔树,获得隐私提升的效果。

4、Schnorr 签名

在密码学中,Schnorr 签名是由 Claus Schnorr 提出的由 Schnorr 签名算法生成的数字签名。 Schnorr 签名算法是一种以简单闻名的数字签名方案,通过将多个签名聚合成单个签名以优化验证和认证过程,该方案适用于多签交易。

4.1 为什么使用 Schnorr 签名

若想执行多签交易,你必须提供多个签名。这些签名会占据额外的空间。以 12/20 多签交易为例:签署交易时,签名会存储在区块内。假设 1 个签名的大小是 5 字节,12 个签名需要占用区块 60 字节的内存,100 个签名需要占用 500 字节的内存。这会增加内存用量。

Schnorr 签名恰好可以解决这一问题。假设你需要 100 个签名且每个签名的大小是 5 字节,Schnorr 签名方案可以将这 100 个签名合并成一个大小为 64 字节的 Schnorr 签名。省下 436 字节(5*100-64=436)的内存可以用来存储更多交易。(注:现在的椭圆曲线签名可不止 5 字节)

4.2 Schnorr 签名的优势

  • 有了 Schnorr 签名,其他人就无法分辨一个签名到底是单人签出的,还是多人共同签出的了;
  • 多签名的解锁条件,可以用一个聚合公钥来替代。
  • 所有 n-n 的多签名合约,都可以享受到 Schnorr 签名提供的隐私保护。其最显然的应用就是闪电网络通道,因为闪电网络通道是一个 2-2 的多签名合约;此后,其他人就无法凭借签名的数量来分辨支付通道和个人用户了。
  • 至于 m-n 的多签名合约,也不用担心,别忘了我们有 MAST:我们可以把所有可能解锁的情形都化成一个分支,在使用某个分支时,所提供的签名也只需是聚合签名。例如,假设我们要做一个 2-3 的多签名合约,在公钥 A、B、C 中三取其二,这个多签名合约效果等同于 “要么(A、B)解锁、要么(B、C)解锁、要么(A、C)解锁”,这可以理解为一个多条件的脚本,每个条件都是一个 2-2 多签名,因此也都可以用相应的聚合公钥来定义解锁条件(而无需以多签名来定义)。所以,当我们需要以某种组合解锁资金时,只需用 MAST 暴露一个分支、提供一个签名,他人依然不知道这到底是一个人,还是两个人,还是多个人。

二、升级后能做什么

1、比特币智能合约

许多人不了解的是,比特币也支持编程智能合约,只不过其智能合约的类型与其他区块链(比如以太坊)的不同。

  • 多签名合约。比特币支持多签名授权使用资金:在 N 个记录好的公钥中,必须有 M 个公钥所对应的私钥(对同一个操作的)签名,该笔资金才可动用。比特币支持最多 15 个公钥的多签名合约。
  • 时间锁。用户可以使用两种类型的时间锁来规定一笔资金的可用时段: (1) CLTV,绝对时间锁,以具体的时间或具体的区块高度来定义,过了这个时间才可动用; (2) CSV,相对时间锁,比如生成该项资金的交易上链的 1000 个区块后,该笔资金才可动用。
  • 多条件编程。即在脚本中使用 “IF … ELSE …” 式的语句,为同一笔资金设定多个解锁条件,任一条件满足即可使用该资金。比如:“A 公钥所对应的私钥可解锁,或者,在区块高度 XXXX 以后,B 公钥所对应的私钥可以解锁,或者,在该交易上链的 YYYY 个区块以后,A、B、C 三个公钥中任意两个所对应的私钥可以解锁”

这几个模块看起来非常简单,组合起来可能性却非常多:多签名合约定义了不同主体的权限,可以适应极为丰富的应用场景,从公司运营,到家庭金库;时间锁则规定了不同主体在不同时段的权限。而多条件则显著放大了这些权限控制的组合效果。你甚至仅凭几个条件,就可以做出一个支持社交恢复、带遗产分配效果的合约。

但是,这些合约要实际上派上用场,两个因素就不能忽视:效率性和隐私性。

  • 在 SegWit 升级以前,单签名的个人钱包与合约钱包是泾渭分明的,前者是 P2PKH 地址,后者是 P2SH 地址,仅从地址上就可以看出来,这又是一个对隐私不利的因素。在 SegWit 升级之后,支持隔离见证的个人钱包也可采取 P2SH 的形式,但原生隔离见证地址(P2WPKH)和合约地址(P2WSH)仍然是泾渭分明的。
  • Taproot 升级后,Schnorr 签名 和 MAST 可以完美解决隐私性和效率性的问题。以一个基础合约为例,Alice 将她的比特币锁定到这个合约内,达到某个区块高度(这时,她的孩子 Bob 已经长大成人)后才能解锁,或是等到 Bob 有能力签署多签交易时就可以解锁。在当前框架下,一旦使用,这两个条件都会向整个网络公开,并写入不可更改的账本中。但是,Taproot 激活后,只有被执行的那个条件才会被公开。这是一种效率升级,不仅节省了宝贵的区块空间,也大幅提高了隐私性,让用户可以充分发挥创造性来保护自己的资产。

2、闪电网络的隐私性

闪电网络作为 2-2 的多签名合约,可以享受到 Schnorr 签名提供的隐私保护,其他人无法凭借签名的数量来分辨支付通道和个人用户了。

3、Taproot 提高侧链的隐私性

与闪电网络通道的开启交易一样,侧链的挂钩交易也依赖于多签合约来完成。RSK(移植以太坊智能合约的比特币侧链 Rootstock)采用了双向挂钩(2WP)来确保比特币转账的安全性。但是,在 Taproot 激活后,该交易变得无法与其它交易区分,占用的区块空间也更少了。

Blockstream 开发的侧链 Liquid 以及 Drivechain 同样如此。常规交易、Liquid 的挂钩交易、闪电网络通道和用户多签从外部看起来都一样。

4、Taproot 提升硬件钱包的体验

对于硬件钱包来说,Taproot 有希望带来更高的效率,体现在发送交易所需的时间上;前序交易的输入输出的平均数量越多,时间上的节省越多。这是因为有了 Taproot 之后,钱包无需花费之前发送(通常体量很大)的交易历史。

对于一笔只有一个输入和两个输出的交易,使用 Taproot 可以节约大概 50% 的时间(相比于 SegWit v0 交易)。这个数字看起来很棒,但在实际使用中用户不会有什么感觉。但随着输入的数量增加,节省的时间也随之增加:如果有 100 个输入(但仍是 2 个输出)那么发送交易的时间可以节约 90%。对于更复杂的,带有大量输入和输出所组成的历史的交易,比如 CoinJoined(混币)交易,节省更为巨大。假设一次混币有 100 位参与者,使用 Taproot 的签名时间可以比当前的 SegWit 交易快上几十倍。Trezor 已计划在今年底引入 CoinJoin 功能,Taproot 将使这些隐私交易用起来更快更简单。

三、拆解 BRC-20

1、ordinals 协议

Casey Rodarmor 的 ordinals 协议使用了通过生命历程来跟踪单个聪的身份的技术。简单来说,新挖出的聪因为其挖出的顺序而被赋予连续的编号。这些编号叫做 “序号”,简称 “ordinals”。当聪在交易中花费的时候,输入中的聪的序号会按照简单的 “先进先出” 算法分配到输出中。当这种身份与关联一些数据或者说权利的标准相结合之后,就可以用来创建非同质代币(或者说准同质的代币),这些代币的所有权可以通过比特币交易来转移。

这项技术已经作为一项 BIP 提出:https://github.com/bitcoin/bips/pull/1408,只是上述 BIP 提议并没有描述任何为一个 ordinals 附加数据或权利的方法。 “ord” 工具定义了 “ 铭刻 inscriptions ”填补了这个空白:它提供了一种在 taproot 输入的 witness 字段包含编码哑剧(mime)的数据的方法。为了制作这样的铭文,需要发起两笔交易:一笔交易将一些聪发送到一个承诺了铭文数据的特殊脚本公钥中,另一笔交易花费这些聪,使之转移给新铭刻的 ordinals 的主人;这样做就会公开完整的铭文。

2、对比特币的影响

我理解比特币和 brc20 的关系,就像是星星和星座的关系。星星是一直存在的,但是星座是人们去解释星星的一种共识。星星本身是不知道星座存在的,同样,比特币系统是不知道 brc20 存在的,比特币的共识也是不管的。所以,brc20 其实就是在这个比特币上写了一些东西,然后自己去解释这些数据的这套规则和标准。当然,只有符合这个标准的客户端按照这个方式去解释,才能看到对应的 NFT 或是 FT。

对 brc20 的共识其实是对客户端的共识,而跟比特币的共识没有关系。社区内观点也是比较分化:

  • 正向可能:Ordinals 拓展了 BTC 网络的应用场景 → 矿工更赚钱 → 更多的全节点 → BTC网络更健壮
  • 负向可能:Ordinals 滥用 Taproot 协议 → 阻塞 BTC网络 → 影响 BTC 的转账甚至出块 —> Ordinals 劣币驱逐良币

参考

Taproot 技术:比特币升级提案 Taproot 技术解读

Taproot 应用:Taproot 如何提高比特币隐私性

Taproot 详解:Taproot 升级详解

Schnorr 签名:什么是 Schnorr 签名? | 登链社区 | 区块链技术社区

Taproot 支付池:基于 Taproot,支付池可能成为比特币下一代的二层协议

Ordinals :纯粹的链下 “染色” 方案