Ordinals铭文如何绑定到某一聪?比特币UTXO与铭文存储机制详解
比特币的最小单位是“聪”:1 BTC = 100,000,000聪。所有金额最终都以聪来计算。但比特币不会给每一聪单独建一条记录,它采用的是UTXO模型(Unspent Transaction Output,未花费交易输出)。

可以把它理解成:系统只记“一袋一袋的钱”,每袋上写着“里面有多少聪”和“谁有权花它”,而不是给袋里的每一聪都贴上标签,钱包显示的余额,其实就是把你能控制的那些“钱袋”金额加总起来。
交易输出(TxOut)在底层长什么样?
每一笔交易输出在原始数据里只有两个核心字段!
| 字段 | 大小 | 含义 |
|---|---|---|
| value | 8字节(int64,小端序) | 这袋钱有多少聪 |
| scriptPubKey | 变长 | 锁定脚本,规定满足什么条件才能花这笔钱 |
完整结构是:
value(8字节)+ scriptPubKey长度(变长)+ scriptPubKey内容
举例:矿工挖到一个区块,获得3.125 BTC奖励。
3.125 BTC = 312,500,000聪。
Coinbase交易的某个输出在数据里就只记:
1. value = 312500000(一个整数)
2. scriptPubKey = 某个地址对应的锁定脚本
系统不会生成3.125亿条“第1聪、第2聪……”的记录,它只存一个数字:312500000。
以后你转账也是一样
假设你有一袋1亿聪(1 BTC),要转0.3 BTC给别人:
● 整个旧UTXO被“花掉”
● 新建两个新输出:收款人30,000,000聪|找零约69,900,000聪(剩下的给矿工当手续费)
旧袋子消失,新袋子诞生。这就是UTXO的本质:永远是整袋进出,而不是一聪一聪拆开。
全节点会维护一个“当前所有未花费输出集合”(UTXO set)。要记住比特币原生数据库里没有任何字段记录“第几聪”,它只知道“这袋有多少聪”。
Ordinals如何给每一聪“编身份证”
原生比特币不追踪单聪,但Ordinals序数理论用一套规则给每一聪编了号。
编号规则
1. 按挖出顺序从0开始编号。
2. 创世块(区块0)的50 BTC = 50亿聪,编号0到4,999,999,999。
3. 区块1的补贴继续往后排,依此类推。
4. 每个区块补贴的起始编号可以精确计算,subsidy随减半周期变化(早期50 BTC,后来25、12.5、6.25、3.125……)。

流转规则(FIFO,先进先出)
当一笔交易把输入的聪转到输出时,Ordinals按顺序“倒”:
1. 把所有输入的聪按顺序排成一条长队。
2. 第一个输出拿走队头它value数量的聪。
3. 第二个输出再拿走接下来的,以此类推。
4. 多出来的进手续费,最后由Coinbase交易“接收”。
举例(简化):
1. 输入有5聪,序数 #100 ~ #104
2. 输出1:3聪 → 拿走 #100、#101、#102
3. 输出2:2聪 → 拿走 #103、#104
这些编号不是比特币数据库里的字段,而是索引器(如ord)根据历史交易顺序计算出来的。任何人运行同样的规则,算出的结果都一样。
1. 比特币本身:只知道“这袋有N聪”
2. Ordinals索引器:额外知道“这袋里的第0到N-1个位置分别对应哪些序数”

某一聪的当前位置用satpoint表示:
交易ID:输出索引:偏移量
如abc123...:0:6表示某笔交易第0个输出里的第6个聪。
每一聪在原生比特币里没有ID,在Ordinals视角下有唯一序数,并且可以通过FIFO规则追踪到它当前所在的UTXO和偏移位置。
铭文(Inscription)的数据具体存在哪里?怎么绑到某一聪?
铭文不是改比特币协议,而是利用已有的Taproot +见证数据(Witness)机制,把任意内容“挂”在某一聪上。
数据存在哪里?
铭文内容完全上链,存放在Taproot脚本路径花费的见证数据里。

具体结构是一个叫envelope(信封)的构造:
OP_FALSE
OP_IF
OP_PUSH "ord" ← 协议标识
OP_PUSH 1 ← 内容类型标签
OP_PUSH "image/png" ← MIME类型(或text/plain等)
OP_PUSH 0 ← 正文开始标记
OP_PUSH <数据块1> ← 实际内容(可分多段,每段≤520字节)
OP_PUSH <数据块2>
...
OP_ENDIF
因为包在OP_FALSE OP_IF ... OP_ENDIF里,这段脚本永远不会被执行,所以里面可以塞任意字节,不会影响正常的花费验证。
这些数据位于交易的witness部分。SegWit/Taproot对见证数据有约75%的折扣(1字节见证数据只计1重量单位,普通数据计4),所以存大文件相对便宜。
为什么需要两笔交易(Commit + Reveal)?
Taproot脚本路径花费必须先有一个对应的Taproot输出。
1.Commit交易:创建一个Taproot输出,它的脚本树里已经“承诺”了包含铭文内容的脚本(内容本身还不公开)。
2.Reveal交易:花费上面那个输出,把完整的envelope脚本放到见证数据里公开。
一旦Reveal交易被打包进区块,内容就永久上链,任何人都能从区块链上读出来。
铭文如何对应到“那一聪”?
1. 默认情况下,铭文绑定在Reveal交易第一个输入的第一聪(该输入的序数队列中的第0个位置)。
2. 也可以通过pointer字段指定偏移,绑定到同一输入里的其他聪。
之后,这聪不管被转到哪个新的UTXO,铭文都跟着它走(因为Ordinals用FIFO继续追踪这聪的位置)。
铭文的唯一ID通常写成:
<Reveal交易的txid>i<索引>
如521f8ecc...i0表示该Reveal交易里的第0个铭文。
多个带铭文的聪可以合并到同一个UTXO吗?会不会空间不够?
好几个聪各自挂着图片铭文,把它们合并进同一个UTXO后,图片数据会不会都挤进这个新UTXO里?答案是不会。
关键区别
●图片的真实数据:永远待在当初那笔Reveal交易的见证数据里,合并时完全不动。
●聪本身:只是被移动到新的UTXO里。
UTXO只记录“这袋有多少聪”和“怎么花它”,它从来不存图片内容。合并操作只是让多枚带铭文的聪“住”进同一个钱袋,图片数据仍然分别待在各自被铭刻时的历史交易中,新UTXO在区块链上的体积几乎没有增加。
因而多个带图片铭文的聪完全可以合并到同一个UTXO,这是正常且常见的操作。
普通人可以怎么理解
1. 比特币只认“钱袋”(UTXO)和金额。
2. Ordinals给袋里的每一聪编了号,并规定转账时按顺序分发。
3. 铭文就是在某笔交易的见证数据里塞进一段“永远不会执行的脚本”,并约定“这段内容归这袋钱里的第X聪所有”。
4. 谁控制了包含那聪的UTXO,谁就控制了铭文。
5. 多个铭文可以住在同一个UTXO里,图片数据不会跟着复制或挤在一起。
整体对应关系一览
| 层级 | 存什么 | 在哪里 | 有没有单聪ID |
|---|---|---|---|
| 比特币原生 | 金额(聪数)+锁定脚本 | 交易输出的value + scriptPubKey | 无 |
| UTXO集合 | 当前所有未花费的输出 | 全节点维护的内存/磁盘结构 | 无 |
| Ordinals | 每一聪的序数+当前位置 | 索引器根据历史计算 | 有(计算出来的) |
| 铭文内容 | 图片/文本/JSON等字节 | Reveal交易的witness(envelope) | 绑定到特定序数的聪 |






