暗号通貨に関する事など

暗号通貨に関する覚書など。メモや日記。

※技術的なことに関して、間違っていたらコメントから指摘していただけると泣いて喜びます

Segwitに関して調べた記録6


前回の続き



Segwitで採用される新しいアドレスフォーマット(はじめに)

 その送金先がSegwitアドレスであることを示す為のアドレスフォーマットについてここでは書く。


 Segwitのアドレスフォーマットは元々BIP-142に定められていたのだが、後にそれを上書きするものとして、BIP-173が提案された。


 BIPは提案なので、実際にBitcoinがSegwitを導入できていない今、BIP-142とBIP-173のどちらが採用されることになるかは、正直わからないのだが、先にSegwitを導入しているLitecoinを見るに、BIP-173が採用される確率が高いと思うので、BIP-173について書く。


 LitecoinではBIP-173の導入を決定しているようで、次の大きなバージョンアップの時に導入するとかしないとか(現時点で導入はされていない)


https://github.com/litecoin-project/litecoin/issues/312
(何かその辺りの会話してるね・・・)



BIP-173


 GithubにアップされたBIP-173はこちら


 BIP-173はSegwitのアドレスフォーマットを定めたもので、大まかな流れは以下のとおりである

  1. witnessProgramにhuman-readable partと呼ばれるデータを付ける
  2. 1のデータに間違い検証用のデータである"チェックサム"を付ける
  3. 2のデータ部分をBIP-173で定められた方法で32文字を使用したデータにエンコードする

 では、まず最初にBech32から説明していく。



Bech32

 BIP-173では、Base58を用いたレガシーなアドレスエンコードに対して、Bech32と呼ばれるエンコードを提案している。


 このBech32は、「human-readable part(人が読む部分)」と「data part(データ部分)」とに分かれており、それらを区切るものとして「separator(セパレーター)」と呼ばれる特定の文字を使用する。



 各パートの意味するところは上記図を見て欲しい。セパレーターは「1」で固定されており、もし、human-readable partに1が複数回出てくる場合は、その一番後ろのものをセパレーターと認識する。(Bech32エンコード後のdata partには1は使われない)


 data part(以下 "データ部分")はバイナリデータをBech32で定められる32文字のデータでエンコードされる。


 ここで注意しておきたいのが、Bech32に使われる文字表は通常のBase32と文字の並びが違うということだ。実際にはBIP-173にかかれている表を見て欲しいが、通常のBase32が「a,b,c...」と始まるところを「q,p,z...」となっている。


BIP-173より引用

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

 都合上表にしているだけで、単に連なった32文字だと思えば良い。(q,p,z...x,8,g,f...)


 次に、チェックサムについて説明をする。



チェックサム

 チェックサムはデータ部分に含まれる。


 チェックサムは、下記Pythonで書かれたコードの「bech32_verify_checksum」メソッドがtrueを返すことでその検証が成功したものとみなす。

BIP-173より引用

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

 生成に関しては、下記Pythonのコードに従って生成を行う。

BIP-173より引用

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

 この辺りのプロセスは実際にコードを読んでその手順を追って欲しい。


 BIP-173にもその説明が簡単にされているが、この計算は「BCH符号」と呼ばれるデータの符号化の計算として最も研究がされているものの一つを利用した計算のようだ。



Sgwitのアドレスフォーマット

 以上を踏まえて、Segwitのアドレスフォーマットに関わる規則は下記のとおりとなっている。


■human-readable part
 各通貨に依る(Bitcoinであればbc,Litecoinであればltcなど)


■data part
 1文字目はwitnessVersionになる。
(version0だと上記で引用した表より"q"となる)


 残りのwitnessProgramとチェックサムの部分は0と1のバイナリデータとして見て5bit毎に区切り(端数はパディングする)、それらを表に記された32個の文字に当てはめていく。
(2の5乗は32なので、5bit毎に区切れば32個の文字列に当てはめることが出来る)


 BIP-173のサンプルを見ると分かるが、例えば"Bitcoin(mainnet)"の"version0"の"WitnessProgram"のアドレスは、必ず「bc1q」から始まる。この時、"bc"がhuman-readable partで"1"がseparator、"q"がversion0の"0"を示している。この後に、witnessProgramとチェックサムを32文字でエンコードした文字が続く。



このパートの最後に

 以上がBIP-173で定められた新しいアドレスフォーマットの詳細になる。正直、実際に自分で実装してみないと分からないと思う。サンプルもあるので実際に自分で生成したほうが良いと思う。また、実装しているうちに新たにわからないところが出てくると思う。(私はそもそもBCH符号化の操作に関してその根拠がよく分かっていない)


 なんだか良く分からないチェックサムの計算だが、SHA-256doubleHashしたデータの頭4byteを抜き出すよりは素早く、より厳密に間違い検証が出来るようだ。


 また、定義が曖昧になってしまったがBech32は表で指定された32文字を用いたデータのエンコードそのものを指すのではなく、チェックサムの計算方法やアドレスフォーマットなど、BIP-173で定められた全ての操作をまとめてBech32と呼ぶようなので、注意して欲しい。



最後に(全体的に)

 今回を含む全6回分の記事に書いてあることがSegwitについて私が調べたことだ。なので今回でおわり。


 正直後半は息切れしながら書いたので説明が雑になってしまったがまぁ仕方ない。

仮想通貨NEM 触って楽しいAPIのお話

はじめに

 仮想通貨NEMにはAPIと呼ばれる機能がついており、それによって誰でも簡単にブロックチェーンの力を得ることが出来る。今回はそのことについて書く。



APIとは

 そもそもAPIとは何なのか。


 APIとは、「アプリケーション・プログラミング・インターフェース(Application Programming Interface)」の略で、本来の意味としてはソフトウェア同士がデータをやり取りするための窓口とそれを使うための取説、仕様全般を指すのだが、取引所やツイッターなどで目にするAPIは意味がすこし狭くなっていて、「インターネットを通じてサーバーとデータのやり取りをする為の窓口」だと思えば良い。


 APIを利用することで得られる恩恵は何か。例えば取引所であれば、通常ブラウザを使って取引所にログイン後、手動で売り買いをしなくてはいけないところ、APIを利用することで、ブラウザを使わなくても取引所のサーバーと直接データのやり取りが可能になり、自作のソフトを作って取引することや、さらには自動で売買を行うプログラムを作ってプログラムに売買を任せることが出来るようになる。



NEMのAPI

 では、NEMのAPIでは何が出来るのか。基本的にNEMに出来ることはAPIで何でも出来る。聞くより使ってみたほうが早いと思うので実際に使ってみよう。


【下のいずれかのURLをクリック!(別窓開きます)】
http://45.76.107.205:7890/heartbeat
http://153.122.13.168:7890/heartbeat
http://160.16.181.49:7890/heartbeat


 クリックすると、下記のようななんだか良く分からない記号と英数字の羅列が出てきたのではないだろうか。(出てこなかったら通信失敗。別のURLを試そう)

{"code":1,"type":2,"message":"ok"}

 で、このURLと謎の記号と英数字の羅列は何なんだという話だが、まず、URLについて、一番上のURLを使って解説しよう。



URL構造

 これはNEMではなくてウェブの話になるが、URLをクリックするということは、下記のリクエストをインターネットに送ったということを意味する。

 これを役所の手続きで例えるとこんな感じになる。

 今回のリクエストでは45.76.107.205の住所にあるノードの7890番の窓口にハードビートリクエストを送ったことになる。



ハートビートリクエスト

 では送った"ハートビートリクエスト"とは何か?ハートビートを直訳すると「心臓の鼓動」で、このハートビートリクエストではリクエスト先のノードが生きているか、死んでいるか(サーバーがダウンしていないか)確認するためにある。


 リクエストを送ってノードから返ってきた答えは次のように読むことが出来る。

 code:1が何を示すのか、などは、APIリファレンス(APIの取説)を読むとわかる。
 (APIリファレンス(英文):http://bob.nem.ninja/docs/


 何となくイメージが掴めただろうか?やっていることはAPIで定められたフォーマットでリクエストを送って、その返信を受け取る作業だ。まさに役所の手続きのようなもの。


 手続きの一覧(利用可なリクエストやリクエストを送る時のフォーマットなど)はAPIリファレンスに載っている。



アドレスの中身を確認するリクエスト

 では続いて、アドレスの中身を確認するリクエストを送ってみよう。
 今回は「NB7J657L7TBNKXOGXQJVP5VEKQODTDZORPW3ZF3Y」のアドレスの中身を覗いてみる。NEMのブロックチェーンは公開台帳なので、誰でもその中身を覗くことが出来る。


【下のいずれかのURLをクリック!(別窓開きます)】
http://45.76.107.205:7890/account/get?address=NB7J657L7TBNKXOGXQJVP5VEKQODTDZORPW3ZF3Y


http://153.122.13.168:7890/account/get?address=NB7J657L7TBNKXOGXQJVP5VEKQODTDZORPW3ZF3Y


http://160.16.181.49:7890/account/get?address=NB7J657L7TBNKXOGXQJVP5VEKQODTDZORPW3ZF3Y


 正常に通信ができていてば、以下のように画面に表示されているはず。

{"meta":{"cosignatories":[],"cosignatoryOf":[],"status":"LOCKED","remoteStatus":"REMOTE"},"account":{"address":"NB7J657L7TBNKXOGXQJVP5VEKQODTDZORPW3ZF3Y","harvestedBlocks":0,"balance":0,"importance":0.0,"vestedBalance":0,"publicKey":"5b82a2d4eb135875465c977adad22260e5c7bd62051709a3d1dedc1809a8057c","label":null,"multisigInfo":{}}}

 さっきのハートビートリクエストよりも複雑だが、基本的には読み方は同じだ。各ステータスの結果の意味はリファレンスを見ながら読んでいくことになる。


 各ステータスが示す細かい話は置いていおて、とりあえずこのアカウントにどれだけのxemが入っているかを確認するには、次の場所を確認すれば良い。

{"meta":{"cosignatories":[],"cosignatoryOf":[],"status":"LOCKED","remoteStatus":"REMOTE"},"account":{"address":"NB7J657L7TBNKXOGXQJVP5VEKQODTDZORPW3ZF3Y","harvestedBlocks":0,"balance":0,"importance":0.0,"vestedBalance":0,"publicKey":"5b82a2d4eb135875465c977adad22260e5c7bd62051709a3d1dedc1809a8057c","label":null,"multisigInfo":{}}}

 balanceステータスがこのアドレスに含まれるxemを示す。それによると、NB7J657L7TBNKXOGXQJVP5VEKQODTDZORPW3ZF3Yに入っているxemは0であることがわかる。


 ちなみに、他のアドレス(例えば自分が管理しているアドレス)を覗いてみたい場合は…

http://45.76.107.205:7890/account/get?address=NB7J657L7TBNKXOGXQJVP5VEKQODTDZORPW3ZF3Y

 上記の着色部分がアドレスを指定する部分になっているので、そこを自分が管理するアドレスに書き換えれば良い。



 駆け足になったが、APIで出来ることが理解できただろうか?この他にも、トランザクションの生成(送金)なども出来るが、処理が複雑なのでここでは紹介しない。気になればAPIリファレンスを読みながら試してみると良いだろう。



API機能はNEMだけにしか無いのか

 便利なAPI機能だが、ではビットコインやライトコイン、モナコインなどの標準クライアントには付いていないのか。


 実は、ビットコインなどにもAPI機能は付いている。そのため、やろうと思えば上記で示したようなことをビットコインで再現することも可能だ。だが、ビットコインではセキュリティの観点から基本的に得体の知れない外部からのリクエストにAPIが応えるべきではないとしている。


 そのため、通常ビットコインなどを利用したサービスは下のような体制をとることになる。

 
 だが、外部からのAPIアクセスを認めたNEMでは、下のような体制を取ることが出来る。

 これが何を意味するのかというと、クライアント側だけを作ってブロックチェーンを利用したアプリを作ることが出来ることを意味する。しかも、自分でいくつもノードを建てなくても単一障害点のないアプリを作ることが出来る。
(その代表的な例がNanoWalletになる)



APIを利用する上で参考となる外部リンク

■NEMの説明書
 APIリファレンスの和訳をしてくれている。


■Qiita&mijinフォーラム(takanobuさんの記事)
 基本的なとろこから細かく解説してくれている。さらに、mijinフォーラムから実際にNEMのAPIを使用して作られた"NEMBook"を使ってみるとAPIのパワーを感じることが出来る。


■Qiita(him0さんの記事)
 トランザクション生成について説明してくれている。


■kataribe(tadajamさんの記事)
 この記事以外にもkataribe内で色々な記事がある。



最後に

 簡単だが以上をNEMのAPIについての説明とする。「ボット」と呼ばれるような自動売買プログラムを簡単にでも作ったことがある人であればそれほど難しい話ではないと思う。触ってみても、アドレスに紐づくUTXOがどうだとかブロックチェーンの仕組みがどうだなどと考える必要もない。(NEMはそもそもUTXOではないけど…)非常に便利だと感じる。


 しかしここで一点注意をしておきたいことがある。仕様変更についてだ。NEMではカタパルトによってその構造自体が変わる予定があるので、もしかしたら大きなAPIの仕様変更があるかも知れない。今からなにか作ろうと思っている方は注意が必要だ。


チャオ☆

Segwitに関して調べた記録5


前回の続き



はじめに

 この記事ではSegwitによって新たに採用されるトランザクション署名用メッセージのシリアライズ方法について書くが、ここで一点前置きをしておきたい。


 Bitcoinの署名用メッセージの生成方法は、予めいくつかの決められたパターンが存在し、そのパターンはHashTypeと呼ばれる。このHashTypeは署名データの一番後ろに1byteで表現されて付け加えられ、unlock scriptに入れられる。
(詳しい仕組みは下記BitcoinWikiのOP_CHECKSIGの項目で確認してください)

OP_CHECKSIG - Bitcoin Wiki


 このHashTypeはSegwitでの署名検証においても使用されるので、本来であれば、それぞれパターンに分けて説明をするべきなのだが、ここでは簡単に説明するため、一般的に使われる「SIGHASH_ALL(=0x01)」に関するシリアライズに絞って書く。



レガシーな署名用メッセージのシリアライズ (SIGHASH_ALL)

 Segwitで使われる署名用メッセージのシリアライズ方法を書く前に、通常のP2PKHなどで使用されるレガシーな署名用メッセージのシリアライズ方法に関して書いておく。


 Segwit採用前のトランザクション署名用メッセージのシリアライズ(SIGHASH_ALL)の方法はunlock scriptフィールドが空の状態のトランザクションに、lock scriptを差し込んだものと、Hasyを4byteで表現したデータを合わせてHash256(SHA-256doubleHash)して生成している。


※新たに発行するトランザクションに参照しているロックスクリプトを差し込む際に、script内に
 OP_CODESEPARATORがあるときは注意が必要。



 ここで、署名用メッセージとしてシリアライズされるフィールドというのはつまり「署名によって守られているフィールド」を意味している。



BIP-143で定められている新しいシリアライズ (SIGHASH_ALL)

 では、BIP-143で定められている新しい署名証メッセージ(SIGHASH_ALL)はどうやって生成するのか、BIP-143を引用すると下記のとおりとなっている。

Double SHA256 of the serialization of:

 1. nVersion of the transaction (4-byte little endian)

 2. hashPrevouts (32-byte hash)

 3. hashSequence (32-byte hash)

 4. outpoint (32-byte hash + 4-byte little endian)

 5. scriptCode of the input (serialized as scripts inside CTxOuts)

 6. value of the output spent by this input (8-byte little endian)

 7. nSequence of the input (4-byte little endian)

 8. hashOutputs (32-byte hash)

 9. nLocktime of the transaction (4-byte little endian)

 10. sighash type of the signature (4-byte little endian)


BIP-143より引用

https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki

 1、4、7、9、10に関しては、レガシーなシリアライズと同じ、新規発行した署名前のトランザクションのフィールドから取り出した値を使用すれば良い。それ以外の2、3、5、6、8に関して、一つずつ見ていこう。



2. hashPrevouts (SIGHASH_ALL)

 hashPrevoutsは新規発行TxのTx_Inの中にある全てのoutPointフィールドを取り出して(index順に)繋げたものにHash256を行う。


3. hashSequence (SIGHASH_ALL)

 hashPrevoutsは新規発行TxのTx_Inの中にある全てのsequenceフィールドを取り出して(index順に)繋げたものにHash256を行う。


5. scriptCode of the input  (SIGHASH_ALL)

 これから署名を行おうとするTx_inが参照しているlock scriptについて…


■P2WPKHの場合

0x 19 76 a9 14 {20-byte-pubkey-hash} 88 ac

 となる。(lockscriptに格納されている状態から、Bitcoin scriptの処理に変換して使用する)


■P2WSHの場合
 witness scriptにOP_CODESEPARATORが含まれていない場合は、witness scriptをそのまま使用する。OP_CODESEPARATORが含まれている場合は、witness scriptにあるOP_CODESEPARATORのうち、一番最後のもの以降のwitness script部分を使用する。


6. value of the output spent by this input  (SIGHASH_ALL)

 これから署名を行おうとするTx_inのoutPointにて参照しているTx_outのvalueフィールド
(つまりこのTx_inが解錠するBitcoinの量)


8. hashOutputs  (SIGHASH_ALL)

 新規発行トランザクションのTx_out部分をindex順に全てシリアライズしてつなげたデータにHash256を行う。


署名によって守られる要素 (SIGHASH_ALL)

 以上の手続きでシリアライズしたデータに署名を行うということはつまり、署名によってそれらが守られることを意味する。新しいシリアライズによって守られるTxの部分を図で示す。
(着色部分は署名によって守られる)

 BIP-143のシリアライズによって新たに加わったところとしては、参照先のTx_outのvalueフィールドが保護されるようになったところである。また、その他の特徴としては、フィールドをそのまま使用するのではなく、トランザクションを構成する要素になる各フィールドを繋げてHash256したダイジェストを使用するところだ。



BIP-143で定められている新しいシリアライズ (さいごに)

 BIP-143で定められている新しいシリアライズ(SIGHASH_ALL)に関する説明は以上となる。この辺りの話を実際に理解するには、実際に自分でシリアライズしてみて検証してみたほうが良いと思う。


 幸い、BIP-143にはいくつかサンプルが載っているので、それと照合して確認するのが良い方法だと思う。


〜6に続く〜