暗号通貨に関する事など

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

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

ビザンチン将軍問題と分散型台帳

はじめに

 ブロックチェーン、分散型台帳、PBFT、コンセンサスアルゴリズム、色々調べると必ずこの単語にたどり着くと思います。「ビザンチン将軍問題」。



 じゃあこのビザンチン将軍問題、何なのかと検索してみると、ビザンチン将軍都市攻撃計画がどうだの、そんな話ばかりでイマイチ分かりにくい。私達は言葉の意味とそのイメージが知りたいわけで、ビザンチン将軍の都市攻撃が成功するかどうかなんていうのはどうでも良いのです。


 そこで、そんな話は一切せずに、分散型台帳におけるビザンチン将軍問題とは何なのかをかんたんに説明してみたいと思います。


 「ブロックチェーン聞いたことあるし何となく知ってるけど正直よくわからん」というエンジニアが理解できれば良いな程度の感覚で書きます。


タナカ氏の送金

 下記図のような分散型台帳ネットワークがあるとします。

 このネットワークでは不正をさせないように下記のルールがあるとします。

  • トランザクション(送金申請)には本人を証明する署名が必要
  • 残高不足であればそのトランザクションは却下

 ここがスタート地点です。


 あるとき、口座残高に10yen持っているタナカさんが、

  1. タナカからサトウに10yen送る
  2. タナカからナカモトに10yen送る

 という2つのトランザクションを、それぞれ別のサーバーに投げたとします。下記図の状態です。



 トランザクションはノードのバケツリレーによってどんどんネットワークに広がっていきます。



 ここで、ある時困ったことが起きます。

 上記図の真ん中の緑色のノードたちは混乱します。何故なら「AもBも正真正銘タナカさんの署名があるが、両方受け入れるには残高が足りない」からです。


 この混乱がビザンチン将軍問題です。(以上)



 一応続きを書きます。 


 混乱はネットワーク全体に広がってゆきます。

 さて、どうしましょうか。



解決法? 1 : 時間優先

 「後から来たやつ無視すればいいぢゃん。」


 はい、それ採用。やってみましょう。

 はい、見事に台帳が2種類に分裂しました。これではまずい・・・



解決法? 2 : 天の声に従う

 混乱したネットワークに1週間後、天の声が響いたとします。「Aを受け入れよ...」

 はい。解決しました。


 ように見えますが、これを扱っている人間は大混乱です。なぜならBを信じて運用していた人たちの帳簿履歴が一部完全に変わってしまうからです。


 帳簿は口座への出入金の記録の連鎖で出来ています。ある点のトランザクションがなかったことになると、その後それによって帳尻があっていた部分が合わなくなってしまいます。そしてその影響は、時間が経てば立つほど大きくなっていきます。

 10秒前の記録が消えるぐらいならレジの前で待てば良いけれど、1週間分とか変わられると使いものにならない。(待ってられない)やっぱりこれでもマズイわけです。


ブロックチェーンはどうなっているの?

 これを書き出すと今回説明したい範囲からそれるので書きませんが、いくつか追加でルールを設けて、「確率的に言ってまず間違いなくこれが正しいはず!」といえるようにしています。


 で、実は「解決法? 2 : 天の声に従う」で問題視していたトランザクションがなかったことになる問題は、ブロックチェーンは完全に解決しておらず、30分前まではこれで良いとされていたトランザクションが無効になる程度のことは度々起きています。これは reorg と呼ばれます。


 reorgに関しては、「まぁまぁ私達が考える仮定に沿って動いていればそんな長い期間の履歴がひっくり返ることないっしょ」という感じで受け入れられているものです。(だから取引所はビットコインなどの入金にどうしても承認時間が必要なんですよね)

【仮想通貨NEM】 NEM2-CliでCatapultネットワークに触れる3


前回の続きです。


今回やること

 今回は、前回までに用意したローカルのmijinネットワークにNEM2-Cliを使ってトランザクションを投げるところまでやります。


 これ以降はNEM2-Cliのリファレンスを見ながらコマンド叩いていくだけですね。


 私の使っているOSはこんなかんじ。

$ cat /etc/os-release

NAME="Ubuntu"

VERSION="18.04 LTS (Bionic Beaver)"


まずはGithubページのREADMEを見て必要なものの確認

 下記ページのREADMEを見ましょう。


 今回は、このリポジトリのダウンロードは不要です。 NEM2-CliはNode.jsのパッケージ管理システムのnpmに登録されたものを利用します。(自分でビルドしたければしてもいいですが…)


 必要なものは、先程も行ったとおりNode.js(npmはNode.jsのインストール時に一緒についてくる。)

The nem2-cli is distributed using the node package manager npm.


npm install nem2-cli -g


The nem2-cli works on NodeJS versions:


8.9.X

9.X.X


https://github.com/nemtech/nem2-cli Installationより

 Node.jsのバージョン確認しましょう。ちなみに私は...

$ node -v
v9.11.1


$ npm -v
6.1.0

 でした。


npmを使ってNEM2-Cliをインストール

 READMEに書いてあるとおり、

$ npm install nem2-cli -g

 を叩きます。すると、管理者権限で実行せよと怒られる。なので…

$ sudo npm install nem2-cli -g --unsafe-perm

 で、無事NEM2-Cliがインストールされた。 しれっと追加されている --unsafe-perm オプションは、管理者権限が必要な操作をする時に、必要になることがあるオプションなんだとか。


 (この前にsudoだけでnpm install すると権限が無いと言われ、--unsafe-permを追加すると無事インストールできた。これが無いと制限がかかるみたいだけど詳しく調べてはないので説明は出来ない。)


 インストールしたら確認しましょう。コンソールに " nem2-cli " と打つだけ。

 おぉ…それっぽい…


xemを持っているアカウント情報を取得する

 Catapultネットワークでは、全てのxemはnemesisブロックで生成され、最初に設定した各アカウントに割り振られます。


 ということは、送金を試す前にまず最初にxemを持っているアカウントの情報を得ないといけません。(具体的には秘密鍵)


 とりあえずヒントをbootstrapのREADMEから探しましょう。「キーの設定」の項に普通に書いてあります。


 前回までで、bootstraopをダウンロードし、docker-composeしている方は、そのディレクトリ内部の build/generated-addresses/ の中に、3つのファイルを見つけることが出来るはずです。

  • README.md
  • addresses.yaml
  • raw-addresses.txt

 の3つです。このうち、addresses.yamlには、各アカウントの秘密鍵、公開鍵、アドレスに加えて、各アカウントの役割が記載されています。ここからxemを持っているアカウントを選択しましょう。


 今回は、addresses.yaml内の  " nemesis_adresses " の一番上にあるものを使います。

[ catapult/catapult-service-bootstrap-master/build/generated-addresses/addresses.yaml ]

nemesis_addresses:

- private: D4DA2B736DAFC494939CEB0583E39450C8EA629E0998A54ACFAD7C97DFED0A00

public: EA2E9D94E0A3A6AD57C45C0EB30EC86C0DDAC864F9B13864333012CD4DD10971

address: SBBT7VPHPAWNTJ5JQQABGOTZUCQWG4FUV6ZELD4H

 
 これで準備が出来ました。ここからがNEM2-Cliの操作です。mijinネットワークは動かしっぱなしにしておいてください。


1. プロフィールを作成する

 まずは、addresses.yamlから選択したアカウントを、NEM2-Cliのプロフィールに登録します。プロフィールの作成のコマンドは下記の通り

$ nem2-cli profile create \

--privatekey your_private_key

--network MIJIN_TEST  \

--url http://localhost:3000 \ 

--profile mijin_test_net_profile 

 なので、今回は...

$ nem2-cli profile create --privatekey D4DA2B736DAFC494939CEB0583E39450C8EA629E0998A54ACFAD7C97DFED0A00 --network MIJIN_TEST --url http://localhost:3000 --profile mijin_test_net_profile

 とします。--profileオプションはプロフィール名なので任意で変えても問題ありません。


2. 作成したプロフィールを確認する

 ちゃんと出来たか確認。

$ nem2-cli profile list


Profile stored correctly

mijin_test_net_D4DA->

Network: MIJIN_TEST

Url: http://localhost:3000

Address: SBBT7VPHPAWNTJ5JQQABGOTZUCQWG4FUV6ZELD4H

PublicKey: EA2E9D94E0A3A6AD57C45C0EB30EC86C0DDAC864F9B13864333012CD4DD10971

PrivateKey: D4DA2B736DAFC494939CEB0583E39450C8EA629E0998A54ACFAD7C97DFED0A00

 出来ていれば問題なし。


3. 作成したプロフィールを登録

 作成したプロフィールは環境変数の " NEM2_PROFILE " にプロフィール名を入れることで登録できます。

$ export NEM2_PROFILE=mijin_test_net_profile

 恒久化したければ .bash_profile などに書いておくのをお忘れなく。windowsだとコマンド違うのかな?(分からないけど環境変数NEM2_PROFILEを作ってプロフィール名を入れればいけるんじゃないかな?)


 これにより、トランザクション生成等のコマンドはこのアカウントから生成されるものであるとNEM2-Cliは認識してくれます。


4. アカウントの情報を確認

 とりあえずプロフィールに設定したアカウントの情報を取ってみます。

$ nem2-cli account info --profile mijin_test_net_profile


Account: SBBT7V-PHPAWN-TJ5JQQ-ABGOTZ-UCQWG4-FUV6ZE-LD4H

-------------------------------------------------------


Address: SBBT7V-PHPAWN-TJ5JQQ-ABGOTZ-UCQWG4-FUV6ZE-LD4H

at height: 1


PublicKey: 0000000000000000000000000000000000000000000000000000000000000000

at height: 0


Importance: 409090909

at height: 5026


Mosaics

nem:xem: 409090909


5. 適当なアドレスの用意

 プロフィールに設定したアカウントからxemを送信するための受取アドレスを適当に用意します。

適当に用意したアドレス:

SBJS4J5HOZLOWISW7KJIKP3CBN3TM2Y7FYABBAGM

 中身見てみましょう。

$ nem2-cli account info --address SBJS4J5HOZLOWISW7KJIKP3CBN3TM2Y7FYABBAGM


Error {"code":"ResourceNotFound","message":"no resource exists with id 'SBJS4J5HOZLOWISW7KJIKP3CBN3TM2Y7FYABBAGM'"}

 はい。まだネットワーク上にアカウント情報がないのでエラーです、


6. 送信トランザクションの送信

 受取アドレスの準備も出来たところで、送信を試してみます。TransferTransactionを使います。

$ nem2-cli transaction transfer \

--recipient recipient_address \

--message "message" \

--mosaics nem:xem::send_amound

 今回は...

$ nem2-cli transaction transfer --recipient SBJS4J5HOZLOWISW7KJIKP3CBN3TM2Y7FYABBAGM --message "payout of 10 xem" --mosaics nem:xem::10000000


Transaction announced correctly 

Hash: 5E6C4C8D40B77FF709E51C77D293A24840F7594F5F43C6E2386F3F079E4AD349

Signer: EA2E9D94E0A3A6AD57C45C0EB30EC86C0DDAC864F9B13864333012CD4DD10971

 これで、SBJS4J5HOZLOWISW7KJIKP3CBN3TM2Y7FYABBAGMに向けて10xemが送られます。注意すべき事項は、xemは可分性が有り1/1,000,000xemが最小単位なので、10xemを送りたければamountを 10,000,000 とするところぐらいでしょうか。


7. 送信できたか確認してみる

 受け取り側アカウントの状態

$ nem2-cli account info --address SBJS4J5HOZLOWISW7KJIKP3CBN3TM2Y7FYABBAGM


Account: SBJS4J-5HOZLO-WISW7K-JIKP3C-BN3TM2-Y7FYAB-BAGM

-------------------------------------------------------


Address: SBJS4J-5HOZLO-WISW7K-JIKP3C-BN3TM2-Y7FYAB-BAGM

at height: 5335


PublicKey: 0000000000000000000000000000000000000000000000000000000000000000

at height: 0


Importance: 0

at height: 0


Mosaics

nem:xem: 10

 送信したトランザクション

$ nem2-cli transaction info --hash 5E6C4C8D40B77FF709E51C77D293A24840F7594F5F43C6E2386F3F079E4AD349


TransferTransaction:

Recipient:SBJS4J-5HOZLO-WISW7K-JIKP3C-BN3TM2-Y7FYAB-BAGM

Message:"payout of 10 xem"

Mosaics: d525ad41d95fcf29:10000000

Signer:SBBT7V-PHPAWN-TJ5JQQ-ABGOTZ-UCQWG4-FUV6ZE-LD4H

Deadline:2018-07-02

Hash:5E6C4C8D40B77FF709E51C77D293A24840F7594F5F43C6E2386F3F079E4AD349

 ということで、送信できたことまで確認できました。 " Mosaics: d525ad41d95fcf29:10000000 " の最初の項目はmosaicIDで、xemのmosaicID=d525ad41d95fcf29ということです。



 今回はここまで(続く)

【仮想通貨NEM】 NEM2-CliでCatapultネットワークに触れる2


前回の続きです。


今回やること

 今回はTechBureauから公開されているCatapult Service Bootstrapを利用してDocker仮想環境上にmijinネットワークを構築して動かし、その内容を確認するところまでやります。


bootstrapのダウンロード

 まずは、下記リンクからTechBureauのGithubページに行ってcatapult-service-bootstrapのclone and downloadボタンからbootstrapのzipファイルをダウンロードしましょう。



 ダウンロードしたzipを解凍したら、ファイルの中にREADME.ja.mdがあります。日本語の説明文です。親切ですね。はい。これに従うだけです。


Docker docker-compose を使える状態にする

 bootstrapはdocker-composeを使います。Dockerが入ってない場合はまず最初にDockerを入れてください。ちなみに、私が今使っていバージョンは...

catapult-service-bootstrap-master$ docker --version
Docker version 18.05.0-ce, build f150324


catapult-service-bootstrap-master$ docker-compose --version
docker-compose version 1.21.2, build a133471

でした。


docker-compose upを叩くだけ

 ダウンロードしたcatapult-service-bootstrap-masterファイル上に移動し、docker-compose upを叩くだけです。READMEのとおりですね。


 ちなみに、私の環境(ubuntu 18.04 LTS)ではDockerを動かすときには管理者権限が必要になるので全部sudo付けています。


ネットワークの構成

 Catapultネットワークは二層で構成されています。ブロックの生成、承認、を行うネットワークとそのネットワークから情報を聞き出し、クライアントからのリクエストに答えるAPIネットワークの二層です。それ以前は(現在のNIS1では)これらは一つにまとめられていて一層です。
 図にしたので載せておきます。

 今回は、一番下のブロックチェーンネットワークは peer-node-0_1 と peer-node-1_1 の2つ、APIネットワークが api-node-0_1 のひとつ、クライアントが NEM2-Cli となります。


コンソールに吐き出される情報を見てみる

 docker-compose upを叩くとdocker仮想環境上でネットワークが構築され、勝手にネメシスブロックを生成し、ブロックチェーンネットワークが動き出します。


 ちょっと内容を見てみます。

peer-node-0_1 | 2018-07-02 03:00:10.499019 0x00007fef967fc700: <debug> (consumers::NewBlockConsumer.cpp@53) forwarding a new block with height 5390


新しいブロックをnode-0_1が見つけたよう。heightは5390 ( 暫く放置してた )

 こんな感じで何をやっているかが読めます。


Block height1の情報を取ってみる

 APIノードがクライアントからの要求を受け取るソケットは3000番のポートにbindされています。


 ということで、ちゃんと動いているかの確認も含めて、READMEにもありますが、block高さ1、つまりnemesisブロックの情報を取ってみましょう。クライアントは何でも良いですが、とりあえずブラウザを使えば良いと思います。(README はcurl使ってるけど)


 WebブラウザのURL欄に 「 localhost:3000/block/1 」を打ち込んでみましょう。

{"meta":{"hash":"C8F26B4BC7B2293BADA2D36115ABF23355B11521BAD2C92E4FA33632FAFB1E54","generationHash":"D17D69C0B81FDD6CEA58F43295D1A5952559F954F3DE8440C2AE8639E04876E2","totalFee":[0,0],"numTransactions":25,

,"blockTransactionsHash":"6E7B8D9AF96527EF6775D1AF06420881B809C6927E5258F75B5C074689E95F80"}}

 こんな感じでnemesisブロックのデータがとれます。


 テストネットの終了は Ctrl-C でinterrupt送れば勝手にいい感じに終了してくれます。


 また再開したければ初回同様catapult-service-bootstrap-masterファイル上に移動し、docker-compose upを叩くだけです。終了した時点のブロックから再開してくれます。



 今回はここまで(続く)