比特币Ordinals铭文终极指南:让你的知识超越99%加密玩家
随着 Ordinals 协议诞生,比特币生态迎来新的活力与热潮。本文将深度介绍 Ordinals 协议的细节。
一、比特币背景
比特币采用了一个类似於现金的交易模型(cash system),其支付方式基於一种称为 UTXO 的模型,这与传统的基於帐户余额的模型有所不同。举例而言:在银行的帐户记帐模型流程中,当 A 向 B 转帐 100 元时,银行会记录三个步骤,这三个步骤构成了一个交易过程。第一步是从 A 的帐户中扣除 100 元,这个步骤的记录 ID 为 tid1。第二步是将 100 元存入 B 的帐户中,这个步骤的记录 ID 为 tid2。第三步是记录一笔转帐记录,该记录将 tid1 和 tid2 关联起来,表示 A 帐户减少 100 元,B 帐户增加 100 元。这样,A 和 B 之间的转帐关系就被记录下来,并且可以在未来查询与追踪。现在,我们将通过对於 UTXO 和支付模型的介绍,讲解比特币的支付方式。
UTXO
在比特币区块链中,所有的余额都是储存在一个名为 「未花费交易输出」(Unspent Transaction Output, UTXO)的列表中。每个 UTXO 都包含一定数量的比特币,以及这些比特币的所有者资讯,并标明是否可用。可以将其想像成一张署有持有人姓名的现金支票,只要持有人在上面签名,就可以将使用权转让给他人。对於特定的地址,其所有的 UTXO 金额加起来即为该地址钱包的余额。通过遍历所有的 UTXO,我们可以获取每个地址的当前余额。将所有的 UTXO 金额加总,则为当前全部流通的比特币。
在比特币的交易结构中,每笔交易都包括若干个输入和输出,其中每个输入是对一个已有的 UTXO 的引用,而每个输出则指定了新的资金接收地址及相应的金额。一旦一笔交易被发起,其输入部分所引用的 UTXO 便会被暂时锁定,以防止在交易完成前被重复使用。只有当这笔交易成功地被矿工打包到一个区块 (Block) 并获得网路确认後,相关的 UTXO 状态才会发生变化。具体来说,用於交易输入的 UTXO 将从 UTXO 列表中移除,表示它们已经被消费,而交易的输出则会生成新的 UTXO,并新增到 UTXO 列表中。可以理解为,旧的现金支票被使用後失效,产生了新的现金支票,其所有权属於新的持有人。
值得强调的是,每个 UTXO 只能在一笔交易中被使用一次。一旦它作为输入被消费,它就会永久地从 UTXO 列表中移除。同时,新生成的输出作为新的 UTXO 加入到列表中。UTXO 列表是不断变化的,随着每个新区块的建立,它会相应地进行更新。并且,通过分析区块链中的交易历史,我们能够重建在任何给定时间点的 UTXO 列表状态。
此外,一笔交易的总输入金额通常会略微超过其总输出金额。这个差额,称为交易费用 (Transaction fee) 或网路费 (Network fee),是作为激励给予负责将交易打包到区块的矿工的。网路费的大小与交易的复杂性成正比,因此,一笔包含更多输入和输出的交易通常需要支付更高的网路费。
现在,为了更加形象地理解比特币的交易结构,我们将通过一个具体的示例进行深入分析。比特币的交易结构如下,其中 vin 和 vout 这两个变数分别代表着比特币交易的 「输入」 与 「输出」。比特币的交易并不像传统的帐户余额模型记录帐户形的资料变化,而是通过输入和输出来表示。
const std::vector vin;
const std::vector vout;
const int32_t nVersion;
const uint32_t nLockTime;
我们可以在 blockchain.com 随机选一个交易记录来分析,下图展示了 Hash ID 为 0627052b6f28912f2703066a912ea577f2ce4da4caa5a5fbd8a57286c345c2f2 的交易。其包含了一个输入和两个输出。
通过使用 bitcoin-cli 的命令 getrawtransaction 和 decoderawtransaction,我们可以检视上述交易的底层结构:
在比特币网路中,交易输出包含两个重要资讯:地址(公钥hash)和 金额(以比特币为单位)。如果一个交易的输出没有在其他交易的输入中使用,那麽这个交易输出就被称为未消费交易输出(UTXO)。谁拥有 UTXO 中公钥对应的私钥,谁就有权使用(即花费)这个 UTXO。
我们观察一下上面程式码中的 「vin」 中的资讯,它表示这个交易所花费的 UTXO 来自於另外一个交易(其 id 为 7957a35fe64f80d234d76d83a2a8f1a0d8149a41d81de548f0a65a8a999f6f18 )的第 0 个输出(一个交易的输出可以有多个,索引从 0 开始编号),我们可以从历史交易中查找出这个 UTXO 的金额(比如为 0.1),所以这个交易中这个使用者花费了 0.1 BTC,数值 0.1 不需要显式地写在 交易中,而是通过查询 UTXO 资讯来得到的。这个交易的 「vout」 有两个输出,这两个输出为两个新的 UTXO,对应了新的余额以及持有人,直到有另外的交易把它们作为输入消费掉。
支付模型
为了更好地理解比特币网路的支付模型,我们通过一个例子介绍由 A 支付给 B 金额为 n 的比特币的支付流程。下图展示了使用者 A 传送 3 个比特币给使用者 B 的过程。
- 对於使用者 A,首先需要确定其拥有的所有 UTXO 集合,即使用者 A 可以支配的所有比特币;
- A 从这个集合中选取一个或者多个 UTXO 作为交易的输入,这些输入的金额之和为 m (2+0.8+0.5=3.3 BTC) 要大於需要支付的金额 n (3 BTC);
- 使用者 A 为交易设定两个输出,一个输出支付给 B 的地址,金额是 n (3 BTC),另一个输出支付给 A 自己的一个 找零地址 ,金额为 m-n-fee (3.3-3-0.001=0.299 BTC)。使用者的钱包通常由多个地址组成,一般情况下每个地址只使用一次,找零预设返回给一个新的地址;
- 等矿工将这笔交易打包上链进行确认後,B 就可以收到这笔交易资讯。因为区块的大小有上限(约 1 MB),所以矿工会优先确认交易费率 (fee_rate=fee/size) 高的交易,以获取最高的手续费回报。我们可以在 mempool 看到即时的挖矿 transaction fee 的情况。如果我们在转帐过程中如果想要最快进行确认,就可以选择高优先权 (High Priority) 或者自定义 (custom) 一个合适的交易费率;
二、聪的编号与追踪
比特币总量是 2100 万个,每个比特币包含 10^8 个聪 (Satoshi, Sat)。因此,比特币网路上一共有 2100 万 * 10^8 个聪。Ordinals 协议将这些聪区分出来,为每个聪进行唯一编号。本节将介绍这个协议是如何做到为每一个聪进行唯一编号,并且如何追踪其所在的帐户。此外,还会简介对於聪的稀有度份分类。
聪的编号
根据 Ordinals 协议,聪的编号是根据它们被开采的顺序而定。下图展示了第 0 个区块挖出的第 0 个聪的表示方式。
对於聪的表达方式有多种:
- 整数符号 :例如 2099994106992659,表示该聪按照挖掘顺序所分配的序号。
- 十进位制符号 :例如 3891094.16797,第一个数位表示挖掘该聪的区块高度,第二个数位表示聪在区块中的编号。
- 度数符号 :例如 3°111094′214″16797‴,第一个数位是周期,从 0 开始编号,第二个数位是减半纪元的区块索引,第三个数位是难度调整期间的区块索引,最後一个数位是区块中 sat 的索引。
- 百分比符号 :例如 99.99971949060254%,表示该聪在比特币供应量中的位置,以百分比表示。
- 名称 :例如 Satoshi。使用字元 a 到 z 对序号进行编码的名称。
我们将通过一个例子来讲解如何对新挖出的比特币进行编号。观察比特币区块链的第 795952 个区块,我们可以看到其中第一笔交易 Tx 3a1f…b177 记录了矿工的奖励(coinbase transaction)。这笔交易包含了新挖出的比特币,这些比特币是作为矿工的打包奖励,以及交易发起者付给矿工的手续费。通过检视下图的输入,我们可以发现其 UTXO 的 id 由一串 0 和区块高度组成。输出的地址则是矿工的钱包地址,金额则是上述的奖励和手续费的总和。
若我们进一步检视输出给矿工的部分,可以看到地址、金额以及所包含的聪的分布情况。如前所述,这些包含了挖矿奖励和手续费。其中,绿色的 sats 编号资讯 1941220000000000–1941220625000000 是挖矿奖励产生的新聪,其余的 712 条聪的记录则对应了该区块中的所有手续费。
我们可以验证一下 Sat 1941220000000000 这个编号。它的 block 编号为 795952,十进位制符号 (decimal) 为 795952.0,意味着挖掘该聪的区块高度为 795952,聪在此区块中的编号为 0,後面的稀有度 (rarity) 标记为 uncommon,我们将在後面的部分进行详细介绍。
聪的流转
因为每个 BTC 都是通过挖矿奖励产生的,所以他们都是可溯源的。比特币帐户使用 UTXO 模型。假设使用者 A 通过挖矿获得了第 100-110 个聪(10 个聪是一个整体存放在同一个 id 为 adc123 的 UTXO 中)。当用户 A 要支付给使用者 B 5 个聪时,他选择使用 id 为 abc123 作为交易的输入,其中 5 个聪给到使用者 B,5 个聪作为找零返回给使用者 A。这两份 5 个聪都是一个整体,分别存放在两个 id 为 abc456 和 abc789 的 UTXO 中。上述 UTXO id 和聪的数量仅作为例子展示,在实际情况下发送的聪的数量 最小限制为 546 个以及 UTXO id 也并非以此形式表达。
在上述的交易中,使用者 A 的 10 个聪的流转路径为:
- 挖矿产生 10 个聪,编号是 [100 *, 110)。* 其表示编号为第 100 到第 109 个聪存放在 id 为 abc123 的 UTXO 中,其所有者为使用者 A。
- 在 A 进行转帐时,10 个聪分成两份,每份 5 个聪。这里采用 「先进先出」 的原则,即聪的编号排序是按照它们在交易输出中的索引决定的。假设输出的顺序先是使用者 A,然後是使用者 B,那麽使用者 A 剩余 5 个聪的序号是 [100, 105),存放在 id 为 abc456 的 UTXO 中,而使用者 B 的 5 个聪的序号是 [105, 110),存放在 id 为 abc789 的 UTXO 中。
稀有度(Rare Satoshi)
作为 Ordinals 协议的衍生玩法,聪的稀有度可以根据它们的挖掘顺序来定义。这将导致一些特殊的聪具有不同的稀有度。以下是不同聪的稀有程度:
- common 普通级:除区块第一个聪外的任何聪(总供应量为 2100 兆)
- uncommon 优良级:每个区块的第一个聪(总供应量为 6929999)
- rare 稀有级:每个难度调整期的第一个聪(总供应量为 3437)
- epic 史诗级:每次减半後的第一个聪(总供应量为 32)
- legendary 传奇级:每个周期的第一个聪(总供应量为 5)
- mythic 神话级:创世区块的第一个聪(总供应量为 1)
这种稀有聪的概念可以为比特币生态增加更多的趣味性和价值。不同稀有度的聪可能在市场上具有不同的价值,吸引收藏家和投资者。
三、铭文方式
Ordinals 与其他非比特币链上的 NFT 显着不同。其中,最主要的差异在於,Ordinals 的元资料并没有储存在一个特定的位置上。相反,这些元资料被嵌入到交易的见证资料 (witness data, witness field) 中,这就是为何我们称之为 “铭文 (inscription)” 的原因,因为这些资料被像铭文一样 「刻」 在比特币交易的特定部分上,而这些资料正是附着在特定聪上的。这一铭文过程通过隔离见证 (Segregated Witness, SegWit) 和 「向 Taproot 支付」(Pay-to-Taproot, P2TR) 的方式实现,其中包含了提交(commit)和揭露(reveal)两个阶段,能够将任何形式的内容(如文字、影象或视讯)铭刻在指定的聪上。我们将在下文介绍另一种更加直接的储存方式 OP_RETURN 并阐述其为何没被作为铭文的手段。同时,我们会介绍隔离见证与 Pay-to-Taproot 是什麽,以及他们在铭文中扮演什麽角色。最後我们会介绍铭文的方式。
延伸阅读:马斯克狠酸NFT:图片没上区块链!比特币社群超译「他看好Ordinals」
OP_RETURE
在 Bitcoin Core 客户端 0.9 版中,通过采用 RETURN 操作符最终实现了妥协。**RETURN 允许开发者在交易输出上增加 80 位元组的非支付资料。** 与伪支付不同,RETURN 创造了一种明确的可验证不可消费型输出,此类资料无需储存於 UTXO 集。 RETURN 输出被记录在区块链上,它们会消耗磁碟空间,也会导致区块链规模的增加,但它们不储存在 UTXO 集中,因此也不会使得 UTXO 记忆体池膨胀,更不会增加全节点昂贵的记忆体代价。
虽然 OP_RETURN 是一个非常直接的用以储存资讯至比特币区块链的手段,它也是一个潜在的铭文方式。但是 OP_RETURN 的限制使得其在处理元资料储存时面临一些挑战。首先,OP_RETURN 只能储存 80 位元组的资料,对於需要储存更大量资料的情况来说,这种限制显然是无法满足的。其次,OP_RETURN 资料被储存在交易输出部分,虽然这种资料不储存在 UTXO 集中,但是它们占用了区块链的储存空间,导致区块链规模的增加。最後,使用 OP_RETURN 会导致交易费用的提高,因为它需要支付更多的费用来发布这些交易。
隔离见证
相比之下,SegWit 提供的新方法则可以克服上述问题。SegWit 是比特币的一个重要协议升级,由比特币核心开发者 Pieter Wuille 在 2015 年提出,最终在 2017 年的 0.16.0 版本中被正式采纳。Segregated Witness 中的 Segregated 是分离、隔离的意思,Witness 是与交易相关的签名事物。因此,SegWit 是将某些交易签名资料 (见证资料) 与交易分开。
延伸阅读:详解》比特币隔离见证 Segwit -工作原理与案例分析
将签名与交易相关资料分离的主要好处是减少了储存在一个比特币块中的资料的大小。这样每个块具有额外的容量来储存更多的交易,也意味着网路可以处理更多的交易,并且传送者支付更低的手续费。从技术上来说就是把指令码签名 (scriptSig) 资讯从基本结构 (base block) 里拿出来,放在一个新的资料结构当中。做验证工作的节点和矿工也会验证这个新的资料结构里的指令码签名,以确保交易有效。Segwit 升级在交易输出中引入了一个新的见证栏位,以确保隐私和效能。虽然见证资料不是为了资料储存而设计的,但它实际上给了我们一个储存铭文元资料等内容的机会。我们通过下图来更加形象地理解隔离见证:
Taproot
P2TR 是比特币的一种交易输出型别,它是在 2021 年进行的 Taproot 升级中引入的,它使得不同的交易条件可以更加隐私地储存在区块链中。在 Ordinals 的铭文中,P2TR 扮演着至关重要的角色。铭文字质上是将特定的资料内容嵌入到比特币交易中,而 Taproot 升级,尤其是 P2TR,使得这种嵌入资料变得更加灵活和经济。
首先,由於 Taproot 指令码的储存方式,我们可以在 Taproot 指令码路径支出指令码中储存铭文内容,这些指令码在内容方面几乎没有任何限制,同时还能获得见证资料的折扣,使得储存铭文内容相对经济。由於 Taproot 指令码的消费只能从已经存在的 Taproot 输出中进行,因此,铭文采用了两阶段的提交 / 揭示流程。首先,在提交交易中,建立了一个承诺包含铭文内容的指令码的 Taproot 输出。然後,在揭示交易中,消费了由提交交易建立的输出,从而在链上揭示了铭文内容。
这种做法大大降低了对资源的消耗。如果不使用 P2TR,见证资讯会储存在交易的输出中。这样,只要这笔输出未被消费,见证资讯就会一直储存在 UTXO 集中。相反,如果使用了 P2TR,见证资讯不会出现在提交阶段生成的交易中,因此它不会被写入 UTXO 集。只有当这笔 UTXO 被消费时,见证资讯才会在揭示阶段的交易输入中出现。P2TR 让元资料能够写入比特币区块链,但却从未出现在 UTXO 集中。由於维护 / 修改 UTXO 集需要更多的资源,因此这种做法可以节省大量资源。
延伸阅读:造就最纯粹密码学货币》比特币 Taproot 比你想的还宽
铭文
Ordinals 协议利用了 SegWit 放宽了对写入比特币网路内容的大小限制,将铭文内容储存在见证资料中。使其可以储存最大 4MB 的元资料。Taproot 使得在比特币交易中储存任意见证资料变得更加容易,允许 Ordinals 开发人员 Casey Rodarmor 将旧操作码(OP_FALSE、OP_IF、OP_PUSH)重新用於他所描述的「信封」为被称为「铭文」储存任意资料。
铸造铭文的流程包含以下两个步骤:
- 首先,需要在提交交易中建立一个承诺到包含铭文内容的指令码的 Taproot 输出。储存的格式是 Taproot,即前一笔交易的输出是 P2TR (Pay-To-Taproot),後一笔交易的输入,在见证的 Taproot script 中嵌入特定格式的内容;首先将字串 ordn入栈,以消除铭文有其他用途的歧义。OP_PUSH 1 指示下一次推送包含内容型别,并 OP_PUSH 0 指示後续资料推送包含内容本身。大型铭文必须使用多次资料推送,因为 taproot 的少数限制之一是单个数据推送不得大於 520 位元组。此时铭文的资料已对应到交易输出的 UTXO 上,但是未被公开。
- 其次,需要在揭示交易中消费提交交易建立的那个输出。在这个阶段,通过将那笔铭文对应的 UTXO 作为输入,发起交易。此时,其对应的铭文内容被公开至全网。
通过上述两个步骤,铭文内容已与被铭刻的 UTXO 进行系结。再根据上文介绍的对於聪的定位,铭刻是在其输入的 UTXO 对应的第一个聪上进行,铭文内容包含在显示交易的输入中。根据上文介绍的对於聪的流转、追踪的介绍,这个被铭刻上特殊内容的聪可以被转移、购买、出售、丢失和恢复。需要注意的是,不可以重复铭刻,否则後面的铭文是无效的。
我们将通过铭刻一个 BTC NFT 小图片的例子来详细说明这个过程,这个过程主要包括之前提到的提交(commit)和揭露(reveal)两个阶段。首先,我们看到第一笔交易的 Hash ID 是 2ddf9…f585c 。可以注意到,这笔交易的输出不包含见证资料,网页中也没有相关的铭文资讯。
接着,我们检视第二阶段的记录,其 Hash ID 是 e7454…7c0e1 。在这里,我们可以看到 Ordinals inscription 的资讯,也就是见证的铭文内容。这笔交易的输入地址是前一个交易的输出地址,而输出的 0.00000546BTC(546 聪)则是将这个 NFT 传送到自己的地址。同时,我们也可以在 Sat 1893640468329373 中找到这个铭文所在的聪。
在比特币钱包中,我们可以看到这个资产。如果我们想要交易这个 NFT,可以直接将其传送给其他人的地址,也就是将这笔 UTXO 传送出去,这样就完成了铭文的流转。
四、 比特币钱包
在我们了解了什麽是 Ordinals 生态、聪的流转以及铭文的相关知识後,目前有许多应用场景,无论是 BRC-20,ORC-20,BRC-721,GBRC-721 等相关衍生协议的出现,需要我们有对应的钱包来支援和显示出代币资讯或者 NFT 小图片。本节我们会介绍一下不同比特币钱包地址的概念和特点。
比特币地址以 1、3 或 bc1 开头。就像电子邮件地址一样,它们可以与其他比特币使用者共享,这些使用者可以使用它们将比特币直接传送到自己的钱包。从安全形度来看,比特币地址没有任何敏感内容。它可以在任何地方释出,而不会危及帐户的安全。与电子邮件地址不同,我们可以根据需要随时建立新地址,所有这些地址都会将资金直接存入您的钱包。事实上,许多现代钱包会自动为每笔交易建立一个新地址,以最大限度地保护隐私。钱包只是地址和解锁其中资金的钥匙的集合。首先我们要知道比特币钱包的地址是怎麽产生的。
比特币私钥和公钥
比特币采用椭圆曲线 Secp256k1 ,「私钥」 是 1 到 n−1 之间的随机数,n 是个很大的数(256 个位元位),n 用科学计数法表示约为:
这个范围是极大的,我们是几乎无法猜出其他人的私钥的。这个随机整数私钥可以用 256 位元位表示,存在多种编码方式。如果使用 WIF、WIF-compressed 形式的私钥是没有加密的,可以解码得到原始的那个 「随机整数」。另一种方式是 BIP38 ,提议用 AES 演算法对私钥进行加密,这种方案得到的私钥以字元 6P 开头,这种私钥必须输入密码才能汇入到各种比特币钱包中,这就是我们平时常用的私钥。
随後我们会利用椭圆曲线公式 K = kG,由私钥 k 来生成比特币的公钥 K,G 为 Base Point,它是 secp256k1 的一个引数。可以得到 K 的两个座标,就是公钥的两种表达方式,分别为 「Uncompressed format」 和 「Compressed format」。
- Uncompressed 形式,就是把两个座标 x 和 y 直接连线在一起,再在前面加个 0x04 字首即可;
- Compressed 形式,就是当 y 为偶数时,编码为 02 x,当 y 为奇数时,编码为 03 x;
比特币地址
比特币各种型别的地址如下图可示,共有四种表示方法:
1. Legacy (P2PKH) 格式
范例:1Fh7ajXabJBpZPZw8bjD3QU4CuQ3pRty9u
地址以 「1」 开头,是比特币最初的地址格式,至今仍在使用。由公钥通过 Hash 计算後得到,也被称为 P2PKH 是 Pay To PubKey Hash(付款至公钥hash)的缩写。
2. Nested SegWit (P2SH) 格式
范例:3KF9nXowQ4asSGxRRzeiTpDjMuwM2nypAN
地址以 “3” 开头,P2SH 是 Pay To Script Hash(支付至指令码hash)的缩写,它支援比 Legacy 地址更复杂的功能。Nested P2SH,获取现有的 P2SH 地址 (以 「3」 开头),并与 SegWit 地址一起封装。
3. Native SegWit (Bech32) 格式
范例:bc1qf3uwcxaz779nxedw0wry89v9cjh9w2xylnmqc3
在 BIP0173 中提出了 bc1 开头的地址,它们是原生的隔离见证地址。Bech32 编码的地址,是专为 SegWit 开发的地址格式。Bech32 在 2017 年底在 BIP173 被定义,该格式的主要特点之一是它不区分大小写(地址中只包含 0-9,az),因此在输入时可有效避免混淆且更加易读。由於地址中需要的字元更少,地址使用 Base32 编码而不是传统的 Base58,计算更方便、高效。资料可以更紧密地储存在二维码中。Bech32 提供更高的安全性,更好地优化校验和错误检测程式码,将出现无效地址的机会降到最低。
Bech32 地址本身与 SegWit 相容。不需要额外的空间来将 SegWit 地址放入 P2SH 地址,因此使用 Bech32 格式地址,手续费会更低。Bech32 地址比旧的 Base58(Base58Check 编码用於将比特币中的位元组阵列编码为人类可编码的字串)地址有几个优点:QR 码更小;更好地防错;更加安全;不区分大小写;只由小写字母组成,所以在阅读、输入和理解时更容易。
4. Taproot 格式 (P2TR)
Bech32 有个缺点:如果地址的最後一个字元是 p,则在紧接着 p 之前的位置插入或者删除任意数量的字元 q 都不会使其 checksum 失效。
为了缓解 Bech32 的上述缺点,在 BIP0350 中提出了 Bech32m 地址:
- 对於版本为 0 的原生隔离见证地址,使用以前的 Bech32;
- 对於版本为 1(或者更高)的原生隔离见证地址,则使用新的 Bech32m。
对於 Bech32m 地址,当版本为 1 时,它们总是以 bc1p 开头(即 Taproot 地址)。具体来说,就像本地隔离见证一样,钱包可以由种子短语和密码短语组成。这些用於生成扩充套件的公钥和私钥,用於在分层确定性钱包中派生任意路径的地址。主要是储存 BRC-20 以及 BTC 的 NFT 等。