Brc20
协议由 domo 基于 Ordinals
协议提出的, 用于在比特币网络上发行代币。其龙头代币 ORDI 市值一度接近20亿美金。本节将详细介绍 Brc20
协议的技术实现细节。
Brc20
数据存储基于 Taproot
, 数据存储在脚本树的节点中。开始之前请确保已学习 P2TR 部分的内容。
由随机生成内部私钥, 计算出公钥的 坐标作为内部公钥。结合脚本树的 值, 计算出 Taproot
输出公钥 。bech32m
编码后得到 Taproot
地址。
Brc20
交易首先会向该地址转账, 并输出一个 UTXO
, 其锁定脚本为 OP_1 <Taproot 输出公钥>
, 类型为 P2TR
。但是, 该转账交易中并没有包含任何 Brc20
的数据。而要使 Brc20
数据显式包含在交易中, 必须要同时花费该 UTXO
。并且花费路径只能选择脚本路径, 因为脚本路径花费时需要提供要花费脚本的完整数据, 如此便实现数据链上存储。
故 Brc20
交易都需要同时包含两笔交易:
- 第一笔交易称作
commit
交易, 用于向生成的Taproot
地址转账 - 第二笔交易称作
reveal
交易, 用于花费commit
交易生成的UTXO
向生成的 Taproot
地址转账时, 需要转账足够的聪。避免花费时因为交易费不足导致的交易无法确认。
Taproot 地址计算
在向 Taproot
地址转账时先计算出要转账的地址。
计算 Commit 地址
随机生成的内部秘钥用于生成临时的 Taproot
地址。为了安全性, 每次 Brc20
交易通常需要生成一个新的 Taproot
地址。
脚本树中定义的锁定脚本只有一个, 内容部分如下所示:
-
OP_FALSE
: 等同于OP_0
, 作用是将数字 0 推入栈中 -
OP_IF
: 条件块开始, 从栈顶弹出一个元素, 如果为真(非0)则执行条件块内的脚本, 否则跳过。由于栈顶元素是0, 所以条件块内的脚本永远不会被执行。脱离Brc20
背景, 条件块内的脚本实际是一段冗余数据, 这也是Brc20
经常被诟病的原因。 -
text/plain;charset=utf-8
: 表示数据的 MIME 类型, 如果是图片数据, 则可以是image/png
-
{"p":"brc-20","op":"mint","tick":"sats","amt":"10"}
: 表示具体的数据内容, 对于Brc20
代币数据, 各个字段分别表示:p
: 表示协议,brc-20
表示Brc20
协议op
: 表示操作,mint
表示铸币,deploy
表示部署,transfer
表示转账tick
: 表示代币名称amt
: 表示数量
在内容部分之上的部分实际是一个 P2PK 锁定脚本
不同的是公钥部分用的是 坐标。一般来说, 椭圆曲线中相同的 坐标会有两个 坐标, 但在 BIP340 Schnorr
签名时总会选择 坐标为偶数的那个, 所以只需要提供 坐标即可。签名交易时, 则使用存储的公钥配对的私钥进行签名。
因此, 花费脚本中的 InternalPubKeyX
并不一定需要是生成 Taproot
地址时使用的内部公钥。但为了方便, 通常会使用相同的公钥。
Commit 交易
生成 Taproot
地址后, 需要向该地址转账。即花费自己的 UTXO
向生成的 Taproot
地址转账, 转账交易输出一个 P2TR
类型的 UTXO
到 Taproot
地址。
一个 P2TR
类型的 UTXO
包含的字段有
三个字段中唯一没有确定的是转账金额, 转账金额需要根据当前比特币网络的费率以及花费该 UTXO
所在交易(Reveal
交易)的字节大小确定。
Reveal
交易的输入只有该 P2TR
类型的 UTXO
, 并且提供的解锁脚本在 witness
字段中, 以及输出一个包含546聪的新 UTXO
给 Brc20
数据的所有者。
Reveal
交易动态字段 witness
包含三个部分:
witness
字段数据的大小可以预先确定, 交易输出的大小也可以预先确定, 整个 Reveal
交易的大小便可以确定。根据当前网络费率, 转账金额可以确定。
例如有如下 Reveal
交易
通过预先计算 Reveal
交易的大小为 138vB
, 假设当前网络的费率是 612.3 sat/vB
。总手续费需要 , 加上需要最低的转账金额 546 sat
。所以 Commit
交易需要给生成的 Taproot
地址转 84500 + 546 = 85046 sat
。
在 Commit
交易中如果所有输入的 UTXO
金额扣除当前交易费和转账金额 85046 sat
后的结果大于或等于 546 sat
, 还需要找零给原地址。
为什么是 546 sat ?
546 sat
在比特币交易中被称为 dust limit
, 是 UTXO
包含的的最小金额。 低于这个金额的交易, 可能会被比特币节点拒绝转发。
Reveal 交易
Reveal
交易用于花费 Commit
交易输出的 UTXO
, 输出 546 聪给 Brc20
数据的所有者。
示例交易:
commit: https://mempool.space/testnet/tx/a4813cd17b2fefd618f54af6d2849de245ced9950c1b8ee06fab628412e936d4 reveal: https://mempool.space/testnet/tx/b159d03058115115b209b4dbff51d75175225320349762011fdefda66a3cbe2d
索引器
索引器用于监听比特币网络, 并解析交易数据, 并将 Brc20
数据存储到数据库中。
索引器是完全的链下服务, 可以存在不同的实现, 无法保证数据的一致性。目前使用较多的是 libbrc20-indexer