post Image
[Node.js]ブロックチェーンアドレスを生成してみた – 中級編 –

実行環境

  • MacOS Sierra (10.12.6)
  • npm (5.3.0)
  • Node.js (8.2.1)

はじめに

前回入門編で実際にアドレス生成をしましたので、今回は前回の補足説明とより細かな設定方法を書いていきたいと思います。

前回の記事

復習

  1. 用意するべきもの。

    npm install bitcore-lib bitcore-mnemonic
    

  2. 前回書いたソースコード。

    server.js
    // ライブラリの読み込み
    var bitcore = require('bitcore-lib');
    var Mnemonic = require('bitcore-mnemonic');
    
    // ネットワークとパスフレーズの設定
    var network = 'livenet';
    var pass = '';
    
    // ニーモニックのランダム生成
    var code = new Mnemonic(Mnemonic.Words.JAPANESE);
    console.log("code: " + code.toString());
    
    // ニーモニック -> 親秘密鍵
    var master_pri = code.toHDPrivateKey(pass, network);
    console.log("master_pri: " + master_pri.toString());
    
    // 親秘密鍵 -> 子秘密鍵
    var child_pri = master_pri.derive("m/44'/0'/0'");
    console.log("child_pri: " + child_pri.toString());
    
    // 子秘密鍵 -> 子公開鍵
    var child_pub = child_pri.hdPublicKey;
    console.log("child_pub: " + child_pub.toString());
    
    // 子公開鍵 -> ブロックチェーンアドレス
    for (var i = 0; i < 5; i++) {
      var address = child_pub.derive("m/0/" + i).publicKey.toAddress();
      console.log("address[" + i + "]: " + address.toString());
    }
    

  3. 実行!!!

    node server.js
    

    コンソール画面に下記のような出力がされるはずです。

    code: とける りくぐん おうたい さいせい えまき おんどけい そそぐ ろんぎ くみあわせ ふこう ぶどう あらし
    master_pri: xprv9s21ZrQH143K4E5JE8kbU8PoGQpsuebfh7LospDFbCZyR2Rtr9CBGS5G2vGRphWLKXEq6Z6iuJKFsc72dtitxzMyGoBicWEXCrQEoDGKzNE
    child_pri: xprv9yfhLwcyCPQQbjeoHkBGQS7vqmnQ7P9wu3D397wgbr8PBVnPp5dFhGataQ7G6sBGvtvaJGLATf2b4xfaENPzbGLGQWP6nxNKfL9MCZAmzLt
    child_pub: xpub6Cf3kT9s2kxhpDjGPmiGma4fPoctWqsoGG8dwWMJABfN4J7YMcwWF4uNRhC3ptXR2cWtufTbVva7qNznNTTFJeAxnkZE5L61C9z6jbpPZg3
    address[0]: 1DkitMVgPYw2rg88HsWvFu3vDhFw64zuXB
    address[1]: 1PRZW5mJsxZcEx5E2MyqJAzdmpsA9tYesi
    address[2]: 18f2pCFG1H6v8qNr3DqqsgwTH5H9vnS6vU
    address[3]: 1CNhEbxcpRw7dMNm7KuJwUmvRBsf18BWfq
    address[4]: 1PMTXSaNQQ5Num5koRYHJHbHPhCBDaYaei
    

本題

前回はほとんど説明なしにとにかくアドレス生成をしたので、

  • ニーモニックは日本語だけしか対応していないの?
  • 秘密鍵って?公開鍵って?
  • 親から直接アドレスは生成できないの?

等々、様々な疑問に答えられるよう頑張って書きたいと思います。今回書ききれてない部分で疑問、質問等ございましたら、コメントの方で教えて頂ければ幸いです。

それでは、できるだ「細かく」「詳しく」書けるだけ書いていきます。

  1. ニーモニックのランダム生成について(server.js 10行目)

    var code = new Mnemonic(Mnemonic.Words.JAPANESE);
    

    前回このようにコードを書きました。
    実行結果を見ると、確かに日本語のニーモニックが12単語並んでいるのが分かりますね。

    実は日本語以外にも、英語・中国語・フランス語・スペイン語・イタリア語にも対応しています。
    それぞれの呼び出し方は、下記の通りです。

    var en1_code = new Mnemonic();
    // => "lobster crime menu radio tennis awesome sing erode cinnamon student cable oblige"
    var en2_code = new Mnemonic(Mnemonic.Words.ENGLISH);
    // => "lobster crime menu radio tennis awesome sing erode cinnamon student cable oblige"
    var ch_code = new Mnemonic(Mnemonic.Words.CHINESE);
    // => "藏 点 急 偏 刀 照 抹 弄 设 亿 威 箭"
    var fr_code = new Mnemonic(Mnemonic.Words.FRENCH);
    // => "décorer toxine dégager aérer objectif lessive nectar pouce enviable lavabo opinion étoile"
    var sp_code = new Mnemonic(Mnemonic.Words.SPANISH);
    // => "mamá abdomen diadema velero artista pájaro plural rosca trazar vivir rampa rifa"
    var it_code = new Mnemonic(Mnemonic.Words.ITALIAN);
    // => "cercare umile argine brevetto guanto sobbalzo scriba corazza ultimato flebo essenza atono"
    

    デフォルトが英語版なので、何も入力しない場合は英語版となります。

    ちなみにランダム生成だけではなく、外部のウォレットアプリで生成された既存のニーモニックを扱うこともできます。その場合はニーモニックが正しいものかどうかバリデーションチェックを推奨します。間違ったニーモニックのままアドレスを生成してしまっては大惨事ですからね。下記では日本語版で書いていますので、上記を参考にお好みの言語に対応させて下さい。

    var code = "すうせん きなが きんじょ とめる おがむ わじまし うつくしい おやつ ちせい そっかん しゃちょう にちじょう";
    var valid = Mnemonic.isValid(code, Mnemonic.Words.JAPANESE);
    // => (boolean) true or false
    if (valid) {
      var arr_code = new Mnemonic(code, Mnemonic.Words.JAPANESE);
      // 以降アドレス生成の過程
    } else {
      console.log("error...");
    }
    

    “arr_code”を入門編の”code”と置き換えて頂ければ以降アドレスを生成できるかと思います。

  2. ニーモニックから親秘密鍵の生成について(server.js 14行目)

    var master_pri = code.toHDPrivateKey(pass, network);
    

    前回このようにコードを書きました。
    “pass”はウォレットを作成する時に設定された方は必要です。特に覚えがない方は空白pass = '';で大丈夫です。
    “network”は「livenet(mainnet)」もしくは「testnet」を選択することができます。簡単にそれぞれの特徴を以下に記しておきます。

    • livenet … 実際に市場で取引されるBitcoinデータが格納されているBlockchainネットワーク。
    • testnet … 開発のためのBlockchainネットワーク。ここで生成されるブロックには価値がない。

    もしお試しでアドレスを生成してみたいという方は、万が一の事を考えて”testnet”でのアドレス生成をオススメします。

    ここで生成した親秘密鍵というのは、下記の画像でいう「Master Node」の秘密鍵です。
    derivation.png

    ブロックチェーン鍵は画像のような階層になっており、最も上に「Master Seed」≒「ニーモニック」があり、そこからただ一つの「Master Node」mが生成されます。その秘密鍵を今回は親秘密鍵と勝手に名付けました。秘密鍵が生成できたということは公開鍵も生成できるということです。
    ニーモニック ≒ シード > 秘密鍵 > 公開鍵 ≒ アドレス

    前回は親公開鍵は生成していませんが、生成することは可能です。ただ作ったところであまり意味はありませんが…。その理由はのちほど説明します。

  3. 子秘密鍵の生成について(server.js 18行目)

    var child1_pri = master_pri.derive("m/44'/0'/0'");
    var child2_pri = master_pri.derive(44, true).derive(0, true).derive(0, true);
    

    上記2通りの方法で子秘密鍵を生成しましたが、どちらも同じ結果になります。
    ここでいう子秘密鍵も勝手に私が名付けたものですので、ご了承ください。

    ところで気になった方も多いと思いますが、数字の右肩に「’」が付いているのは何故か…。
    実は「’」の付いた階層は強化鍵と呼ばれ、秘密鍵を持つもののみが入れる階層となります。
    つまり、公開鍵しか持っていない人は入れない「関係者以外立ち入り禁止」スペースなのです。

    先ほどの画像をもう一度見て頂くと、「Master Seed」の下に「Wallet Accounts」があり、さらにその下に「Wallet Chains」があり、ようやくその下に「Addresses」があるという感じに、深い木のような構造をしていますね。
    実際に皆さんがウォレットアプリを使ってアドレスを発行する時、どのルートを辿っているのかというと、
    (Master Seed) m / (Account) 0 / (Chain) 0 / (Address) i
    のようなルートになります。

    もし「Wallet Accounts」で”0″番目のアカウント以外を見られてしまったら、サービスによってはユーザー毎にアカウントを割り振っている場合があり、つまりは他のユーザーのアドレスを勝手に覗ける事になってしまうのです。これではセキュリティー的に問題があるので、先ほどの画像(BIP32)では「Wallet Accounts」は強化鍵をつける事になっているのです。(例えば “m/0’/0/0” のように)

    ちなみに私が書いたソースコードではBIP32規格の中のある一つの規格であるBIP44方式でアドレスを生成しているので、画像とは多少導出の仕方が異なります。以下に記しておきます。
    (Master Seed) m / (purpose) 44' / (coin_type) 0' / (account) 0' / (change) 0 / (address_index) i
    考え方はBIP32と同じなので、詳しくは以下のサイトを参考にしてください。
    -> BIP44 Wiki

    今回親秘密鍵から強化鍵の必要な階層まで導出し、それを子秘密鍵としたという事です。公開鍵からは絶対に導出できないものです。また一度奥の階層に入ってしまうと戻る事はできないので、気をつけましょう。
    ○ 親 -> 子
    × 子 -> 親
    親から子は産めますが、子から親は産めませんからね(笑)

  4. 子公開鍵の生成について(server.js 22行目)

    var child_pub = child_pri.hdPublicKey;
    

    秘密鍵から公開鍵を生成する。ただそれだけです。階層は変わりません。
    つまり子公開鍵の現在の階層は”m/44’/0’/0′”という事です。
    ここから奥の階層は強化鍵は必要ありませんから、公開鍵さえあればアドレス生成をする事ができます。
    ウォレットアプリによっては拡張公開鍵という名でこの子公開鍵をエクスポートできるものもあります。
    ウォレットを他人に預けるのは怖いですから、アドレスの生成のみできる公開鍵を渡す事は合理的です。
    そう、秘密鍵なしには送金する事はできないのです。それが一つ手前の「Wallet Chains(BIP32)」や「Change(BIP44)」の階層であり強化鍵で守られているので、公開鍵からはどう頑張っても導出できません。

    なんとなく子公開鍵の存在意義が伝わりましたでしょうか?
    私はこれを理解するのにすごく時間がかかりました(汗)

  5. アドレス生成について(server.js 26行目)

    var pub1_address = child_pub.derive("m/0/0").publicKey.toAddress();
    var pub2_address = child_pub.derive(0).derive(0).publicKey.toAddress();
    var pri1_address = child_pri.derive("m/0/0").privateKey.toAddress();
    var pri2_address = child_pri.derive(0).derive(0).privateKey.toAddress();
    var master1_address = master_pri.derive("m/44'/0'/0'/0/0").privateKey.toAddress();
    var master2_address = master_pri.derive(44, true).derive(0, true).derive(0, true).derive(0).derive(0).privateKey.toAddress();
    

    上記6通りの方法で0番目のアドレスを生成していますが、どれも同じ結果になります。
    秘密鍵から直接アドレスを導出する事もできますし、秘密鍵であればどの階層からでも導出できます。公開鍵は最後の2階層のみですね。

    一番奥の階層の数字を増やしていけば、新しいアドレスをどんどん生成できます!
    入門編のソースコードではfor文で回す事で0番目から5つアドレスを生成しています。

    ここで一つ気をつけなければならない事があります。
    それが「gap limit」です。

    ブロックチェーン上には多数のブロックが存在しており、それら全てを貴方のウォレットアプリで常に同期するというのは非現実的だというのは想像に難くないと思います。
    ウォレットアプリからすれば、なるべく必要最低限のアドレスだけを同期したいのです。
    そんな考えから、すでに使用済みの(送金または受金で使われた)アドレスから「gap limit」分、一般的なウォレットアプリだと”20″個連続で未使用なアドレスが続くとそこで同期を止めてしまうのです。

    つまり、Aさんが100番目のアドレスまで生成していて、そのアドレスを送受金に使った状態であれば、そこから20個先の120番目のアドレスまでウォレットアプリは常に同期しているということです。
    なので、120番目のアドレスを貴方がウォレットアプリ上ではなく、今回長々と説明してきた方法でパソコン上で生成した場合、そのアドレスに対して送受金をしてもウォレットアプリ上にその記録が瞬時に表示されます。
    一方121番目以降のアドレスを同様にして生成したとしても、そのアドレスに送受金をしてもウォレットアプリ上には何も表示されない為、まるで大切なお金がどこかへ消えてしまったような挙動に見えてしまいます。

    安心してください。本当に消えたわけではなく、同期されてないが故に感知されていないだけなので、101番目のアドレスが使用済みになる、もしくはウォレットアプリ上で121番目のアドレスが生成されるまで、「新しいアドレスを発行する」ボタンを連打すれば121番目のアドレスも同期対象になるので、晴れてウォレットに記録されます。

    この点にだけ気をつければ、アドレスの生成も怖くないですね!
    (※今自分が何番目のアドレスまで使ったのか調べる方法は私の勉強不足でわかりません。どなたか知っている方がいましたら、コメントでご教授お願いいたします。)

終わりに

次回はアドレスが使用済みなのか未使用なのか、またブロック情報の調べ方など書いていきたいと思います。

次回記事はこちら

また、少しブロクチェーンについて興味が湧いた!面白そう!と思った方がいましたら、ぜひコメント下さい(^^)

参考サイト


『 Bitcoin 』Article List
Category List

Eye Catch Image
Read More

Androidに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

AWSに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Bitcoinに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

CentOSに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

dockerに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

GitHubに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Goに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Javaに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

JavaScriptに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Laravelに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Pythonに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Rubyに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Scalaに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Swiftに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Unityに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Vue.jsに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Wordpressに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

機械学習に関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。