中本聪(satoshis),这里简称聪,是比特币网络的原子原生货币。一个比特币可以细分为1亿个聪,并且不能再继续细分。
序数理论关注的是中本聪,赋予聪个体身份,并允许它们被追踪、转移和赋予意义。
序数理论的优势
- 序数理论不依赖比特币之外的侧链或代币,并且可以在不对比特币网络进行任何更改的情况下使用。
- 序数理论赋予每个聪独一无二的价值,使他们能够作为收藏品被收集和交易。
- 任意资产,例如 NFT、安全代币、账户或稳定币,可以使用序数作为稳定标识符附加到聪上。
序数理论的劣势
序数理论给单独的聪赋予意义,但是比特币网络不鼓励太小的UTXO(Unspend transaction output)存在,如果一个交易的输出太小(一般而言,小于330聪),网络不会对该交易进行打包。因此,无法仅转移单个聪。另外,如果想要把连续的3个聪分开,需要精心设计额外的交易来达成。
序数理论的盛行会导致大量很小的UTXO存在,这加重了比特币网络对UTXO的管理负担,并且这些UTXO作为比特币而言价值很低,归集成本已经超出了本身的价值,因此这部分聪可以认为从比特币的流通中燃烧了,某种意义上减少了比特币的供应量。(也许这并不是劣势:))
聪的稀缺性
序数理论给每个聪编号,因此,某些特殊意义编号的聪便有了稀缺性。比特币网络中存在一些周期性的事件,有些很频繁,有些很久才出现一次,自然而然就给聪赋予了稀缺性。
下面是比特币网络中的周期性事件:
- 区块 比特币网络平均大约每10分钟出一次块。
- 难度调整 每2016个区块,大约每2周,比特币网络进行一次挖矿的难度调整。
- 减半 每21万个区块,大约每4年,每个区块挖矿的奖励减半。
- 循环 每6次减半,大约每24年,减半的事件会和难度调整事件重合,成为循环,第一次难度重合事件会发生在2032年。
这些周期性事件给了我们下面的稀有性定义:
- 普通聪 每一个区块里的除了第一个聪的其它聪(索引不为0的聪)。
- 罕见聪 每一个区块的第一个聪。
- 稀有聪 每个难度调整周期的第一个聪。
- 史诗聪 每个减半周期的第一个聪。
- 传奇聪 每个循环周期的第一个聪。
- 神话聪 创世区块的第一个聪,只有1个。
聪的命名
根据聪的稀有性,可以使用度数表示法给聪命名:
A°B′C″D‴ |
下面是一些例子。
普通聪:
1°1′1″1‴ |
罕见聪:
1°1′1″0‴ |
稀有聪:
1°1′0″0‴ |
史诗聪:
1°0′1″0‴ |
传奇聪:
1°0′0″0‴ |
神话聪:
0°0′0″0‴ |
如果区块索引为0,可以忽略,下面是罕见聪的表示:
1°1′1″ |
除了按照度的表示方法命名,聪最直接的命名方式是用序数来表示,每个聪的序数如何获取将在后面说明。另外还可以用a-z的字符对聪的序号进行编码得到字符名称等。
其它稀缺性的定义
除了根据比特币的周期性事件来定义聪的稀缺性,还有其它的维度,比如:
- 中本聪本人挖掘出来的聪
- 序数对称或者回文
- 序数末尾有多个0
- 序数在数学上有特殊意义的聪
- 和特定历史事件关联的聪
- 每个区块的最后一个聪
- 等等
如何给聪编号
每个聪都按其开采顺序从0开始进行序列编号。这些数字被称为序数,给出了总供应中每个聪的顺序。 序数这个词非常明确,因为它在比特币协议的其它地方没有使用。
根据交易中输入和输出的大小和顺序,交易输入中的聪序号以先进先出的顺序传输到输出聪。在普通交易中,并没有创建新的聪,因此只是聪的转移。
如果使用与当前UTXO集合中的输出相同的交易ID来挖掘交易,则遵循比特币核心的行为,新的交易输出将取代旧的UTXO集合条目,从而破坏第一笔交易的任何未使用输出中包含的聪。该规则需要处理具有重复交易ID的两对主网交易,即区块91812/91842和91722/91880的coinbase交易,这些交易是在BIP-34使得不可能创建具有重复ID的交易之前开采的。
出于算法实现的目的,Coinbase 交易被认为具有大小等于区块奖励的隐式输入,然后是块中每个付费交易的输入,按照这些交易出现在块中的顺序。隐试区块奖励输入包含该区块新创建的聪。隐试费用输入则包含在区块交易中作为费用支付的聪。
Coinbase中少付区块奖励不会改变后续区块中开采的序数。序号仅取决于可以开采的聪数量,而不是实际开采的数量。
源码阅读
首先是一些基本结构的定义:
- 减半周期(Epoch)
// 减半周期用u32表示 |
- 区块高度
pub struct Height(pub u32); |
- 聪
// 使用整数序数来表示聪 |
- 聪的度表示法
pub struct Degree { |
- 稀有性
pub enum Rarity { |
为比特币网络建立序数索引
在比特币网络中,聪位于UTXO中,很自然地,我们想要能够快速检索某个聪在哪个UTXO中,以及某个UTXO中包含哪些聪。
对于前者,如果要给每个聪索引的话,会消耗巨大的存储空间,一般是记录稀有聪对应的UTXO。下面是ord的具体实现。
impl<'index> Updater<'index> { |
index_block
函数调用了index_utxo_entries
,下面是其实现:
fn index_utxo_entrie( |