随着 Ordinals 协议的诞生,其为比特币提供了编号和铭文的功能,从而拓宽了比特币生态系统的产品范围,并为比特币生态带来了新的活力。在本文中,我们将深入探讨 Ordinal 协议的细节,包括如何对每个比特币进行编号和追踪,以及铭文与编号之间的关系。但在深入探讨这个主题之前,我们需要首先了解一些比特币的基本背景,以帮助我们更好地理解后续内容。
完成本文的阅读后,你将掌握比特币的交易机制和支付模型,了解 Ordinals 如何为每个聪实现编号和追踪,以及铭文是如何创建和交易的。此外,你还将了解不同类型的钱包之间的差异。
比特币采用了一个类似于现金的交易模型(cash system),其支付方式基于一种称为 UTXO 的模型,这与传统的基于账户余额的模型有所不同。举例而言:在银行的账户记账模型流程中,当 A 向 B 转账 100 元时,银行会记录三个步骤,这三个步骤构成了一个交易过程。第一步是从 A 的账户中扣除 100 元,这个步骤的记录 ID 为 tid1。第二步是将 100 元存入 B 的账户中,这个步骤的记录 ID 为 tid2。第三步是记录一笔转账记录,该记录将 tid1 和 tid2 关联起来,表示 A 账户减少 100 元,B 账户增加 100 元。这样,A 和 B 之间的转账关系就被记录下来,并且可以在未来查询与追踪。现在,我们将通过对于 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<CTxIn> vin;const std::vector<CTxOut> vout;const int32_t nVersion;const uint32_t nLockTime;
来源:https://github.com/bitcoin/bitcoin/blob/v22.0/src/primitives/transaction.h#L270
我们可以在blockchain.com随机选一个交易记录来分析,下图展示了 Hash ID 为0627...345c2f2 的交易。其包含了一个输入和两个输出。
来源:https://www.blockchain.com/explorer/transactions/btc/0627052b6f28912f2703066a912ea577f2ce4da4caa5a5fbd8a57286c345c2f2
通过使用 bitcoin-cli 的命令 getrawtransaction 和 decoderawtransaction ,我们可以查看上述交易的底层结构:
{ "version": 1, "locktime": 0, "vin": [ { "txid": "7957a35fe64f80d234d76d83a2a8f1a0d8149a41d81de548f0a65a8a999f6f18", "vout": 0, "scriptSig" : "3045022100884d142d86652a3f47ba4746ec719bbfbd040a570b1deccbb6498c75c4ae24cb02204b9f039ff08df09cbe9f6addac960298cad530a863ea8f53982c09db8f6e3813[ALL] 0484ecc0d46f1918b30928fa0e4ed99f16a0fb4fde0735e7ade8416ab9fe423cc5412336376789d172787ec3457eee41c04f4938de5cc17b4a10fa336a8d752adf", "sequence": 4294967295 } ], "vout": [ { "value": 0.01500000, "scriptPubKey": "OP_DUP OP_HASH160 ab68025513c3dbd2f7b92a94e0581f5d50f654e7 OP_EQUALVERIFY OP_CHECKSIG" }, { "value": 0.08450000, "scriptPubKey": "OP_DUP OP_HASH160 7f9b1a7fb68d60c536c2fd8aeaa53a8f3cc025a8 OP_EQUALVERIFY OP_CHECKSIG", } ]}
在比特币网络中,交易输出包含两个重要信息:地址(公钥哈希)和 金额(以比特币为单位)。如果一个交易的输出没有在其他交易的输入中使用,那么这个交易输出就被称为未消费交易输出(UTXO)。谁拥有 UTXO 中公钥对应的私钥,谁就有权使用(即花费)这个 UTXO。
我们观察一下上面代码中的“vin”中的信息,它表示这个交易所花费的 UTXO 来自于另外一个交易(其 id 为 7957a35...99f6f18)的第 0 个输出(一个交易的输出可以有多个,索引从 0 开始编号),我们可以从历史交易中查找出这个 UTXO 的金额(比如为 0.1),所以这个交易中这个用户花费了 0.1 BTC,数值 0.1 不需要显式地写在 交易中,而是通过查找 UTXO 信息来得到的。这个交易的“vout”有两个输出,这两个输出为两个新的 UTXO,对应了新的余额以及持有人,直到有另外的交易把它们作为输入消费掉。
为了更好地理解比特币网络的支付模型,我们通过一个例子介绍由 A 支付给 B 金额为 n 的比特币的支付流程。下图展示了用户 A 发送 3 个比特币给用户 B 的过程。
比特币总量是 2100 万个,每个比特币包含 10^8 个聪 (Satoshi, Sat)。因此,比特币网络上一共有 2100 万 *10^8 个聪。Ordinals 协议将这些聪区分出来,为每个聪进行唯一编号。本节将介绍这个协议是如何做到为每一个聪进行唯一编号,并且如何追踪其所在的账户。此外,还会简介对于聪的稀有度份分类。
根据 Ordinals 协议,聪的编号是根据它们被开采的顺序而定。下图展示了第 0 个区块挖出的第 0 个聪的表示方式。
来源:https://ordinals.com/sat/0
对于聪的表达方式有多种:
我们将通过一个例子来讲解如何对新挖出的比特币进行编号。观察比特币区块链的第 795952 个区块,我们可以看到其中第一笔交易Tx 3a1f...b177 记录了矿工的奖励(coinbase transaction)。这笔交易包含了新挖出的比特币,这些比特币是作为矿工的打包奖励,以及交易发起者付给矿工的手续费。通过查看下图的输入,我们可以发现其 UTXO 的 id 由一串 0 和区块高度组成。输出的地址则是矿工的钱包地址,金额则是上述的奖励和手续费的总和。
来源:https://ordinals.com/tx/3a1fdea5953faea184e0303774ea234533aa58979a4d9a4f1c0de0d9b2efb177
若我们进一步查看输出给矿工的部分,可以看到地址、金额以及所包含的聪的分布情况。如前所述,这些包含了挖矿奖励和手续费。其中,绿色的 sats 编号信息1941220000000000–1941220625000000是挖矿奖励产生的新聪,其余的 712 条聪的记录则对应了该区块中的所有手续费。
来源:https://ordinals.com/output/3a1fdea5953faea184e0303774ea234533aa58979a4d9a4f1c0de0d9b2efb177:0
我们可以验证一下 Sat 1941220000000000 这个编号。它的 block 编号为 795952,十进制符号 (decimal) 为 795952.0,意味着挖掘该聪的区块高度为 795952,聪在此区块中的编号为 0,后面的稀有度 (rarity) 标记为 uncommon,我们将在后面的部分进行详细介绍。
来源:https://ordinals.com/sat/1941220000000000
因为每个 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 个聪的流转路径为:
作为 Ordinals 协议的衍生玩法,聪的稀有度可以根据它们的挖掘顺序来定义。这将导致一些特殊的聪具有不同的稀有度。以下是不同聪的稀有程度:
这种稀有聪的概念可以为比特币生态增加更多的趣味性和价值。不同稀有度的聪可能在市场上具有不同的价值,吸引收藏家和投资者。
Ordinals 与其他非比特币链上的 NFT 显著不同。其中,最主要的差异在于,Ordinals 的元数据并没有存储在一个特定的位置上。相反,这些元数据被嵌入到交易的见证数据 (witness data, witness field) 中,这就是为何我们称之为 "铭文 (inscription)" 的原因,因为这些数据被像铭文一样“刻”在比特币交易的特定部分上,而这些数据正是附着在特定聪上的。这一铭文过程通过隔离见证 (Segregated Witness, SegWit) 和“向 Taproot 支付”(Pay-to-Taproot, P2TR) 的方式实现,其中包含了提交(commit)和揭露(reveal)两个阶段,能够将任何形式的内容(如文本、图像或视频)铭刻在指定的聪上。我们将在下文介绍另一种更加直接的存储方式 OP_RETURN 并阐述其为何没被作为铭文的手段。同时,我们会介绍隔离见证与 Pay-to-Taproot 是什么,以及他们在铭文中扮演什么角色。最后我们会介绍铭文的方式。
在 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 是将某些交易签名数据 ( 见证数据 ) 与交易分开。
将签名与交易相关数据分离的主要好处是减少了存储在一个比特币块中的数据的大小。这样每个块具有额外的容量来存储更多的交易,也意味着网络可以处理更多的交易,并且发送者支付更低的手续费。从技术上来说就是把脚本签名 (scriptSig) 信息从基本结构 (base block) 里拿出来,放在一个新的数据结构当中。做验证工作的节点和矿工也会验证这个新的数据结构里的脚本签名,以确保交易有效。Segwit 升级在交易输出中引入了一个新的见证字段,以确保隐私和性能。虽然见证数据不是为了数据存储而设计的,但它实际上给了我们一个存储铭文元数据等内容的机会。我们通过下图来更加形象地理解隔离见证:
SegWit 前后的交易数据结构
P2TR 是比特币的一种交易输出类型,它是在 2021 年进行的 Taproot 升级中引入的,它使得不同的交易条件可以更加隐私地存储在区块链中。在 Ordinals 的铭文中,P2TR 扮演着至关重要的角色。铭文本质上是将特定的数据内容嵌入到比特币交易中,而 Taproot 升级,尤其是 P2TR,使得这种嵌入数据变得更加灵活和经济。
首先,由于 Taproot 脚本的存储方式,我们可以在 Taproot 脚本路径支出脚本中存储铭文内容,这些脚本在内容方面几乎没有任何限制,同时还能获得见证数据的折扣,使得存储铭文内容相对经济。由于 Taproot 脚本的消费只能从已经存在的 Taproot 输出中进行,因此,铭文采用了两阶段的提交 / 揭示流程。首先,在提交交易中,创建了一个承诺包含铭文内容的脚本的 Taproot 输出。然后,在揭示交易中,消费了由提交交易创建的输出,从而在链上揭示了铭文内容。
这种做法大大降低了对资源的消耗。如果不使用 P2TR,见证信息会存储在交易的输出中。这样,只要这笔输出未被消费,见证信息就会一直存储在 UTXO 集中。相反,如果使用了 P2TR,见证信息不会出现在提交阶段生成的交易中,因此它不会被写入 UTXO 集。只有当这笔 UTXO 被消费时,见证信息才会在揭示阶段的交易输入中出现。P2TR 让元数据能够写入比特币区块链,但却从未出现在 UTXO 集中。由于维护 / 修改 UTXO 集需要更多的资源,因此这种做法可以节省大量资源。
Ordinals 协议利用了 SegWit 放宽了对写入比特币网络内容的大小限制,将铭文内容存储在见证数据中。使其可以存储最大 4MB 的元数据。Taproot 使得在比特币交易中存储任意见证数据变得更加容易,允许 Ordinals 开发人员 Casey Rodarmor 将旧操作码(OP_FALSE、OP_IF、OP_PUSH)重新用于他所描述的「信封」为被称为「铭文」存储任意数据。
铸造铭文的流程包含以下两个步骤:
OP_FALSE OP_IF OP_PUSH "ord" OP_PUSH 1 OP_PUSH "text/plain;charset=utf-8" OP_PUSH 0 OP_PUSH "Hello, world!" OP_ENDIF
包含字符串"Hello, world!"的文本铭文被序列化如上
通过上述两个步骤,铭文内容已与被铭刻的 UTXO 进行绑定。再根据上文介绍的对于聪的定位,铭刻是在其输入的 UTXO 对应的第一个聪上进行,铭文内容包含在显示交易的输入中。根据上文介绍的对于聪的流转、跟踪的介绍,这个被铭刻上特殊内容的聪可以被转移、购买、出售、丢失和恢复。需要注意的是,不可以重复铭刻,否则后面的铭文是无效的。
我们将通过铭刻一个 BTC NFT 小图片的例子来详细说明这个过程,这个过程主要包括之前提到的提交(commit)和揭露(reveal)两个阶段。首先,我们看到第一笔交易的 Hash ID 是2ddf9...f585c。可以注意到,这笔交易的输出不包含见证数据,网页中也没有相关的铭文信息。
来源:https://www.blockchain.com/explorer/transactions/btc/2ddf90ddf7c929c8038888fc2b7591fb999c3ba3c3c7b49d54d01f8db4af585c
接着,我们查看第二阶段的记录,其 Hash ID 是e7454...7c0e1。在这里,我们可以看到 Ordinals inscription 的信息,也就是见证的铭文内容。这笔交易的输入地址是前一个交易的输出地址,而输出的 0.00000546BTC(546 聪)则是将这个 NFT 发送到自己的地址。同时,我们也可以在Sat 1893640468329373中找到这个铭文所在的聪。
来源:https://www.blockchain.com/explorer/transactions/btc/e7454db518ca3910d2f17f41c7b215d6cba00f29bd186ae77d4fcd7f0ba7c0e1
来源:https://www.blockchain.com/explorer/transactions/btc/e7454db518ca3910d2f17f41c7b215d6cba00f29bd186ae77d4fcd7f0ba7c0e1
在比特币钱包中,我们可以看到这个资产。如果我们想要交易这个 NFT,可以直接将其发送给其他人的地址,也就是将这笔 UTXO 发送出去,这样就完成了铭文的流转。
在我们了解了什么是 Ordinals 生态、聪的流转以及铭文的相关知识后,目前有许多应用场景,无论是 BRC-20,ORC-20,BRC-721,GBRC-721 等相关衍生协议的出现,需要我们有对应的钱包来支持和显示出代币信息或者 NFT 小图片。本节我们会介绍一下不同比特币钱包地址的概念和特点。
比特币地址以 1、3 或 bc1 开头。就像电子邮件地址一样,它们可以与其他比特币用户共享,这些用户可以使用它们将比特币直接发送到自己的钱包。从安全角度来看,比特币地址没有任何敏感内容。它可以在任何地方发布,而不会危及帐户的安全。与电子邮件地址不同,我们可以根据需要随时创建新地址,所有这些地址都会将资金直接存入您的钱包。事实上,许多现代钱包会自动为每笔交易创建一个新地址,以最大限度地保护隐私。钱包只是地址和解锁其中资金的钥匙的集合。首先我们要知道比特币钱包的地址是怎么产生的。
比特币采用椭圆曲线Secp256k1,“私钥”是 1 到 n−1 之间的随机数,n 是个很大的数(256 个比特位),n 用科学计数法表示约为 1.15792*10^77。这个范围是极大的,我们是几乎无法猜出其他人的私钥的。这个随机整数私钥可以用 256 比特位表示,存在多种编码方式。如果使用 WIF、WIF-compressed 形式的私钥是没有加密的,可以解码得到原始的那个“随机整数”。另一种方式是 BIP38,提议用 AES 算法对私钥进行加密,这种方案得到的私钥以字符 6P 开头,这种私钥必须输入密码才能导入到各种比特币钱包中,这就是我们平时常用的私钥。
随后我们会利用椭圆曲线公式 K = kG,由私钥 k 来生成比特币的公钥 K,G 为 Base Point,它是 secp256k1 的一个参数。可以得到 K 的两个坐标,就是公钥的两种表达方式,分别为“Uncompressed format”和“Compressed format”。
比特币各种类型的地址如下图可示,共有四种表示方法:
Legacy (P2PKH) 格式
范例:1Fh7ajXabJBpZPZw8bjD3QU4CuQ3pRty9u
地址以“1”开头,是比特币最初的地址格式,至今仍在使用。由公钥通过 Hash 计算后得到,也被称为 P2PKH 是 Pay To PubKey Hash(付款至公钥哈希)的缩写。
Nested SegWit (P2SH) 格式
范例:3KF9nXowQ4asSGxRRzeiTpDjMuwM2nypAN
地址以"3"开头,P2SH 是 Pay To Script Hash(支付至脚本哈希)的缩写,它支持比 Legacy 地址更复杂的功能。Nested P2SH,获取现有的 P2SH 地址 ( 以“3”开头 ),并与 SegWit 地址一起封装。
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 码更小;更好地防错;更加安全;不区分大小写;只由小写字母组成,所以在阅读、输入和理解时更容易。
Taproot 格式 (P2TR)
Bech32 有个缺点:如果地址的最后一个字符是 p,则在紧接着 p 之前的位置插入或者删除任意数量的字符 q 都不会使其 checksum 失效。为了缓解 Bech32 的上述缺点,在 BIP0350 中提出了 Bech32m 地址:对于版本为 0 的原生隔离见证地址,使用以前的 Bech32;对于版本为 1(或者更高)的原生隔离见证地址,则使用新的 Bech32m。对于 Bech32m 地址,当版本为 1 时,它们总是以 bc1p 开头(即 Taproot 地址)。具体来说,就像本地隔离见证一样,钱包可以由种子短语和密码短语组成。这些用于生成扩展的公钥和私钥,用于在分层确定性钱包中派生任意路径的地址。主要是储存 BRC-20 以及 BTC 的 NFT 等。
Spectrum Labs 是一个由专注于区块链研究的硕士和博士,以及区块链行业内部的资深人士组成的团队。我们致力于区块链研究链技术及其应用,以帮助人们更好地了解区块链。Spectrum Labs 的主要业务包括研究报告的撰写、课程的编写和工具的开发。
BTC NFT 中文社区 是一个为全球华人新人打造的 BTC NFT 中文交流广场。
【免责声明】市场有风险,投资需谨慎。本文不构成投资建议,用户应考虑本文中的任何意见、观点或结论是否符合其特定状况。据此投资,责任自负。