Contact

【CTO Tech Blog】 OP_CATを使用したPoWベースの分散型Faucet

  • CTO Tech blog

少し前にAnthony TownsがDalving Bitcoinに投稿した、OP_CATを用いてPoWの検証をすることで、分散型のFaucetを実現する提案が面白かった↓

https://delvingbitcoin.org/t/proof-of-work-based-signet-faucet/937

OP_CATを使用したPoWの検証

まだBitcoinに導入されていない機能をsignet上でテストするための実装Bitcoin Inquisitionを使用すると、現在signet上でOP_CAT opcodeを利用できる。OP_CATの仕様については以前の記事参照。

単純なPoWの検証

OP_CATを使用してPoWの検証をする単純なロックスクリプトは↓

<000000> OP_CAT OP_SWAP OP_SHA256 OP_EQUALVERIFY

000000の部分はハッシュ値の先頭の値で、ここではハッシュ値の先頭の値がこの値で始まることを強制する。

このスクリプトをアンロックするためには、以下のアイテムを提供する必要がある。

<nonce>
<000000の後に続くハッシュ値の残り>

このアイテムをスタックにプッシュしてロックスクリプトを実行すると、

  1. 000000の後に続くハッシュ値の残り000000OP_CATで連結され、スタックにプッシュされる。
  2. スタック上で1のデータとnonceの位置を入れ替える。
  3. OP_SHA256nonceのSHA256値をスタックにプッシュする。
  4. 4のハッシュ値と1のデータが等しいか検証する。

ユーザーは、000000が続く目的にハッシュ値を生成するnonceを見つければアンロックできる。

nonce再利用の対処

↑のままだと、難易度が同じ↑のロックスクリプトがオンチェーン上で一度でもアンロックされると、そのnonceを使いまわしてPoWを回避できてしまう。そこで、↑のnonceの値に署名データを利用することでnonceの再利用をできなくする。

具体的には、nonceの値を

x || 署名 || y

のように3つのデータを連結した値にし、その署名データを複製しさらにOP_CHECKSIGで検証させるようにする。この署名検証の公開鍵は任意の公開鍵でよくwitnessの要素として提供すればいい。

署名データはトランザクションにコミットしているので、別のトランザクションで同じ(x, 署名, y)のデータを使いまわすと、署名検証の際にエラーとなる。署名がトランザクション全体にコミットしていることを保証するために、署名データのサイズが64 byteであることをチェックするとより堅牢になる*1

Bitcoinのマイニング機器との互換性

Anthony Townsの提案では、Bitcoinのマイニング機器のPoWとの互換性を持たせるよう、x || 署名 || yが80 byteとなるように調整している。80 byteというのはBitcoinのブロックヘッダーと同じサイズで、このデータに対してdouble-SHA256を計算するのがマイニングだから。具体的にはxを4 byte、yを12 byteとしている。これをブロックヘッダーとして解釈すると、

  • xは、ブロックのバージョン
  • 署名は、前のブロクのハッシュと、ブロック内のトランザクションから計算したマークルルート
  • yは、タイムスタンプと難易度、nonce

に該当する。

Bitcoin Coreではbitcoin-utilという実行ファイルが提供されおり、

$ bitcoin-util grind <x || 署名 || y>

のようにgrindコマンドを実行すると、yの中で指定された難易度をクリアするPoWの計算を行い、有効なnonceを含む値をブロックヘッダーとして返してくれる。つまり、既存のマイニングツールを使ってFaucetのコインを入手するためのPoWの計算ができる。

Faucetのロックスクリプト

実際にsignet上のアドレスtb1pffsyra2t3nut94yvdae9evz3feg7tel843pfcv76vt5cwewavtesl3gsphにコインがロックされており、PoWによりそのコインを入手しているトランザクションが↓

25deff74b7775918aa6824cfeab9121a519fb419d31ea74f6cb6a53f98cc863a

実際に提供されているスクリプト(Tapscript)はもう少し複雑で、設定された難易度によって相対的なタイムロックが付与されるようになっている。つまり、Faucet用にロックされているコインをアンロックする際、より難易度が高いPoWを行うほどすぐにアンロックができるようになっている。

こういった分散型のFaucetだと、既存のFaucetみたいにウェブサイトをホスティングする必要がないのが便利ね。

*1:Taprootでsighash typeを省略した64 byteの署名は、SIGHASH_ALLとして扱われるため

本記事の元ページ

https://techmedia-think.hatenablog.com/entry/2024/12/24/182150

話題のキーワード