Develop with pleasure!

福岡でCloudとかBlockchainとか。

Segwitのアドレスフォーマット(BIP-142)

Segregated WitnessのアドレスフォーマットについてBIP-142に定義されてるので見てみる。

bips/bip-0142.mediawiki at master · bitcoin/bips · GitHub

仕様

新しく定義されたBitcoinアドレスは、BIP-141のSegregated Witnessで定義されているPay-to-Witness-Public-Key-Hash (P2WPKH) とPay-to-Witness-Script-Hash (P2WSH)のアドレス。そのscriptPubKeyは、OP_0に続く20バイトのハッシュ(P2WPKH)か32バイトのハッシュ(P2WSH)からなる。

新しいアドレスは既存のアドレス形式と同じ方法でエンコードされる

base58-encode:
    [1-byte address version]
    [1-byte witness program version]
    [0x00]
    [20/32-byte-hash]
    [4-byte checksum]

P2WPKHアドレスの場合、address versionがmainnetでは6(0x06)、testnetでは3(0x03)になる。 P2WSHアドレスの場合、address versionがmainnetでは10(0x0A))、testnetでは40(0x28)になる。

witness program versionは0 (0x00) から 16 (0x10)の1バイトの値で、現在BIP-141でバージョン0のみ定義されている。1〜16のバージョンは将来の拡張のため予約されている。

witness program versionに続いて各バージョン毎にユニークなプレフィックスを持つよう0x00パディングする。

パディングのあとには、P2WPKHアドレスの場合は20バイト、P2WSHアドレスの場合は32バイトのプログラムハッシュが続く。

続いてそのデータをシリアライズしたデータをSHA256でダブルハッシュした最初の4バイトをチェックサムにする。

この方法で生成されたアドレスは一定の長さを持つ(20バイトの場合は36桁、32バイトの場合は53桁)。

異なるwitness program versionsはそれぞれ以下の表のようにユニークなプレフィックスを持つ。

f:id:techmedia-think:20160301143156p:plain

論拠

BIP-141ではwitness programをエンコードする2つの方法を定義する。

  • ネイティブwitness programの出力は、witness programに続いてversion byteをプッシュしたscriptPubKeyである。
  • Segwit-in-P2SHは、(scriptPubKeyが通常のP2SHの出力のように見えるが)witness programに続いてversion byteをプッシュしたBIP-16のP2SH redeemScript である。

BIP-13のP2SHアドレスが2012年に定義されているので、segwit-in-P2SHを使う分には、既存のほとんどのウォレットは何のアップデートをする必要もなくsegwit互換のウォレットであると言える。しかしこの方法はより多くのブロックスペースを必要とするため移行をスムーズにするための短期的な解決策である。最終的には全てのユーザが支払いの主な方法として効果的なネイティブwitness programを使うことが期待される。

Bitcoinアドレスの欠点はBIP-13で広く議論されており、より良い支払い方法が提案されてきた。例えば、

  • BIP47 Reusable Payment Codes for Hierarchical Deterministic Wallets
  • BIP63 Stealth Addresses
  • BIP70 Payment protocol

しかしこれらはどれもエンドユーザに広く採用されてはいない。P2WPKHとP2WSHアドレスフォーマットの提案はwitness programを採用するための最も簡単な方法と考えられており、ブロックチェーンの容量をスケーリングする状況において特に重要となる。

P2WPKHアドレスが単一の公開鍵への簡単な支払いのために使われるのに対し、P2WSHアドレスはBIP-13のP2SHアドレスのように任意の複雑なsegwit取引を可能にする。

互換性

この提案には下位互換性は無いが、古い実装では新しいアドレスタイプが無効と判断され、トランザクションの作成が拒否されるだろう。

この提案は、20バイトと32バイトのwitness programsの将来のバージョンとの上位互換性がある。

以下の公開鍵に対し

0450863AD64A87AE8A2FE83C1AF1A8403CB53F53E486D8511DAD8A04887E5B23522CD470243453A299FA9E77237716103ABC11A1DF38855ED6F2EE187E9C582BA6

P2PKHテンプレートとしてエンコードすると

DUP HASH160 <010966776006953D5567439E5E39F86A0D273BEE> EQUALVERIFY CHECKSIG

となり、対応するBitcoinアドレスは

16UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM

となる。

同じ公開鍵をP2WPKHとしてエンコードすると、scriptPubKeyは、

 OP_0 <010966776006953D5567439E5E39F86A0D273BEE>

となり、address versionとして0x06(mainnet)を使い、witness program versionとして0x00を付加し0x00でパディングしたP2WPKHアドレスが

p2xtZoXeX5X8BP8JfFhQK2nD3emtjch7UeFm

となる。

参照実装

github.com

以上がSegwitのアドレスについて。

実際にアドレスを算出してみる

bitcoin-rubyを使って実際に↑の例のP2WPKHアドレスを算出してみた。

require 'bitcoin'
include Bitcoin::Util

address_version = "06"
wp_version = "00"
padding = "00"

pubkey = '0450863AD64A87AE8A2FE83C1AF1A8403CB53F53E486D8511DAD8A04887E5B23522CD470243453A299FA9E77237716103ABC11A1DF38855ED6F2EE187E9C582BA6'

pubkey_hash = hash160(pubkey)
hex = address_version + wp_version + padding + pubkey_hash
address = encode_base58(hex + checksum(hex))

な感じで算出できる。

ちなみにbitcoin-rubyはまだsegwitへの対応はされてないみたい。