BitcoinのOrdinal Theoryについて（Bitcoin NFT)

## はじめに

最近NFT界隈が幻滅期に突入しているようですが、今年の2月くらい？より新たな潮流が誕生しました。
これまでNFTのブロックチェーンといえばEtherium, Solana, BSC, Maticなどの話で、Bitcoinは蚊帳の外でした。
Bitcoinはあくまで価値保存や決済に特化したブロックチェーンでその他の応用は考えられませんでした。
しかし、直近のアップグレード(Taproot)によりスケーラビリティが向上したことで、安価でチェーン上にデータを刻み込めるようになりました。
　_※ここの説明が不正確かもしれません。誤りがあったらご指摘ください。_
その一つの応用として、BitcoinNFT[^1]というものが考えられ、最近徐々に注目されつつあります。
本記事では、BitcoinNFTの基礎となる、Ordinal theoryについて簡単に説明します。

## Ordinal theory とは

* 公式サイト；　https://ordinals.com/
    * Ordinalsの概要説明(Handbook)
    * 簡単なビューアー（検索ツール)
    * Ordinal時計（Clock)
        * 後ほど説明します

ビットコインは生涯の発行枚数上限がプログラムにより決まっていて、その枚数は2100万枚(BTC)です。
さらに1BTCは分割することができて、「1億分の1」BTCを1sat[^2]といいます。(ビットコインの最小単位です)

Ordinal theory[^3]　ではこのすべてのsatに一意に識別子を割り振り区別できるようにしています。
(紙幣の製造番号のようなものだと思ってください）

## アルゴリズム

Ordinal theory提唱者のBIP[^4]に記載があります。
刻み込み(inscribe)を実行するord walletのソースコードも下記です。

https://github.com/ordinals/ord/blob/master/bip.mediawiki#specification

コードを抜粋すると下記です。

```python

# subsidy of block at given height
def subsidy(height):
  return 50 * 100_000_000 >> height // 210_000

# first ordinal of subsidy of block at given height
def first_ordinal(height):
  start = 0
  for height in range(height):
    start += subsidy(height)
  return start

# assign ordinals in given block
def assign_ordinals(block):
  first = first_ordinal(block.height)
  last = first + subsidy(block.height)
  coinbase_ordinals = list(range(first, last))

  for transaction in block.transactions[1:]:
    ordinals = []
    for input in transaction.inputs:
      ordinals.extend(input.ordinals)

    for output in transaction.outputs:
      output.ordinals = ordinals[:output.value]
      del ordinals[:output.value]

    coinbase_ordinals.extend(ordinals)

  for output in block.transaction[0].outputs:
    output.ordinals = coinbase_ordinals[:output.value]
    del coinbase_ordinals[:output.value]
```

上記を理解するには、bitcoinの残高を管理する仕組みであるUTXOを理解する必要があります。
 
### UTXO

Unspent Transaction Outputの略で日本語では未使用トランザクションアウトプットと訳されています。

ビットコインの送金トランザクションを見てみてください。

https://chainflyer.bitflyer.jp/Transaction/a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d

どのトランザクションを見ても[^5]、必ずInput（入力)という項目とOutput(出力)という項目があります。
Inputの合計値とOutputの合計値は必ず等しくなるようになっています。
ただし、1つのUTXO=1BTCとは限らず、1000BTCだったり、5BTCだったりします。(1000円札、5円硬貨のようなものです）
ウォレットに紐づくUTXOの中から送金金額以上のUTXOをかき集めて(Input)消費します。
例えば1002BTCの送金を行う際1000BTCと5BTCのUTXOしかなかった場合は、1000BTCと5BTCを消費します。[^6]
ビットコインのアルゴリズムにより新たに1003BTCとお釣りとなる2BTC(Output)を作成し、　1003BTCを送り先のUTXOとして紐付け、2BTCを送り元のUTXOとして紐づけます。このようにして、ビットコインは循環しています。

さて、これを踏まえて、先ほどのOrdinal theoryのアルゴリズムを見てみましょう。

### subsidy（マイニング手数料)

```python
# subsidy of block at given height
def subsidy(height):
  return 50 * 100_000_000 >> height // 210_000
```

ブロックの高さに応じて、支払われる手数料を返す関数です。
約10分ごとに1ブロック確定していき、21万ブロック(約4年)生成されたら半減期が訪れます。
1ブロックあたりのマイニング報酬が最初50BTCだったものが半減期により25BTC => 12.5BTC ...
と減っていきいずれ次第に報酬が減っていきます。最終的にトータル供給されるBTCは約2100万に収束します。
この関数は、ブロックの高さ（数）から、そのブロックにおける報酬金額をsatsで返却しています。

### first_ordinal(最初のOrdinal番号)

```python
# first ordinal of subsidy of block at given height
def first_ordinal(height):
  start = 0
  for height in range(height):
    start += subsidy(height)
  return start
```

そのブロック上で初めて払い出されるOrdinal(番号)を取得する関数です。
ブロックの高さを引数に取り、単純に今まで払い出された番号から始まって、
そのブロックの報酬分順番に新たにOrdinalを割り当てる関数です。

### assign_ordinals(Ordinalsの割り当て）

```python
# assign ordinals in given block
def assign_ordinals(block):
  first = first_ordinal(block.height)
  last = first + subsidy(block.height)
  coinbase_ordinals = list(range(first, last))

  for transaction in block.transactions[1:]:
    ordinals = []
    for input in transaction.inputs:
      ordinals.extend(input.ordinals)

    for output in transaction.outputs:
      output.ordinals = ordinals[:output.value]
      del ordinals[:output.value]

    coinbase_ordinals.extend(ordinals)

  for output in block.transaction[0].outputs:
    output.ordinals = coinbase_ordinals[:output.value]
    del coinbase_ordinals[:output.value]
```

coinbase_ordinalsに、新規に払い出した番号を割り当てています。
その下にfor文がいくつかあります。

```
①for
    ②for
    ③for
    ④coinbase_ordinals.extend(ordinals)
⑤for
```

①は、UTXOのアルゴリズムにおいて、Inputに含まれるsats(Ordinals)を新たに生成したsatsに割り当てるアルゴリズムです。
Inputの合計値とOutputの合計値は等しくなるものの、各UTXO単位の塊の数が等しくなるとは限りません。
InputのUTXOは消費して、新たにOutputのUTXOを生成するのがBitcoinのアルゴリズムなのです。
②でInputに含まれるOrdinalsを　一旦　　`Ordinals` として定義したプールに退避して、
③でFIFO（先入り先出し）で新たに生成されるものに　`Ordinals`　から割り当てを行っています。
余った送金手数料は、マイナーに支払われる仕様です（④）
⑤で新規に払い出したOrdinalsをマイナーに支払われるUTXOに割り当てています。

このように単純なアルゴリズムを使うことで、送金時UTXOが消費されても、Ordinalをトレースすることが可能になりました。

## Ordinalsのレアリティ

上記により、すべてのsatに一意に識別番号Ordinalが付与されることになったことで、Ordinalに意味付けが可能となりました。
実際の紙幣でも、製造番号がキリ番だったりゾロ目だったりすると、紙幣本来の価値よりも高値で取引されることがあります。
Ordinalも同様に、いろいろな価値基準で価値を測ることができます。
Ordinal提唱者は、下記によりレアリティを定義しています。

### 周期的なイベントに含まれる　sats

ビットコインのアルゴリズム上、周期的なイベントがいくつか存在します。

* 2016ブロック（約２週間)ごとの難易度調整
    * マイニングの成功がちょうど10分程度となるようにマイニングの難易度が調整されます。
* 21万ブロック（約4年)ごとの半減期
    * 一回あたりのマイニング報酬が半分になります。

それぞれのイベントに応じて下記の通りレアリティが定義されています。

* common（コモン）
    * 普通のレアリティです。なんら珍しくありません。
    * 任意のブロック内の最初以外のsatすべてです。
    * 最終的には約2100兆個供給されます。[^7]
* uncommon（アンコモン）
    * 各ブロックの最初のsat
    * 最終的には6929999個供給されます。
    * 平均すると、25.6btcあたりに1個含まれる計算になります。
* rare（レア）
    * 難易度調整が行われたブロックの最初のsat
    * 最終的には3437個共有されます
* epic（エピック）
    * 半減期が訪れた最初のブロックの最初のsat
    * 最終的には32個が供給されます
* legendary（レジェンダリー；伝説）
    * 半減期が6回訪れると、２週間の難易度調整と重なるブロックがあります。（２４年に一度、最初訪れるのは2032年予定)
    * 最終的には5個供給されます。
* mythic（ミシック；神話）
    * ビットコインの最初の最初、ジェネシスブロックの最初のsat
    * サトシナカモトがマイニングしたsatです。
    * 全satsの中で１つしかありません。
    * おそらく誰も手に入れることはできません。

mythicを除き他は周期的に発生するイベントなので、開発者で提唱者のcaseyは、この周期的なイベントをアナログ時計になぞらえてOrdinal時計を発明しました。

https://ordinals.com/clock

* 1目盛63個分のブロックが含まれています。
* 短針が半減期(epoc)を表しています。
* 長針が難易度調整を表しています。
* 赤い長針がブロックの位置を示していて、一番上に来ると、長針が1目盛分動くようなイメージです。
* 短針と長針と目盛が重なる箇所は目盛が太くなっていて、これがlegendary satsが生まれる場所です。

uncommon以上のすべてのsatsは下記に一覧があります。

https://ordinals.com/rare.txt

### 歴史に紐づく or 特別な取引に含まれるsats

歴史に紐ずくsatにも特別な意味を持たせることが可能です。

ord.io;
https://www.ord.io/

のsatribute(satの特徴）では、上記レアリティに加え、下記のバッジを定義しています。

* Vintage
    * 最初の1000ブロック(2009年)でマイニングされたsats
* Nakamoto
    * サトシナカモトにマイニングされたsats
* First Transaction
    * 2009年1月12日、サトシナカモトからHal　Finneに初めて送金された10BTCに含まれるsats
* Palindrome
    * ordinal番号が回文になっているsats
* Pizza
    * 2010年5月22日、bitcoinによる支払いで最初の買い物（ピザ）が行われた10000BTCに含まれるsats
* block 9
    * 流通している最古のブロックに含まれるsats。8以前はナカモトのウォレットにあり、一度も動いていない。
* block 78
    * ナカモト以外（Hal Finne)によってマイニングされた最初のブロック78に含むsats


## 表記法

1satに対して多面的に捉えられるように、いくつかの表記法が定義されています。

https://ordinals.com/sat/2099994106992659

こちらをサンプルに見てみます。

* Integer notation(整数表記)
    * 2099994106992659
    * Ordinalの番号を単純に整数表記しています。
* Decimal notation
    * 3891094.16797
    * `ブロックの高さ(数)`.`そのブロックにおけるordinalの相対位置`
* degree notation
    * 3°111094′214″16797‴
    * `半減期の数（Cycle)`°`半減期内のブロックの相対高さ`′`難易度調整が行われる間のブロックの相対高さ`″`ブロック内のordinalの相対位置`
    * この表記法において各種satを表記すると下記のような形となります。(x > 0)
        * x°x′x″x‴: common
        * x°x′x″0‴: uncommon
        * x°x′0″0‴: rare
        * x°0′x″0‴: epic
        * x°0′0″0‴: legendary
        * 0°0′0″0‴: mythic
* Percentile
    * 99.99971949060254%
    * 全体供給量を100%ととした内の位置をパーセント表記しています。
* Name
    * satoshi
    * a〜zのアルファベット(26進数)で各ordinalをエンコードしています。
    * 一番最後のsat https://ordinals.com/sat/a を `a`　　とし、後ろから、順に`b, c, ..`と割り当てている `z`まできたら `aa, ab, ac ..`となります。
    * 逆順にしているのは、最初のsatがナカモトによってロックされている（動かされない）ため意味を持ちやすい短めのアルファベットの組みがナカモト以外の誰のものにもならないことを防ぐためです。
    * Nameが特別な意味を持つ単語であったりする場合もまた、人によってはレアモノとして定義されます。

## おわりに

以上が、ビットコインの最小単位であるSatoshiに通し番号をつけ、意味を持たせるOrdinal Theoryの説明となります。
これらのOrdinalに対して、デジタルデータを刻印（inscribe)してやっとNFTっぽい感じになってくるのですが、
Inscriptionに関しては技術的な知見を得ていないため、本記事ではここまでの説明に留めておきます。

また誤りや質問等ありましたらお気軽にコメントしていただけるとありがたいです。

最後まで読んでいただきありがとうございました。

### 参考

https://docs.ordinals.com/introduction.html


[^1]: Ordinal theoryの提唱者は、"NFT" というのがわかりづらいということで、"Digital Artifact" と呼んでいますが、Non-funsible　（代替不可能） という意味ではNFTといっても間違いではなく、流行語大賞にノミネートされた日本人としてはNFTのほうが馴染み深いので、BitcoinNFTと呼びます。
[^2]: satoshiの略。BitcoinCoin論文の著書がSatoshi Nakamotoであるから。
[^3]: Ordinalは日本語で序数という意味。順番のこと。
[^4]: Bitcoin Improvement Proposals; Bitcoin仕様改善提案書
[^5]: Coinbaseトランザクション(システムからマイナーへの支払い)にはInuputはありません
[^6]: 手数料等は省略してます。
[^7]: 2100万(BTC) * 1億(sats) - 他のレアリティを除くもの