著者:@hicaptainz
ここ2週間、私はBTCエコシステムやさまざまなインスクリプションプロジェクトを調査していて、原理や技術的詳細を明確に説明している記事が非常に少ないことに気づきました。たとえば、インスクリプションの作成時にトランザクションはどのように開始されるのか、UTXO内のsats(サトシ)はどのように追跡されているのか、刻印された内容はスクリプトのどこに保存されるのか、BRC20の送金時になぜ2回の操作が必要なのか、といった点です。これらの技術的詳細を理解しない限り、BRC20、BRC420、Atomicals、Stamps、ルーン(Runes)などの各種プロトコルの違いを正しく理解することは難しいでしょう。本稿では、BTCブロックチェーンの基礎知識まで踏み込み、上記の疑問に答えていきます。
BTCのブロック構造
ブロックチェーンの本質は、複数ユーザーによる台帳技術であり、コンピュータサイエンスの用語で言えば分散型データベースです。一定期間内の記録(取引)がひとつの「ブロック」を形成し、時間順に連なって台帳が拡張されていきます。

Excelを使ってブロックチェーンの動作原理を説明します。1つのExcelファイルが1つのブロックチェーンを表しており、各シートが個々のブロックです。ブロックは時間順に560331、560332…から最新の560336まで並んでいます。560336番目のブロックには、直近の取引が詰め込まれます。ブロックの中核部分は会計分野でよく知られる複式簿記であり、片方のアドレスを借方(debit)としてinputs from、もう片方のアドレスを貸方(credit)としてoutputs toと記録します。ValueはそれぞれのアドレスにおけるBTC数量に対応します。InputsのBTC総量はOutputsより多くなり、その差額がユーザーが支払う手数料、すなわちマイナー(記帳人)の報酬となります。ブロックヘッダーには、前ブロックの高さ、前ブロックのハッシュ値、当該ブロックの生成時刻(タイムスタンプ)、およびナンスが含まれます。この去中心化された台帳技術において、誰が次のブロックの記帳権を得るのでしょうか? その鍵となるのが、このナンスとそれに対応するハッシュ値です。計算能力を持つマイナーが、現在のブロックのナンスに対してハッシュ計算を行い、条件を満たすハッシュ値を最初に得たマイナーが次ブロックの記帳権を獲得し、ブロック報酬と手数料を得ます。最後にスクリプト領域ですが、これには拡張アプリケーションのための情報が置かれます。たとえばop_returnというスクリプト命令は「備考欄」として利用可能です。ただし実際のブロックでは、スクリプト領域はinputやoutput情報に付随しており、独立した別領域があるわけではありません。inputに付随するスクリプトは「アンロックスクリプト(ScriptSig)」と呼ばれ、ウォレットアドレスの秘密鍵による署名が必要で、出金許可の役割を果たします。一方、outputに付随するスクリプトは「ロックスクリプト(ScriptPubKey)」と呼ばれ、受け取ったBTCを使用できる条件を設定します(通常は「対応する秘密鍵を持つ者だけが使用可能」という条件です)。


上記2枚の図は、元のinputとoutputのデータ構造を示しています。実行レベルでは、スクリプトは取引情報に付随するパラメータとして現れます。その中でも、秘密鍵による承認が必要なアンロックスクリプト(ScriptSig)は「証人データ(witness data)」とも呼ばれます。
隔離型証人(SegWit)とTaproot
ビットコインネットワークは10年以上稼働していますが、取引コストが極端に高騰し、実用性が損なわれる事態が何度も発生しました。そのため、開発者たちは今後増加する取引量に対応するために、ネットワークをどのようにスケーリングすべきかを長年議論してきました。
2017年、この議論は頂点に達し、ビットコイン開発コミュニティは二つの陣営に分裂しました。一方はソフトフォークで導入される「SegWit(隔離型証人)」を支持する派閥、他方は直接的なブロックサイズ拡大を主張する「大ブロック派」でした。
前述したように、アンロックスクリプトには秘密鍵による署名が必要な「証人データ」が含まれます。もしこの証人データをブロックから分離すれば、結果的に各ブロックが処理可能な取引数を増やすことができませんか? 「隔離型証人(Segregated Witness)」は2017年8月に正式に有効化されました。その実装方法は、すべての取引データを2つに分け、一つは取引の基本情報(Transaction Data)、もう一つは署名情報(Witness Data)とし、後者を新しいデータ構造に格納して、オリジナルの取引とは別に伝送するというものです。これが「証人(witness)」と呼ばれる新たなブロック領域です。

技術的には、SegWitにより、取引自体に証人データを含める必要がなくなりました(つまり、ビットコインが当初ブロックに割り当てていた1MBの容量を消費しなくなります)。代わりに、ブロック末尾に証人データ専用の独立した空間が設けられ、任意のデータ転送が可能になり、かつ「ブロック重量(block weight)」という割引ルールが適用されます。これにより、大量のデータをビットコインのブロックサイズ制限内に巧妙に収めることができ、ハードフォークを回避しながら、取引データの上限を引き上げ、署名データの手数料を削減できます。SegWit導入前はビットコインの容量上限は1MBでしたが、SegWit後は通常の取引部分の上限は依然1MBですが、隔離型証人領域の容量は最大4MBまで拡大されました。
Taprootは2021年11月に導入され、3つの異なるビットコイン改善提案(BIP)から構成されています。これらはTaproot、Tapscript、および「Schnorr署名」と呼ばれる新しいデジタル署名方式です。Taprootは、ビットコインユーザーにとって取引の秘匿性向上や手数料の低下といった多くの利点をもたらすことを目的としています。また、より複雑な取引を可能にすることで、応用範囲を広げます(新たなオペコードopcodesが追加されました)。
これらのアップデートは、Ordinals NFTの重要な推進力となりました。NFTデータはTaprootのスクリプトパスの支出スクリプト(spent script)—つまり証人データ領域—に保存されます。今回のアップデートにより、構造化された任意の証人データの保存が容易になり、「ord」標準の基盤が築かれました。データ要件が緩和されたことで、ある取引が自身の取引データと証人データでブロック全体を埋め尽くすことが可能になり(証人データ領域の4MB上限まで)、ブロックチェーン上に保存可能なメディアの種類が大幅に拡大しました。
ここで疑問が湧くかもしれません。「スクリプトに文字列を入れるなら、その文字列に制限はないのか? もし本当にそのスクリプトが実行されたらどうなるのか? 適当な内容を放り込んだら、バグコードになってブロック拒否されたりしないのか?」 これに対する答えはOP_FALSE命令です。ビットコインスクリプトにおけるOP_FALSE(「0」としても表記される)は、スクリプト実行パスが決してOP_IF分岐に入らないようにし、未実行状態を維持します。これはスクリプト内のプレースホルダまたは空操作(No Operation)として機能し、高級言語における「コメント」と同様に、後続のコードが実行されないことを保証します。

UTXO送金モデル
ここまでで、コンピュータのデータ構造の観点からBTCの基本原理を解説してきました。次に、金融モデルの観点からUTXOモデルについて考察します。
UTXOはUnspent Transaction Outputsの略で、日本語では「未使用取引出力」と訳され、実際には送金時に残った未使用資金を意味します。なぜビットコインはこのような概念を使うのでしょうか? これは、台帳方式における「アカウントモデル」と「UTXOモデル」の違いに由来します。
私たちは中央集権的なシステムに長く慣れ親しんできたため、アカウント残高モデルでの記帳方法に非常に慣れています。ユーザーAがユーザーBに100円を送金する場合、銀行はまずAの口座に100円以上あるかを確認し、あればAの口座から100円を引き、Bの口座に100円を加算することで、送金を完了させます。
しかし、ビットコインの台帳アルゴリズムには「残高」という概念がありません。ブロックチェーンの分散型台帳に記録されるのは一連の取引のみであり、アカウントの現在残高は直接記録されません(残高を記録するには専用のサーバーノードが必要となり、それは中央集権的になります)。仮にユーザーAの残高が1000円だとしましょう。AがBに100円を送金すると、この取引は以下のように記録されます:
取引1:ユーザーAがユーザーBに100円を送金
取引2:ユーザーAがユーザーA自身に900円を送金(UTXO)

この取引2は一見取引ですが、機能としては残高の役割を果たしており、100円の送金後、Aのアカウントに900円が残っていることを示しています。
では、なぜこのようなUTXOをわざわざ作るのでしょうか? ビットコインブロックチェーン上では取引しか記録できず、アカウント残高は記録できないからです。もしUTXOがなければ、残高を計算する際に、あるアカウントのすべての入金・出金取引を合計する必要があり、これは非常に時間と計算資源を消費する作業です。UTXOの登場により、残高計算のためにすべての取引を遡るという問題が巧妙に回避されました。
UTXOには特徴があります。それは硬貨と同じで、分割できないということです。では取引中に必要な金額をどうやって集め、お釣りはどのように出すのでしょうか? 硬貨に例えるとわかりやすいでしょう(実際にUTXOという単語を見るたびに、自動的に「硬貨」と訳すと良いでしょう)。
明くんが剛くんに1ビットコインを送金するとします。このとき、明くんは十分なinput(入力)を集める必要があります。たとえば、明くんのアドレスに関連する過去の取引から、0.9の価値を持つUTXOを見つけましたが、1ビットコインには足りません。幸いにも、取引には複数の入力が許可されているため、明くんはさらに0.2の価値を持つUTXOを見つけました。この送金取引には2つの入力が含まれます。出力も2つあり、1つは剛くんのアドレスに向けられ、価値は1ビットコインです。もう1つは明くん自身のアドレスに戻り、価値は0.1ビットコインで、これがお釣りです(この例ではガス手数料は無視しています)。
言い換えれば、明くんのポケットには0.9と0.2の2枚の硬貨があり、1の価値の支払いをするために、両方を剛くんに渡します。剛くんはそれを受取り、0.1のお釣りを明くんに返します。この記帳モデルの本質は、「お釣り」の操作によって「残高計算」を回避することにあるのです。
Ordinalプロトコルの番号付けシステム
Ordinalプロトコルは、今回のBTCエコシステム爆発の源流と言えます。均質なBTCを最小単位であるsatに分解し、各satに番号を付ける仕組みです。どのように行われるのでしょうか?
ご存じの通り、BTCの総量は2100万枚で、1BTCは1億分割(sat)まで細分化できます。したがって、BTCの最小単位はsatであり、これらBTCや最小単位satは典型的な均質トークン(FT)です。ここで、これらのsatsに序数(ordinal)を割り振ってみましょう。
ブロックデータ構造について述べた際、取引情報にはinputのアドレスと金額、outputのアドレスと金額を明記する必要があると述べました。各ブロックには2種類の取引が含まれます。1つはBTCのブロック報酬、もう1つは取引手数料です。手数料の取引にはinputとoutputが存在しますが、ブロック報酬は新たに生成されたBTCであるためinputアドレスが存在せず、「input from」フィールドは空白になります。これを「coinbase取引」と呼びます。BTCの2100万枚すべてはこのcoinbase取引から生まれ、すべてのブロック内で取引リストの先頭に位置します。
Ordinalプロトコルの規定は以下の通りです:
-
番号付け:各satは採掘された順に番号が付けられる
-
移転:FIFO(先入れ先出し)ルールに従い、取引のinputからoutputへと移転される
1つ目のルールは比較的単純です。これにより、番号付けは採掘報酬であるcoinbase取引でのみ生成されることになります。たとえば、最初のブロックの報酬が50BTCであれば、最初のブロックには[0;1;2;...;4,999,999,999]の範囲のsatsが割り当てられます。2番目のブロックの報酬も50BTCであれば、2番目のブロックには[5,000,000,000;5,000,000,001;...;9,999,999,999]の範囲のsatsが割り当てられます。

理解が難しいのは、UTXOは多数のsatsを含むため、それらのsatsは見た目が同じなのに、どうやって順番を付けるのかという点です。これは実は2つ目のルールが決定しています。簡単な例を挙げます:
まず、BTCの最小分割単位を1と仮定し、10ブロックが生成され、各ブロックの報酬が10BTC、つまり総量100BTCだとします。この100BTCに(0-99)の番号を直接付けることができます。もし何も送金がなければ、1ブロック目の10BTCの番号は(0-9)、2ブロック目の10BTCは(10-19)、…、10ブロック目の10BTCは(90-99)とわかります。ここで、出費(output)がないため、output自体が存在せず、10BTCごとに番号範囲しか与えられないことになります。
ここで2ブロック目に2つの出費を加えます。1つは3BTC、もう1つは7BTCの「お釣り」です。これは他人に3BTCを送金し、自分に7BTCをお釣りとして戻す取引です。このとき、ブロックの取引リスト内で、自分に返す7BTCが1番目(対応する番号は10-16)、他人に送る3BTCが2番目(対応する番号は17-19)とします。こうして、outputの移転を通じて、特定のUTXOに含まれるsatsの順序集合が確定します。
注意すべきは「各sat」であって「UTXO」ではないことです! UTXOは分割不可能な最小取引単位であるため、satはUTXOの中にしか存在できません。また、UTXOはある範囲のsatsを包含し、そのUTXOを消費して新しい出力を生成する際にのみ、satsの番号を再分割できます。
この「番号」を表現する方法については、Ordinalは複数の形式をサポートしています。前述の「整数法」のほか、10進小数法、度数法、パーセンテージ法、純アルファベット命名法などがあります。

satsに統一された序数が付いた後、インスクリプション(刻印)を考えることができます。前述したように、最大4MBの隔離型証人領域にテキスト、画像、動画など任意のデータタイプのファイルをアップロードでき、アップロード後、ファイルは自動的に16進数に変換され、Taprootスクリプト領域に保存されます。つまり、1つのUTXOが1つのTaprootスクリプト領域に対応し、そのUTXOは多数のsatsを包含します(全体としてsatsの連続集合です。粉塵攻撃を防ぐため、単一UTXO内のBTC量は546 sat未満であってはなりません)。Ordinalプロトコルでは記録を簡便にするため、意図的に「この集合の最初のsat番号をバインド関係として使用する」と規定しています(白書の原文は「最初のoutputの最初のsatの番号」)。たとえば、(17-19)番のsatsを含むUTXOは、17番でこの集合と刻印内容を紐付けます。
Ordinal資産の発行と移転
Ordinal NFTは明らかに、様々なファイルを隔離型証人のスクリプト領域にアップロードし、それにsatsの連続集合をバインドすることで、BTCチェーン上でNFT資産を発行する仕組みです。しかし、もう1つ疑問があります。隔離型証人のスクリプト領域にはinputのアンロックスクリプトとoutputのロックスクリプトの両方が含まれますが、内容はどちらのスクリプトに置かれるのでしょうか? 正解は「両方に含まれる」です。ここで、ブロックチェーン技術におけるcommit-reveal(コミット・リヴェール)メカニズムに触れる必要があります。
ブロックチェーンのCommit-Revealメカニズムは、情報の公平性と透明性を確保するためのプロトコルです。このメカニズムは、投票や入札のように、非公開情報を提出し、後にその情報を開示する必要がある場面でよく使われます。Commit-Revealメカニズムは2段階に分かれます:コミット(Commit)段階とリヴェール(Reveal)段階です。
1. コミット段階:この段階で、ユーザーは自分の情報(投票選択や入札価格など)を提出しますが、その情報は暗号化されています。通常、ユーザーはその情報のハッシュ値(情報の暗号化ダイジェスト)を生成し、それをブロックチェーンに送信します。ハッシュ関数の特性により、一意の出力(ハッシュ値)が生成され、元の情報から逆算できないため、提出時の情報の機密性が保たれます。
2. リヴェール段階:予め決められた後の時点において、ユーザーは元の情報を開示し、それが以前に提出したハッシュ値と一致することを証明しなければなりません。これは通常、元の情報とハッシュ値生成に使用した追加データ(乱数や「ソルト」)を提出することで行われます。ネットワークは、その元情報のハッシュ値が以前に提出したものと一致するかを検証します。一致すれば、元の情報は有効とみなされます。
前述したように、刻印内容はUTXOに含まれるsats連続集合とバインドされる必要があります。UTXOはブロック内でoutputにあたりますので、必然的にoutputのロックスクリプトに付随しなければなりません。しかし、BTCのフルノードは、ネットワーク全体のUTXO集合をローカルで維持・伝送する必要があります。もし1万個の4MBの動画ファイルを1万個のUTXOのロックスクリプトに直接アップロードしたら、すべてのフルノードが非常に高い記憶容量と超高速のネット接続を必要とし、チェーンは即座に崩壊してしまうでしょう。そのため、唯一の解決策は、内容をinputのアンロックスクリプトに置き、その内容が別のoutputを「指し示す」ようにすることです。
したがって、Ordinal資産の発行は2ステップに分かれます(ウォレットはこの2ステップを統合処理しています。取引構築時に、同時にコミット・リヴェールの親子取引を構築するため、ユーザー体験上は1ステップに感じられ、ガス手数料も節約できます)。
発行段階では、ユーザーはまず、あるファイルのハッシュ値をコミット取引(自身のAアドレスからBアドレスへの送金)のUTXOのロックスクリプトにアップロードします。ハッシュ値であるため、フルノードのUTXOデータベース空間をあまり消費しません。次に、ユーザーは新しい取引(自身のBアドレスからAアドレスへの送金)を構築します。これをリヴェール取引と呼びます。このときのinputは、前のステップのコミット取引でハッシュ値を含むUTXOを使用し、そのinputのアンロックスクリプトには、元の刻印ファイルを含めなければなりません。白書の原文で言えば、「まず、コミットで、銘文内容を含むスクリプトへのtaproot出力を作成する。次に、リヴェール取引で、コミット取引の出力を使用して、チェーン上の銘文内容を表示する。」
移転段階では、Ordinal NFTとBRC20には少し違いがあります。Ordinal NFTは全体移転のため、バインドされたUTXOのNFTを受取人に直接送るだけで済み、通常のBTC送金と似ています。しかし、BRC20はカスタム数量の送金を伴うため、やはり2ステップに分かれます。1ステップ目は「取引」のインスクリプション(Inscribe "TRANSFER")、2ステップ目は送金「取引」(Transfer "TRANSFER")です。1ステップ目のインスクリプション取引は、実際にはOrdinal NFTの発行プロセスと類似しており、暗黙的にコミット・リヴェールの親子取引ペアを含んでいます。2ステップ目の送金取引は、通常のOrdinal NFTの移転に似ており、バインドされたUTXOのBRC20資産を受取人に直接送ります。一部のウォレットは、この3つの取引(親・子・孫の三代取引)を同時に構築し、時間を節約し、ガスを削減します。

まとめると、コミット取引は刻印内容(元内容のハッシュ値)と番号付きsats(UTXO)をバインド















