【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の後に続くハッシュ値の残り>
このアイテムをスタックにプッシュしてロックスクリプトを実行すると、
000000の後に続くハッシュ値の残り
と000000
がOP_CAT
で連結され、スタックにプッシュされる。- スタック上で1のデータと
nonce
の位置を入れ替える。 OP_SHA256
でnonce
のSHA256値をスタックにプッシュする。- 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として扱われるため