Develop with pleasure!

福岡でCloudとかBlockchainとか。

Output Descriptorとscantxoutsetを使ってUTXOセットをスキャンする

Bitcoin Core 0.17.0からUTXOセットをスキャンするscantxoutsetというRPCが追加された。

Bitcoin Core :: scantxoutset (0.17.0 RPC)

今まではウォレット内に鍵を持つUTXOの情報はlistunspentなどで取ってこれてたけど、↑はウォレット機能とは別で、UTXOセットの中から指定した条件に合うUTXOを検索することができる。

この時、検索対象を指定する際に使用する記述子がOutput Descriptor↓

bitcoin/descriptors.md at 0.17 · bitcoin/bitcoin · GitHub

(訳は後述)

Output Descriptorを指定してscantxoutsetでUTXOを検索

scantxoutsetは以下のように2つの引数を取る。

$ bitcoin-cli scantxoutset <action> <scanobjects>
  • action
    実行するアクションを指定。
    • startでスキャンを開始
    • abortで現在のスキャンを打ち切り
    • statusで現在のスキャンの進捗を確認
  • scanobjects
    スキャン対象を配列で指定。各要素で指定可能なスキャン対象は今のところ以下の3つ
    • descriptor: 後述のOutput Descriptorの文字列を指定
    • ['desc': xxx, 'range': n]: (オプション)Output Descriptorとメタデータを含むオブジェクト。子HDチェーンをどこまで探索するかのインデックスを指定して検索したい場合(デフォルト:1000)

例えば、公開鍵0259f6658325c4e3ca6fb38f657ffcbf4b1c45ef4f0c1dd86d5f6c0cebb0e09520のP2PKHのUTXOを探す場合、以下のようにscantxoutsetを実行してしばらく待つと結果が得られる↓

$ bitcoin-cli -testnet scantxoutset start "[  \"pkh(0259f6658325c4e3ca6fb38f657ffcbf4b1c45ef4f0c1dd86d5f6c0cebb0e09520)\" ]" 
{
  "success": true,
  "searched_items": 20353944,
  "unspents": [
    {
      "txid": "1915bdd359feb0bb12bc4f6f1f0791b982def6936af420473f892bacd16db014",
      "vout": 1,
      "scriptPubKey": "76a9143b9722f91a2e50d913dadc3a6a8a88a58a7b859788ac",
      "amount": 0.10015556,
      "height": 1117751
    },
    {
      "txid": "e9dcfee7eb0715570cf8b3cc2149309ca4c0af3a4387f4eb92a4c04d746986ed",
      "vout": 1,
      "scriptPubKey": "76a9143b9722f91a2e50d913dadc3a6a8a88a58a7b859788ac",
      "amount": 0.46970645,
      "height": 1117751
    }
  ],
  "total_amount": 0.56986201
}

実行中は別のターミナルから↓を実行するとスキャンの進捗(%)が確認可能。

$ bitcoin-cli -testnet scantxoutset status
{
  "progress": 45
}

とこんな感じで、手軽にUTXOセットを検索できるようになったのは便利だ。

scanobjectsの指定方法は以下のようにOutput Descriptorを構成することで様々な検索が可能。

Output Descriptorの機能

以下、Output Descriptorの機能部分の訳↓

現在以下のOutput Descriptorをサポートしている。

  • pk関数を介して、Pay-to-pubkeyスクリプト(P2PK)をサポート
  • pkh関数を介して、Pay-to-pubkey-hashスクリプト(P2PKH)をサポート
  • wpkh関数を介して、Pay-to-witness-pubkey-hashスクリプト(P2WPK)をサポート
  • sh関数を介して、Pay-to-script-hashスクリプト(P2SH)をサポート
  • wsh関数を介して、Pay-to-witness-script-hashスクリプト(P2WSH)をサポート
  • multi関数を介して、マルチシグスクリプトをサポート
  • addr関数を介して、サポートされる任意のアドレスタイプ
  • raw関数を介して、RAWスクリプトのhex表記をサポート
  • hex表記の公開鍵(圧縮、非圧縮)または、BIP32拡張公開鍵と導出パス

サンプル

  • pk(0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798)は、P2PKアウトプットを表す。
  • pkh(02c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5)は、P2PKHアウトプットを表す。
  • wpkh(02f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9)は、P2WPKHアウトプットを表す。
  • sh(wpkh(03fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556))は、P2SH-P2WPKHアウトプットを表す。
  • combo(0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798)は、P2PK、P2PKH、P2WPKH、P2SH-P2WPKHアウトプットを表す。
  • sh(wsh(pkh(02e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13)))は、P2SH-P2WSH-P2PKHアウトプットを表す。
  • multi(1,022f8bde4d1a07209355b4a7250a5c5128e88b84bddc619ab7cba8d569b240efe4,025cbdf0646e5db4eaa398f365f2ea7a0e3d419b7e0330e39ce92bddedcac4f9bc)は、素の1-of-2のマルチシグを表す。
  • sh(multi(2,022f01e5e15cca351daff3843fb70f3c2f0a1bdd05e5af888a67784ef3e10a2a01,03acd484e2f0c7f65309ad178a9f559abde09796974c57e714c35f110dfc27ccbe))は、P2SHの2-of-2のマルチシグを表す。
  • wsh(multi(2,03a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c7,03774ae7f858a9411e5ef4246b70c65aac5649980be5c17891bbec17895da008cb,03d01115d548e7561b15c38f004d734633687cf4419620095bc5b0f47070afe85a))はP2WSHの2-of-3のマルチシグを表す。
  • sh(wsh(multi(1,03f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8,03499fdf9e895e719cfd64e67f07d38e3226aa7b63678949e6e49b241a60e823e4,02d7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e)))はP2SH-P2WSHの1-of-3のマルチシグを表す
  • pk(xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8)は、指定されたxpubの公開鍵部分を使った単一のP2PKアウトプットを示す。
  • pkh(xpub68Gmy5EdvgibQVfPdqkBBCHxA5htiqg55crXYuXoQRKfDBFA1WEjWgP6LHhwBZeNK1VTsfTFUHCdrfp1bgwQ9xv5ski8PX9rL2dZXvgGDnw/1'/2)は、指定されたxpubの1'/2の子鍵を使った単一のP2PKHアウトプットを示す。
  • wsh(multi(1,xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/1/0/*,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/1/0/*))は、2つのHDチェーンの対応する導出パスの公開鍵を使った1-of-2のP2WSHマルチシグアウトプットを示す。

参照

記述子はいくつかのタイプの式で構成される。トップレベルの式は常にSCRIPT

SCRIPT式:

  • sh(SCRIPT)(トップレベルのみ): 引数を埋め込んだP2SH
  • wsh(SCRIPT)(別のwshの内部であってはならない): 引数を埋め込んだP2WSH
  • pk(KEY)(どこでも可): 与えられた公開鍵P2PKアウトプット
  • pkh(KEY)(どこでも可): 与えられた公開鍵のP2PKHアウトプット(公開鍵ハッシュしか知らない場合は代わりにaddrを使用)
  • wpkh(KEY)wshの内部以外): 与えられた圧縮公開鍵のP2WPKHアウトプット
  • combo(KEY)(トップレベルのみ): pk(KEY)pkh(KEY)のコレクションのエイリアス。もしkeyが圧縮されている場合、wpkh(KEY)sh(wpkh(KEY))も含まれる。
  • multi(k,KEY_1,KEY_2,...,KEY_n)(どこでも可): k-of-nのマルチシグスクリプト
  • addr(ADDR)(トップレベルのみ): ADDRが展開されるスクリプト
  • raw(HEX)(トップレベルのみ): HEXとして16進エンコードされたスクリプト

KEY式:

  • Hexエンコードされた公開鍵(02および03で始まる場合は66文字、04で始まる場合は130文字)。
    • wpkhwshの内部では、圧縮された公開鍵のみが許可される。
  • WIFエンコードされた秘密鍵は、対応する公開鍵の代わりに同じ意味で指定できる。(BIP 32で定義されている)xpubエンコードされた拡張公開鍵もしくは、xprvエンコードされた拡張秘密鍵
    • 0以上の/NUMの非強化鍵もしくは/NUM'強化鍵のBIP 32導出パスが続く。
    • オプションで、/*もしくは/*で直接的な子どもの非強化鍵、強化鍵のステップが続く。
    • 強化鍵の導出ステップの使用には、秘密鍵の提供が必要となる。
    • 'の代わりにh suffixを使って強化導出を表すことができる。

ADDR式はサポートされている任意のアドレス:

  • P2PKHアドレス(1...から始まるbase58フォーマット)。記述子内のP2PKHアドレスは、P2PKアウトプットに使用できないことに注意すること(代わりにpk関数を使うこと)。
  • P2SHアドレス(3...から始まるbase58フォーマット、BIP 13で定義)
  • Segwitアドレス(bc1...から始まるbech32フォーマット、BIP 173で定義)

説明

単一鍵のスクリプト

実際には、単一キーの構成が多く使われ、一般にP2PK、P2PKH、P2WPKHおよびP2SH-P2WPKHが含まれる。最適ではないがもっと多くの組み合わせが考えられるP2SH-P2PK, P2SH-P2PKH, P2WSH-P2PK, P2WSH-P2PKH, P2SH-P2WSH-P2PK, P2SH-P2WSH-P2PKH。

これを記述するために、これらを関数としてモデル化する。関数pk (P2PK)、pkh (P2PKH)、wpkh (P2WPKH)は、16進表記の公開鍵を入力として受け取り、対応するscriptPubKeyを返す。関数sh (P2SH) 、wsh (P2WSH)は入力としてスクリプトを受け取り、インプットをスクリプトとして埋め込んだP2SH及びP2WSHのアウトプットを記述したスクリプトを返す。関数名は簡潔にするためp2を省略している。

マルチシグ

いくつかのソフトウェアでは、BitcoinのOP_CHECKMULTISIG opcodeに基づいてマルチシグスクリプトを使用する。これをサポートするために、multi(k,key_1,key_2,...,key_n)関数を導入する。これは提供されたn個の公開鍵の内、任意のk個の署名が必要なk-of-nのマルチシグを表す。

BIP 32導出鍵とチェーン

最新のウォレットソフトウェアやハードウェアはBIP 32(HDキー)を利用して導出した鍵を使用する。期待される公開鍵を(一般にxpubと呼ばれる)拡張公開鍵と導出パスで構成される文字列で指定することを許可することで、これらを直接サポートする。導出パスは0以上の整数の順序で構成され、それぞれオプションで'もしくはhが付き、/文字で区切られる。文字列はオプションで、非強化導出、強化導出の全ての子鍵を参照するため/*または/*'(もしくは/*h)で終わることがある。

強化導出ステップを使って公開鍵を指定する場合、対応する秘密鍵にアクセスすることなくスクリプトを計算することはできない。

秘密鍵の包含

必要な秘密鍵を一緒にスクリプトの説明を伝えることはよく役に立つ。このため、公開鍵またはxpubがサポートされている場合、代わりにWIFフォーマットもしくはxprvを提供することができる。これは強化導出ステップや、秘密鍵の材料を含むウォレット記述子のダンプなどで秘密鍵が必要な場合に便利だ。

古いウォレットとの互換性

既存のBitcoin Coreウォレットで現在サポートされているスクリプトのセットを簡単に表現するため、入力として公開鍵を受け取り、その鍵でP2PK, P2PKH, P2WPKHおよび P2SH-P2WPHスクリプトを構成する便利な関数comboが提供される。公開鍵が圧縮されていない場合、P2PKおよびP2PKHのみを構成する。