8弊社エンジニアがブロックチェーンの旬の話題をお届けします。2019の1日目の記事です。動機なぜか最近、自分の周りでブロックチェーン関連の仕事をする人が増えており、質問を受ける機会が多い。ブロックチェーンの基本的な用語や情報などはWeb上に多く見られるが、仕様に関して日本語でまとまってわかりやすく説明されている記事などはまだまだ少ないように思う。ブロックチェーンを理解するためには、大枠として、「トランザクション」と「ブロック」の仕様をそれぞれで理解すると進めやすい。Bitcoinの目次で言えば、下記に該当する。「Bitcoinネットワーク」「ブロックチェーン」「マイニングとコンセンサス」そこで、本記事では、「トランザクション」の部分に注目して、前準備なしに触りながら理解できる記事を書ければと思っている。対象通貨はBitcoinとする。流れトランザクションのシリアライゼーションフォーマットを理解するScriptは何を表現しているのかを理解する実際にmainnetやtestnet上に流れているトランザクションを見ながら理解を深めていく。現在、Bitcoinのブロックチェーン上では下記3種類のトランザクションが存在している。非segwit)segwitトランザクションcoinbaseトランザクション今後のBitcoinのアップデートなどにより、これら以外のトランザクションが出てくる可能性もある。普通のトランザクションに関して、「普通の」とつけたのは、segwit及びcoinbaseトランザクションと区別するためで、通常は非segwitトランザクションと呼ばれることが多い。非segwit)」を取り上げる。普通のトランザクションを解析してみるブロックチェーン上にすでに存在するトランザクションを見て、理解を深めていく。トランザクションを解析するためには、トランザクションの実体である、生トランザクション(RawTransaction)を取得していく。そのため、普通のトランザクションのTxID1を取得する必要がある。普通のトランザクションかsegwitトランザクションかを見分けるには、ChainFlyerがお手軽だ。ChainFlyerサイトにアクセスしたら、画面上部から落ちてくる正六面体で、下記画像の一番右のような、プレーンな正六面体を選ぶ。すると、「トランザクション」の文字の下にTxIDが表示される。ちなみに鍵があるものや、小さな正六面体があるものを選ぶと、下記のように「トランザクション」の文字の横にsegwitと表示される。こちらがsegwitトランザクションとなる。生トランザクションの取得それでは、画像で使われている5a4216acfb7b8619b4455925e77d789867cea06b74c77f09be41037fcddc062cのTxIDを使って、生トランザクションを取得する。読者の方で、bitcoin-cliが使える環境を用意されている方は稀だと思うので、下記サイトを利用する。ChainQueryこのサイトでは、bitcoin-cliの各機能がブラウザ上から使えるようになっている。使いたいので、getrawtransactionのページに遷移する。Commandを実行する。(reCAPTHCAが表示されていたら、チェックを入れてください。getrawtransactionと書かれている箇所に表示される。ここでresultに表示されている01000000015975479e8161302eca4b69ad687418655dfc6d960da3c642542d712193bc6127010000006b48304502210094ea6b6cce6b1224047c39fd5da6ce932d0a5091a5d20f4e1dd4d2e1a6c04733022065d606a3e210650c1ad857d99a1eadd12ab7f08d5def1913766117124be0cec7012102a166ea841c7344b2d3a9a1f9e890d8b2144b5b975cb0ed87d68f12065df89ea7ffffffff0258c90900000000001976a9141eca25f20d936a6e176701b6fe2953d358d9add788ac86022b00000000001976a9144edc3518c2b5eb0a35535d0c47f164b7b5423a0a88ac00000000が生トランザクションとなる。生トランザクションをシリアライゼーションフォーマットに当て込むこれだけ見ていると頭が痛くなる方もいるかもしれないが、形に当てはめてしまえば割と簡単。トランザクションはバイナリのフォーマット(シリアライゼーションフォーマット)が仕様で定められているので、そこに当て込むだけである。普通のトランザクションのシリアライゼーションフォーマットはChaintopeの安土さんの記事がBitcoin公式リファレンスの翻訳になっていてわかりやすい。上記記事では、シリアライゼーションフォーマットの入れ子関係が分かりづらいので、下記表にまとめてみた。(各詳細は上記記事で補足してください。LockTime※tx_inとtx_outはそれぞれのcount数分連続して続きます。サイズの項目の「1,3,5,9のいずれか」は、対象のデータサイズをもとに、下記ルールによって決まる。得られた結果を先頭から当てはめていってみると、下記のようになる。endianになっていることに気をつけよう。segwitトランザクションでもcoinbaseトランザクションでも、それぞれのシリアライゼーションフォーマットが用意されており、同様に当て込んでいくことができる。トランザクションのシリアライゼーションフォーマットへの当て込み方はここまでで理解できたと思うので、次はトランザクションの内容を理解するために、Scriptを理解していこう。locktimeやtx_in-sequenceに関しては、本稿では説明しないが、簡単にはトランザクションのブロックへの取り込みタイミングを制御するために使われる。詳しくはBIP-68やBIP-125などを参考にして欲しい。script(以下ScriptSigと呼ぶ)やpk_script(以下ScriptPubkeyと呼ぶ)が謎の部分だろう。これらは総称してScriptと呼ばれるが、ここがBitcoinトランザクションの肝になってくる。Scriptの説明に、よくP2PKHやP2SHなどの言葉が出てくると思うが、そもそもそれ以前にScriptの役割を知っておいたほうがよいと考えている。BitcoinにおけるScriptとは、間違いを恐れずに一言で表現すると「UTXOの消費にかかわるクイズを定義するもの」である。クイズのお題がtx_outに含まれるScriptPubkeyであり、それに対する回答がtx_inに含まれるScriptSigである。UTXO対象のScriptPubkeyに対して、正解のScriptSigを含むトランザクションをブロックチェーン上に送信したときに、クイズに正解したということで、BTC残高の移動が行われる。逆に言うと、クイズが解かれるまでは、残高はそのクイズによってLockされているわけである。scriptと呼ばれる所以である。BTC残高が移動する、ということは、アドレスからアドレスへBTCが移動しているということである。残高が移動する、という表現が成り立つ。それでは先程のトランザクションのScriptSig48304502210094ea6b6cce6b1224047c39fd5da6ce932d0a5091a5d20f4e1dd4d2e1a6c04733022065d606a3e210650c1ad857d99a1eadd12ab7f08d5def1913766117124be0cec7012102a166ea841c7344b2d3a9a1f9e890d8b2144b5b975cb0ed87d68f12065df89ea7は、どのScriptPubkey(クイズ)に対する回答か?というと、一つ前のトランザクションのScriptPubkey(クイズ)に対する回答になる。自分が勉強を始めたときによく勘違いしていたのが、ScriptPubkey(クイズ)と対応するScriptSig(回答)が同一のトランザクションに含まれていると勘違いしていた。同一のトランザクション内に存在するScriptSigとScriptPubkeyは、同じトランザクションに含まれているというだけで、全く関係性はない。ここまでの話をイメージしやすいように下記の図を用意したので、説明と合わせて理解できるまでじっくり見て欲しい。P2PKHやP2SHなどのスクリプトの種類を知る前にこの関連性を知っておくことが大事である。この前提を知った上で、先程のトランザクションのScriptを具体的に見ていく。Scriptの解析まず、ScriptSigから見ていこう。ScriptSigはクイズのお題に対する回答なので、まずお題を知る必要がある。お題は、tx_inのprev_outから知ることが可能だ。ここに、一つ前のTxIDとTxOutputのindex値が格納されている。4またChainQueryにお世話になろう。https://chainquery.com/bitcoin-cli/getrawtransactionそうすると、以下の結果が得られる。0200000000010184bde6688f4c23b10dc667f785af08290ac2f0d11958213c8afcfd3c087cb2f90600000000fdffffff0abef40100000000001976a91475d286c168187202b18f2e236c340af9f1cae4bd88ac84ce3400000000001976a914742e1f933af72f03876eeadac8402cfcafd4533288ac4b0a0d00000000001976a91477b97182bc281a8fbe1b0c39ca8c9e6fd2b13ce488acaf250800000000001976a9145b1dbf9b075e156f53abeb7cb9176fe54befa41b88ac75ae0600000000001976a914f510e76146715f0b8b9f3fd342efcac33edd5e8e88ac104b1000000000001976a91405724f9ff55ffb3ed13f1c951251a96bcd4b56c388ac1fe73000000000001976a91422e068ba8c926017436d1c6e5b66754c5da3a43688acf1918f01000000001600145f7ddd38fa71a27af7e847a4dd194a6048eae663ce8f1300000000001976a91486f292f7ad4df5aecbffd516dca55b91c1ec973d88ac8d0c3900000000001976a91476db8fa6f32d531f8a0c1c952fa5063e77f4564888ac02473044022064274d9e12d23dbe718215973f6c8744c5f56624cd400f6a9f9828d2a78bd590022073b06769a4630fb060430c5a1c5536fd5ec68f70c0687b73ef0552ca7bdfe0e00121024362d42ce1d8a639afdd14b3fb281a79ed1a5761e3537519d986eddee5673582a5390900この生トランザクションをシリアライゼーションフォーマットに当て込めてもいいが、いちいちめんどくさいし、このトランザクションはsegwitトランザクションで、segwitトランザクションのシリアライゼーションフォーマットは説明していないので、今回はツールを使わせてもらおう。実行すると、上記トランザクションがシリアライゼーションフォーマットに合わせてJSON出力として得られる。無い方は、BlockCypherのページに、生トランザクションをデコードしてくれるページがあるので、こちらを使用する。Transactionのボタンを押すと、JSONでデコード結果が表示される。1番目なので、下記結果のみを利用する。(indexは0からはじまるので注意。"76a914742e1f933af72f03876eeadac8402cfcafd4533288ac"がScriptPubkey(お題)である。このままだと、このお題が何を表現しているかわからないので、このscriptを解析する。bitcoin-cli環境が無い方は、下記サイトを利用させていただこう。IDE画像のように、Assemblyと書かれているタブを選択し、上記scriptを貼り付け、Scriptと書かれているタブに戻ると、解析結果が表示される。Hash)のScriptである。これに対して、ScriptSigも同様に解析すると、下記のようになる。02a166ea841c7344b2d3a9a1f9e890d8b2144b5b975cb0ed87d68f12065df89ea7これは`の並びとなっており、P2PKHに対する回答となる。これを下記のようにの順に並べ、Scriptを実行すると、1(true)`が得られる。OP_CHECKSIGここで、このScriptが正しいかどうかの検証を行いたかったが、どうもうまく動作するサイトが見つからなかったので、検証に関しては一旦置いておくとする。6ここでは、Scriptが1(true)になれば、回答(ScriptSig)が正解であり、正解のときにBTC残高が移動する、ということがわかれば良い。Scriptの詳細は色んな所で記事になっているので、本稿では説明しない。最近見た記事では下記記事がわかりやすかった。上記のScriptの例と照らし合わせて見ると、理解が進むかもしれない。前項で、正解のときにBTC残高が移動する、と書いたが、ご承知の通り、BTC残高はアドレスに紐づくものだ。実は、ScriptPubkeyの中にアドレスの情報となるものが含まれており、ここのをもとにアドレスが導出されている。前項で解析した一つ前のトランザクションのScriptPubkeyを見てみる。OP_CHECKSIGこのScriptはP2PKHのScriptだと説明したが、Scriptもトランザクション同様仕様が定められている。ここで742e1f933af72f03876eeadac8402cfcafd45332の部分は、公開鍵のHash1607を計算したものとなる。アドレスは公開鍵から導出できる。公開鍵->Hash160化->Base58Check8というプロセスを経てアドレスとなる。実際に上記Hash160でハッシュ化された公開鍵から、アドレスが導出できるか見てみよう。下記サイトを使わせていただく。BASE58Check)を選択してみよう。1BbJdxaNRy4rUePTE9hcQ9rTgAK67SWMxxが結果として得られるはずだ。Explorerで検索してみる。すると、下記画像のような結果が得られる。Fromに一つ前のトランザクションである2761bc9321712d5442c6a30d966dfc5d65187468ad694bca2e3061819e477559が。Toに対象トランザクションである5a4216acfb7b8619b4455925e77d789867cea06b74c77f09be41037fcddc062があることがわかる。同様にして、5a4216acfb7b8619b4455925e77d789867cea06b74c77f09be41037fcddc062の2つのTxOutputのScriptPubkeyをBitcoinIDEで解析し、ScriptPubkeyに含まれているHash160でハッシュ化された公開鍵からBase58Checkしてアドレスを導出してみよう。すると、13ooSG4xiHh4DUQUiGk7UAh8oJJ6ZAKStGと18ByWF2NTxMoNDzVCt97KABQquLixNBo9Jが得られるはずだ。このように、ScriptPubkeyからアドレスが導出できるため、TxOutputでは明示的にアドレスを指定する必要がないわけである。アドレスからアドレスへBTC残高の移動が行われる、というわけである。まとめ以上、トランザクションのシリアライゼーションフォーマットから、Scriptの解析、アドレス導出というところまで見てきた。生トランザクションからトランザクションを理解していく記事はあんまりないんじゃないかなと思う。実際自分がトランザクション周りを理解していく過程の中で、生トランザクションを触ったことは、理解を大きく進めることに非常に役に立った。今回取り上げた以外のトランザクションの種類やスクリプトの種類もあるが、トランザクションの基本的な考え方はここに書いてあるものがベースとなっている。トランザクションやスクリプト、アドレスなどの関連性がいまいちぼんやりしている方には、ぜひ読んでいただきたい。TxHashとも呼ばれる。↩sign系やsend系の一部機能はおそらくセキュリティの観点から封印されている。scriptという理解は厳密には違うが、ここでは簡単にするため、その意味で進める。Bitcoinの標準的なトランザクションの項を参照してほしい。↩ChainFlayerなどのBlockExplorerからPrevTx(親Tx)をたどることも可能。今回はあえてバイナリ形式のScriptがほしいため、この方法をとっている。↩このツールはdecoderawtransactionの結果にBlockCypher独自の付加情報も合わせて表示されるが、本質的に違いはない。↩prefixの種類もBase58checkする対象によって定まっている。00はP2PKHアドレスのprefixである。辻野晃一ゲームプログラマ->TV開発->暗号通貨ウォレット開発ブロックチェーンは全く門外漢だったが、たまたま暗号通貨ウォレット開発案件に参画。ドキュメントが揃ってるXRPが割と好き。この記事では、チェックサム部分のアルゴリズムを解いていきます。2019の18日目の記事です。2019の7日目の記事です。Signetについて興味を持ち、10月のビットコインとか勉強会#34でもハンズオンを行いました。この記事はbitcoinプロトコルをrustでお話してみる(前編)の続きの記事です。2019の14日目の記事です。マイニングの知見深めたいな。通信してみる(前編)ホームお知らせフレセッツ株式会社とは暗号資産(仮想通貨)取引所向けに事業者用ウォレットシステムを提供する事業を行っています。コールド/ホットを問わず、マルチシグ対応のウォレットを作っています。Reserved.ホーム検索トップサイドバーフレセッツ株式会社とは暗号資産(仮想通貨)取引所向けに事業者用ウォレットシステムを提供する事業を行っています。コールド/ホットを問わず、マルチシグ対応のウォレットを作っています。Lemma)の解説と具体例2019.12.092019.12.18カテゴリーお知らせ最近のコメントタイトルとURLをコピーしました。