いるねすのブログ

働きたくない系SEが無駄に遊んだ記録

Hyperledger Fabric と戯れる part.4

Writing Your First Application (つづき)

前回に続き、Writing Your First Application チュートリアルをすすめてく。

hyperledger-fabric.readthedocs.io

node query.js

前々回あたりからチラホラ query とか invoke とか普通に言ってたが、基本的に query は参照などの read only なアクセス、invoke は追加・更新などの write を伴うアクセスに使う。

(実際のところ invoke で read only な事とかも出来たりするので不正確だったりするけど、まあさておき。)

  1. ../../basic-network/connection.jsonccp として読み込み
    • 前回と同じ
    • 以下、mychannel へのアクセスをするために使用している
  2. new FileSystemWallet() として ./wallet を使用
    • 前回と同じ
    • これまでの操作により、 ./wallet には adminuser1 の Identity が存在している
  3. gateway.connect(ccp, {wallet, identity: 'user1' ...})user1 としてゲートウェイに接続
    • admin でなく user1 として接続する点以外は前回と同じ
    • これで、各ノードに対し wallet を使用して接続し、 clientuser1@org1.department1 として振舞える
  4. network = await gateway.getNetwork('mychannel')mychannel へのアクセスを獲得
  5. contract = network.getContract('fabcar') で ChainCode fabcar へのアクセスを獲得
  6. result = await contract.evaluateTransaction('queryAllCars') で ChainCode の queryAllCars() をコール

で、肝心の ChainCode 側を見ていく。ChainCode 側のドキュメントはこちら。

fabric-shim.github.io

lib/fabcar.js が本体。 (index.js もあるけど、module の export しかしてない)

class FabCar extends Contract のように fabric-contract-api.Contract を継承しているクラスのメソッドがそのまま SDK 側から呼べるようになっている。

メソッドは Context クラスを第一引数に必ず取り、以降の引数(省略可能) を取れば、クライアントSDK側からデータを受けとることができる。

詳しくはこちらを参照。

fabric-shim.github.io

なお、Context の class API にはクラス変数の説明がないが上記ドキュメントの「Structure of the Transaction Context」を読めばわかる通り、ctx.stubChainCodeStub オブジェクト、 ctx.identityClientIdentity オブジェクトをそれぞれ取得できる。

やってることは単純にこれだけ。

  1. FabCar.queryAllCars(ctx)

なお、取得したデータは startFabric.shinvoke していた、initLedger() で格納している。 せっかくなので内容を見てみるけど、queryAllCars 以上にやってる事は単純。

  1. FabCar.initLedger(ctx)

node invoke.js

query.js と diff を取るとわかるが、違いは最後の contract.evaluateTransaction('queryAllCars')contract.submitTransaction('createCar', ...) になっている事と、明示的に gateway.disconnect() しているところのみ。

  • evaluateTransaction -> submitTransaction
  • FabCar.createCar()
    • 引数で指定された内容で Car オブジェクトを作って、それを ctx.stub.putState() で保存してるだけ
  • gateway.disconnect() の実行
    • コメントアウトして実行してみるとわかるけど、これをやらないと invoke.js は永久に終わらない。
    • 不可解だが、 query にこの行を足しても問題は起きないし、極めて一般的な感覚として connect したら必ず disconnect するべきと思うので、そういうもんだと思っておく

おしまい

話長くなるかと思ったけど、すげえ短かった。

次回は Commercial paper tutorial をやる予定。

hyperledger-fabric.readthedocs.io

Hyperledger Fabric と戯れる part.3

Writing Your First Application

予告通り、Writing Your First Application チュートリアルに進む。

hyperledger-fabric.readthedocs.io

startFabric.sh xxx

各ノードを構築して chaincode のインストール・インスタンス化まで実施。

xxx に javascript|typescript|go を指定することで chaincode の実装言語を選べる。デフォルトは Go だがチュートリアル的には JavaScript で説明している。 前回までの BYFN では Go をつかってたし、せっかくだから今回はチュートリアル通りに JavaScript でやってみる。好みではないんだけどね。

なお、それぞれの chaincode のソースコード../chaincode/fabcar に置いてある。

javascript-low-level というディレクトリがあるが、これは v1.4 以前のプログラムモデルによる実装。詳細は以下を参照。

hyperledger-fabric.readthedocs.io

  1. (TypeScriptのみ) JavaScript へのトランスパイル
    • Go のコンパイルは chaincode のインストール時に行われてるように見えていたが、TypeScript のトランスパイルはこの時点で行う
    • つまり、実装言語は TypeScript だとしても、実際に chaincode としてインストールされるのは(トランスパイルされた) JavaScript ということになる。
  2. docker-compose で必要なノードを起動する
    • 設定ファイルは ../basic-network/docker-compose.yml
    • 前回までは crypto-config を生成していたが、今回は最初から出来てる
      • ../basic-network/generate.sh で作ることもできるっぽいが、なんか微妙に違うものができる
        • generate 時の設定ファイル ../basic-network/crypto-configl.yamlorderer および org1 の設定のみがある
    • 今回作成するのは以下。なお全てのノードは basic ネットワークに含まれる。
      • ca.example.com
        • CA サーバ。今回初出。
        • ca.org1 の証明書と鍵をもつ
      • orderer.example.com
        • Orderer
        • orderer の証明書と鍵をもつ
        • peer0.org1 の証明書と鍵をもつ
      • peer0.org1.example.com
        • peer. 今回は 1 Organization, 1 Peer 構成ということになる
        • peer0.org1 の証明書と鍵をもつ
        • org1 の User1 と Admin の証明書と鍵をもつ
      • couchdb
        • CouchDB. 台帳の最新状況を保持するためのもの。今回初出。
      • cli
        • peer0.org1 に対する操作がセットアップされている
        • crypto-config データを持っている
  3. mychannel チャンネルを作成
    • 設定は ../basic-network/channel.tx
    • これまた既に作成済み。元となるものは ../basic-network/configtx.yaml
      • チャンネル参加者は orderer および peer0.org1 のみ。
  4. mychannelpeer0.org1 を join
    • mchannel.block も作成済み。
  5. mychannel に ChainCode fabcar v1.0 をインストール
    • ChainCode のパスは上述の通り
  6. mychannel の ChainCode fabcar v1.0 をインスタンス
  7. mychannel の ChainCode fabcar に対し initLedger()invoke
    • 動作確認がてら初期データの挿入を行っている模様
    • 以下を読み進めればわかる事だが、呼ばれているのは ../fabcar/javascript/lib/fabcar.js

クライアント側セットアップ

上記で chaincode の使用準備は整ったが、このままでは peer コマンド経由で叩くくらいしか使い道がない。 したがってクライアントアプリの構築をする。

startFabric.sh の出力を見てもわかるとおり、クライアントアプリの実装言語を選んで cd し、ビルドコマンドを叩くだけ。

クライアントアプリは JavaScript か TypeScript が選べ、また ChainCode 同様 v1.4 以前のプログラムモデルによる javascript-low-level もある。 ここも TypeScript はトランスパイルの 1 手間がかかるだけで大した違いはないっぽいので、素直にチュートリアルの指示通り JavaScript を選択した。

node enrollAdmin.js

クライアント用の Admin ユーザを登録。ざっくり読んでいく。

なお、Client側 (以下 SDK) API ドキュメントはコレ。

fabric-sdk-node.github.io

  1. ../../basic-network/connection.jsonccp として読み込み
    • 当該ファイルは今回のシステムの構成情報を記述してある。
    • 以下、CA の URL を得るために使用している
  2. new FabricCAServices() で CA に接続
  3. wallet = new FileSystemWallet() として ./wallet を使用
  4. identity = await ca.enroll({ enrollmentID: 'admin' ... }) して CA に admin を登録。
  5. X509WalletMixin.createIdentity(identity...) で、上で取得した鍵と証明書、MSPID (=Org1MSP) から Identity を生成
  6. wallet.import('admin', identity)walletadmin として identity を登録

これで wallet に admin が登録される。

  • ./wallet は以下のようになる。
$ tree wallet
wallet
└── admin
    ├── 81e6bfa(略)691478-priv
    ├── 81e6bfa(略)691478-pub
    └── admin

1 directory, 3 files
  • 81e6bfa(略)691478-priv, 81e6bfa(略)691478-pub は名前の通り中身はそれぞれ秘密鍵と公開鍵
    • 81e6bfa(略)691478 はランダムな値で、毎回違う値になる。
  • adminJSON ファイルで、以下のようなかんじ。
{
  "name": "admin",
  "mspid": "Org1MSP",
  "roles": null,
  "affiliation": "",
  "enrollmentSecret": "",
  "enrollment": {
    "signingIdentity": "31b577222c67(略)73516ea3c2483a",
    "identity": {
      "certificate": "-----BEGIN CERTIFICATE-----\nMIICAjCCA(略)BAd8GA=\n-----END CERTIFICATE-----\n"
    }
  }
}
  • certificate 部分は証明書なので平文に戻してみると以下
    • ca.org1.example.comclientadmin に発行した証明書であることがわかる。
    • これらは ca.enroll 時に生成されたもので、../../basic-network/crypto-config にある Admin@ca.org1.example.com 等の cert とは異なるもの。
$ Cat wallet/admin/admin \
     | jq -r '.enrollment.identity.certificate' \
     | openssl x509 -inform PEM -text -noout
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            02:af:ba:bd:ec:(略):c0:6c:27:1c:66
    Signature Algorithm: ecdsa-with-SHA256
        Issuer: C=US, ST=California, L=San Francisco, O=org1.example.com, CN=ca.org1.example.com
        Validity
            Not Before: Apr 17 07:34:00 2019 GMT
            Not After : Apr 16 07:39:00 2020 GMT
        Subject: OU=client, CN=admin
        Subject Public Key Info:
            Public Key Algorithm: id-ecPublicKey
                Public-Key: (256 bit)
                pub:
                    04:1d:36:c3:b7:64:20:03:7f:82:39:f8:58:2d:37:
                    (略)
                    5d:3a:c9:72:0b
                ASN1 OID: prime256v1
                NIST CURVE: P-256
        X509v3 extensions:
            X509v3 Key Usage: critical
                Digital Signature
            X509v3 Basic Constraints: critical
                CA:FALSE
            X509v3 Subject Key Identifier:
                67:49:65:58:49:(略):86:CA:A9:96:F7:91
            X509v3 Authority Key Identifier:
                keyid:42:39:AA:(略):6A:57:36:5E:49:7C

    Signature Algorithm: ecdsa-with-SHA256
         30:44:02:20:7c:7c:58:29:d9:5e:db:6a:91:af:1b:3b:19:8d:
         (略)
         16:60:52:00:0c:91:58:3a:f0:75:88:ae:3d:15:1f:df

node registerUser.js

  1. ../../basic-network/connection.jsonccp として読み込み
    • 当該ファイルは今回のシステムの構成情報を記述してある。
    • 以下、CA の URL を得るために使用している
  2. new FileSystemWallet() として ./wallet を使用
  3. gateway.connect(ccp, {wallet, identity: 'admin' ...})ゲートウェイに接続
  4. secret = await ca.register(...) でユーザを作成
    • Hyperledger Fabric SDK for node.js Class: FabricCAServices
    • CA に対し admin の権限で実行
    • client ロールをもつ user1@org1.department1 ユーザを作成する
    • secretuser1 のパスワード(自動生成)
    • まだ作っただけで登録は済んでいない。次の enroll() ではじめて登録される。
  5. await ca.enroll(), X509WalletMixin.createIdentity(), wallet.import()walletuser1 を保存
    • admin の時と全く同じ。

これで wallet に user1 が登録される。

  • ./wallet は以下のようになる。
$ tree wallet
wallet
├── admin
│   ├── 81bab1e(略)724a0e-priv
│   ├── 81e6bfa(略)691478-priv
│   ├── 81e6bfa(略)691478-pub
│   └── admin
└── user1
    ├── 81bab1e(略)724a0e-priv
    ├── 81bab1e(略)724a0e-pub
    └── user1

2 directories, 7 files
  • user1 ディレクトリができ、鍵ペアと証明書が新たに追加された
  • admin の下に新しい秘密鍵が増え、user1 のそれと同じというのが謎
    • あとでしらべる
  • 先ほど同様user1certificate 部分を平文に戻してみると以下
    • ca.org1.example.comclientadmin に発行した証明書であることがわかる。
    • 1.2.3.4.5.6.7.8.1: という属性が追加されており、ユーザ作成時に指定した affiliationrole などの追加情報が埋め込まれている
      • これが MSP で使用されるのだろう、たぶん。
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            28:38:98:15:77:(略):48:ce:39:9c:58
    Signature Algorithm: ecdsa-with-SHA256
        Issuer: C=US, ST=California, L=San Francisco, O=org1.example.com, CN=ca.org1.example.com
        Validity
            Not Before: Apr 17 09:26:00 2019 GMT
            Not After : Apr 16 09:31:00 2020 GMT
        Subject: OU=client, OU=org1, OU=department1, CN=user1
        Subject Public Key Info:
            Public Key Algorithm: id-ecPublicKey
                Public-Key: (256 bit)
                pub:
                    04:52:7b:ef:f4:49:b7:30:07:e6:a1:40:e7:90:70:
                    (略)
                    6a:9f:ae:ce:5d
                ASN1 OID: prime256v1
                NIST CURVE: P-256
        X509v3 extensions:
            X509v3 Key Usage: critical
                Digital Signature
            X509v3 Basic Constraints: critical
                CA:FALSE
            X509v3 Subject Key Identifier:
                5C:B5:E3:84:9F:(略):0B:C6:10:55:AF:38
            X509v3 Authority Key Identifier:
                keyid:42:39:AA:(略):6A:57:36:5E:49:7C

            1.2.3.4.5.6.7.8.1:
                {"attrs":{"hf.Affiliation":"org1.department1","hf.EnrollmentID":"user1","hf.Type":"client"}}
    Signature Algorithm: ecdsa-with-SHA256
         30:45:02:21:00:e9:10:09:8b:4b:d8:29:c8:e8:e8:52:b4:2f:
         (略)
         79:02:91:e1:04:32:af:65:b1:6e:42:ea:09:ab:72:33:86

今日はここで中断

さあこれから query と invoke を叩いて SDK 側だけじゃなく ChainCode の内側まで入っていくよ、という所なのだが、話が長くなりそうなので今回はここで中断。

次回はこの続きを読んでいくよ。

Hyperledger Fabric と戯れる part.2

ということで、今日も今日とてチュートリアル。まだコード書かないんかい。

前回の補足

前回やってたチュートリアルはこちら。

hyperledger-fabric.readthedocs.io

./byfn.sh down しないで以下のようにコンテナとイメージを削除するだけだと次の ./byfn.sh up でいろいろ失敗する。なにがいかんのかはパッと見分からなかったが、とにかく ./byfn.sh down しよう。

$ docker rm -f $(docker ps -aq)
$ docker rmi -f $(docker images | grep 'dev-' | awk '{print $3}')
$ git clean -fdx .

Adding an Org to a Channel チュートリアル

hyperledger-fabric.readthedocs.io

今回から eyfn.sh を使う。byfn が Build Your First Network の略っぽいから、eyfn は Edit 以下略とかって事なのかな。 ネーミングセンス・・・

ともあれ、 eyfn.sh にも サブコマンド generate, up, down (あと一応 restart も) がある。

チュートリアル本文では generate を省略して up を呼ぶ指示があるが、これは up のなかで generate の出力の有無をチェックして、必要があれば適宜呼んでいるから。(実は ./byfn.sh もここらへんの仕組みは同じ。)

初期状態 (前回のおさらい)

./byfn.sh up が完了した状態が今回の初期状態とある。つまり前回解説した通り、

ということになる。

./eyfn.sh generate

  1. cryptogenorg3-artifacts/org3-crypto.yaml の設定通りに証明書を発行して ./org3-artifacts/crypto-config を生成
    • cryptogen は以下を生成して、各ノード、ユーザの設定となるようディレクトリツリーをつくり配置する
      • org3.example.com ドメインの CA、全ユーザ(Admin, User1)、全ノード(peer0, peer1) それぞれに対する証明書と鍵
        • 証明書はそれぞれ交互に配布しあう (ユーザ同士は交換しない)
  2. configtxgenorg3-artifacts/configtx.yaml の設定通りに Org3 の設定を生成して ./channel-artifacts/org3.json を生成
    • 前回と違って Anchor Peer の設定ファイルとして .tx ファイルを作ってるわけではない。
    • org3-artifacts/configtx.yaml から organization の構成について抜粋したみたいなファイルを作っている。
  3. crypto-config/ordererOrganizationsorg3-artifacts/crypto-config/ にコピー
    • 前回作った Orderer まわりの証明書と鍵。
  4. cliscripts/step1org3.sh を実行させる
    1. apt-get install jq
      • 知ってる人も多いと思うけど、 jqJSON の操作をするコマンド。色つけたり整形したりもできて便利なのでみんな使おう
    2. peer channel fetch config ...
      • Orderer から mychannel の設定を取得している
      • 結果を configtxlator proto_decode --type common.Block することで JSON 形式に変換、 jq で必要情報を抜き出している
        • 内容は色々あるが、おおよそ mychannel の構成情報
    3. 上で抜き出した channel 設定に、上記で作成した ./channel-artifacts/org3.json を埋め込み
    4. configtxlator proto_encode, configtxlator compute_update 等を駆使して更新用のデータを作成
      • ここらへんの仕様にかんするドキュメントがまるで見当らないので詳細は不明
    5. peer channel signconfigtx ...
      • peer0.org1 に対して上で作った更新用データへの署名を手動で付加
    6. peer channel update ...
      • peer0.org2 に対して変更を送信
      • channel の管理者は peer0.org* の 2 つであり、変更ポリシは過半数の承認で受け入れれらるように設定されている。つまり 2 つ両方の承認が必要
        • peer0.org1 は先ほど手動で署名済み
        • peer0.org2 は今回の要求で org2 の Admin として送付されるため、問題なければ署名され、そのまま変更が受け入れられる
      • なおコレが mychannel のブロック5 にあたる。
        • ブロック 0 はジェネシスブロック (チャンネル初期設定)
        • ブロック 1 は Org1 のアンカーピア更新
        • ブロック 2 は Org2 のアンカーピア更新
        • ブロック 3 は myccインスタンス
        • ブロック 4 は mycc への invoke (byfn.sh で動作確認したやつ)
        • ブロック 5 が今回の org3 追加

./byfn.sh up

この時点では、mychannelorg3 を含ませるように設定できている。 だが実際に org3 の peer は mychannel に参加はしていない。(というより、org3 の peer 自体まだ存在していない)

  1. docker-composeorg3 の各ノードを起動する
    • 設定ファイルは docker-compose-org3.yaml
      • 内容的には org1, org2 と大差ない
    • 起動するのは以下。なおすべて byfn ネットワークに属する。
  2. 作った Org3cliscripts/step2org3.sh を実行させる
    1. peer channel fetch 0 ...
      • Orderer から mychannelジェネシスブロックを取得している
      • 前回は peer channel create の結果として生成されていたので取得の必要はなかったが、今回はこうして取得する
    2. peer channel join
      • Org3 の peer ノード(2つ)それぞれに対して実行してる。
        • 上で取得した mychannel.block を渡して、対象 peer ノードを mychannel に参加させる
    3. peer chaincode install
      • Anchor Peer である peer0.org3.example.com に対し実施
        • chaincode 名は mycc、 バージョン 2.0、実装言語は golang、とそれぞれ指定している。
        • chaincode 自体には変更がないが、バージョンを前回の 1.0 でなく 2.0 としているところに注意
  3. cliscripts/step3org3.sh を実行させる
    • ここだけ Org3cli ではなく cli に実行させてるので注意
    • peer chaincode install
      • Anchor Peer のうち残り 2 つである peer0.org1.example.com peer0.org2.example.com に対し実施
        • chaincode 名は mycc、 バージョン 2.0、実装言語は golang、とそれぞれ指定している。
        • org3 のとき同様、バージョンが上がっている。
    • peer chaincode upgrde
      • peer0.org1.example.com ノード 1 つのみに対して実行されている
      • peer chaincode instantiate とほとんど同じだが、バージョンアップ時はこちらを使うっぽい。
        • orderer orderer.example.com に対し、
          • TLS を有効にし、crypto-config/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pemTLS CA 証明書として付加したうえで、
        • mychannel において、
        • 初期化メッセージ {"Args":["init","a","90","b","210"]} を渡し、
          • "a" に "90" を、 "b" に "210" をそれぞれセットしているっぽい
        • ポリシー AND ('Org1MSP.peer','Org2MSP.peer','Org3MSP.peer') も渡して、
          • Org1、Org2、Org3 の承認の 3 つが必要ということ
        • mycc のバージョン 2.0インスタンス化する
      • インスタンス化の操作は channel 内の全 peer に伝達される
      • この時点で Org3 は他の Org1, Org2 と同様に mychannel の参加者となっている
  4. 再度 Org3cliscripts/testorg3.sh を実行させる
    • 動作確認。目新しいことはしていないので省略。

ここで、Docker コンテナを一覧してみると

$ docker ps --format "table {{.Names}}\t{{.CreatedAt}}\t{{.Status}}\t{{.Ports}}" | sort
NAMES                                 CREATED AT                      STATUS              PORTS
Org3cli                               2019-04-15 13:50:36 +0900 JST   Up About an hour
cli                                   2019-04-15 10:55:05 +0900 JST   Up 4 hours
dev-peer0.org1.example.com-mycc-1.0   2019-04-15 10:55:56 +0900 JST   Up 4 hours
dev-peer0.org1.example.com-mycc-2.0   2019-04-15 13:50:51 +0900 JST   Up About an hour
dev-peer0.org2.example.com-mycc-1.0   2019-04-15 10:55:39 +0900 JST   Up 4 hours
dev-peer0.org2.example.com-mycc-2.0   2019-04-15 13:51:24 +0900 JST   Up About an hour
dev-peer0.org3.example.com-mycc-2.0   2019-04-15 13:51:09 +0900 JST   Up About an hour
dev-peer1.org2.example.com-mycc-1.0   2019-04-15 10:56:13 +0900 JST   Up 4 hours
orderer.example.com                   2019-04-15 10:55:04 +0900 JST   Up 4 hours          0.0.0.0:7050->7050/tcp
peer0.org1.example.com                2019-04-15 10:55:04 +0900 JST   Up 4 hours          0.0.0.0:7051->7051/tcp
peer0.org2.example.com                2019-04-15 10:55:04 +0900 JST   Up 4 hours          0.0.0.0:9051->9051/tcp
peer0.org3.example.com                2019-04-15 13:50:35 +0900 JST   Up About an hour    0.0.0.0:11051->11051/tcp
peer1.org1.example.com                2019-04-15 10:55:04 +0900 JST   Up 4 hours          0.0.0.0:8051->8051/tcp
peer1.org2.example.com                2019-04-15 10:55:04 +0900 JST   Up 4 hours          0.0.0.0:10051->10051/tcp
peer1.org3.example.com                2019-04-15 13:50:35 +0900 JST   Up About an hour    0.0.0.0:12051->12051/tcp

のように、

  • クライアントノード 2 種
  • mycc v1.0 インスタンス 3つ (peer0.org1, peer0.org2, peer1.org2)
  • mycc v2.0 インスタンス 3つ (peer0.org1, peer0.org2, peer0.org3)
  • orderer 1 つ
  • org 3種 x peer 2つで計 6 つの Peer ノード

が起動していることがわかる。 chaincode はアップグレードしてもコンテナ自体は消えないのな。

./eyfn.sh down

単純なおそうじスクリプト。上記までで作ったものをみんな削除する。

おしまい

今回は前回の内容を踏襲してる部分が殆どだったので、わりと簡単だった。

次回は、前回飛ばしていた Writing Your First Application チュートリアルに進む予定。

hyperledger-fabric.readthedocs.io

Hyperledger Fabric と戯れる part.1

ということで今日はさくっと Hyperledger Fabric を動かしてみる。

ちょっと調べたかんじ Hyperledger Composer も便利そうだったので、あわせて導入だけしておく。

その前に

Hyperledger Fabric がどんなもんか、用語とその内容がわかる程度にザックリ読んどく。

hyperledger-fabric.readthedocs.io

理解したことをすげえざっくりまとめると

  • Network
    • Hyperledger Fabric をつかって作るシステム全体を指すよ
    • 1つ以上の Organization が network の管理をする権利を持てるよ
      • これは厳密には System Channel という特別な channel として扱われるよ
    • 1つ以上の Channel を含むよ
    • 1つ以上の Orderer を含むよ
  • Organization
    • この network に参加する組織を指すよ
    • 1つ以上の channel に参加できるよ
    • 1つ以上の peer を持つよ
    • 1つの MSP を持つよ
  • Peer
    • (物理的な意味で) organization が管理するノードだよ
      • つまり、 1 つ以上の channel に参加できるよ
        • つまり、 1 つ以上の台帳を持つよ
      • (論理的な意味では) channel にホストされるノードだよ
    • 4 種の役割があり、各 peer は1つ以上の役割を担うよ
      • Commitment Peer
        • 台帳を保有しているよ
        • 検証されたトランザクションを自身の台帳に反映するよ
        • 基本的にすべての peer は commitment peer になると思うよ
      • Endorsement Peer
      • Anchor Peer
        • network に参加する他の organization との通信の窓口になるよ
      • Leader Peer
        • orderer と直接やりとりするよ
        • 1 organization につき必ず 1 leader peer が必要だよ
  • Channel
    • 1つの台帳と、それを扱う organization たちをまとめた単位だよ
    • channel に所属する organization だけが channel に所属する台帳を保持、制御できるよ
    • 1つ以上の peer をもつよ
      • 常に 1 つの Leader Peer をもつよ
      • 少なくとも 1 つの Commitment Peer をもつよ
      • 少なくとも 1 つの Endorsement Peer をもつよ
  • 台帳
    • そのままだよ
      • 内部的には、現在(最新)の状態を保持した DB と、それまでの操作履歴を保持した BlockChain で構成されるよ
    • 台帳とおなじ channel に所属する organization (の peer) がそれぞれ全く同じ台帳のコピーを保持してるよ
    • 台帳とおなじ channel に所属する organization (の peer) が chaincode を通して台帳を制御できるよ
      • DB みたいなノリでアクセスできるよ
  • Endorsement Policy
    • トランザクションが受け入れられるために、どの organization が承認する必要があるかの定義だよ
    • channel 構成に含まれ、channel 内のすべての endorsement peer は同一のポリシで動く必要があるよ
  • Chain Code
    • 台帳に対する操作を定義したプログラムみたいなものだよ
    • peer にインストールし、インスタンス化することで使用することができるよ
      • バージョンは管理されるよ
  • Orderer
    • 各 peer に対するトランザクションの順番やコンセンサスを管理する特別なノードだよ
    • network につき 1 つ以上含まれるよ
      • 複数ある場合は、Apache Kafka で冗長構成をとるだけだよ
    • network にあるいずれかの organization に所属しているよ
      • 複数ある場合は、複数の organization でそれぞれ持つことができるよ
    • network に含まれるすべての channel を跨いで存在しているよ
      • 所属している organization がすべての channel に含まれていなくても大丈夫だよ
  • CA
    • ただの認証局だよ
      • Peer や Orderer、 Client とかに X.509 証明書を分配するよ
      • Fabric-CA というものがパッケージに含まれてるけど、普通に組織独自の CA 使えばいいよ
    • 通常、各 organization がそれぞれ CA を持ってるよ
  • MSP
    • Membership Services Provider
    • CA をつかって、network 内の各ノードやチャンネル、ユーザなんかの Hyperledger Fabric 特有のあれこれを管理するよ
    • 各 organization がそれぞれ運用するよ
  • Client
    • network 中の台帳を参照・制御するアプリケーションだよ
      • あくまでも Hypeledger Fabric システムに対するクライアントを指すので混乱しないよう注意だよ
    • たいていは各 organization がそれぞれに作成・管理するよ

Identity と MSP あたりがわりと理解あやしい。それら含め何か勘違いしてるようなら後ほど修正する。 (ので、指摘等してくれる人がいたら嬉しい。)

インストール

公式ドキュメント通り進める。インストールマニュアルを和訳する趣味はないのでリンクだけ貼っとく。

注意すべきところは、 Node.js は v8 系じゃないとダメとの事なので nvm を使ってバージョンを指定すること、pyenv などで python コマンドのバージョンを 3 系にしてるときは忘れず 2.7 系になるようにしておくこと、くらい。 ということで prereqs がわりと重要なのであわせて貼っとく。

なお Fabric のインストールスクリプトはカレントディレクトリに samples リポジトリをクローンするので、変な場所で実行すると微妙な気持ちになるので注意。

もう既にインストール済なものもあったので色々飛ばしたり等したのもあるが、 MacOS 10.14.4 の環境でだいたいこんなかんじになった。

$ node --version
v8.15.1
$ python --version
Python 2.7.10
$ go version
go version go1.12.1 darwin/amd64
$ docker --version
Docker version 18.09.2, build 6247962
$ docker-compose --version
docker-compose version 1.23.2, build 1110ad01
$ composer --version
v0.20.8
$ docker images -a | sort  
REPOSITORY                     TAG                 IMAGE ID            CREATED             SIZE
hyperledger/fabric-ca          1.2.1               be8400395e15        6 months ago        251MB
hyperledger/fabric-ca          1.4.1               3a1799cda5d7        9 hours ago         252MB
hyperledger/fabric-ca          latest              3a1799cda5d7        9 hours ago         252MB
hyperledger/fabric-ccenv       1.2.1               8651e7160d88        6 months ago        1.43GB
hyperledger/fabric-ccenv       1.4.1               d7433c4b2a1c        9 hours ago         1.43GB
hyperledger/fabric-ccenv       latest              d7433c4b2a1c        9 hours ago         1.43GB
hyperledger/fabric-couchdb     0.4.10              3092eca241fc        9 months ago        1.61GB
hyperledger/fabric-couchdb     0.4.15              8de128a55539        3 weeks ago         1.5GB
hyperledger/fabric-couchdb     latest              8de128a55539        3 weeks ago         1.5GB
hyperledger/fabric-javaenv     1.4.1               b8c9d7ff6243        11 hours ago        1.74GB
hyperledger/fabric-javaenv     latest              b8c9d7ff6243        11 hours ago        1.74GB
hyperledger/fabric-kafka       0.4.15              b4ab82bbaf2f        3 weeks ago         1.44GB
hyperledger/fabric-kafka       latest              b4ab82bbaf2f        3 weeks ago         1.44GB
hyperledger/fabric-orderer     1.2.1               b1a1dd788841        6 months ago        152MB
hyperledger/fabric-orderer     1.4.1               ec4ca236d3d4        9 hours ago         173MB
hyperledger/fabric-orderer     latest              ec4ca236d3d4        9 hours ago         173MB
hyperledger/fabric-peer        1.2.1               ef0e7788ead0        6 months ago        159MB
hyperledger/fabric-peer        1.4.1               a1e3874f338b        9 hours ago         178MB
hyperledger/fabric-peer        latest              a1e3874f338b        9 hours ago         178MB
hyperledger/fabric-tools       1.4.1               432c24764fbb        9 hours ago         1.55GB
hyperledger/fabric-tools       latest              432c24764fbb        9 hours ago         1.55GB
hyperledger/fabric-zookeeper   0.4.15              20c6045930c8        3 weeks ago         1.43GB
hyperledger/fabric-zookeeper   latest              20c6045930c8        3 weeks ago         1.43GB

CA とか Orderer とか Peer なんかのイメージがインストールされてることが確認できた。

Hyperledger Fabric の最新版は 1.4.1 だが、Composer の最新版の対象バージョンはいまだ 1.2 系なので一部 1.2 系が含まれている。 v1.4 系が LTS なのと、v1.4 系からプログラミングモデルが更新されたとの事なので、できるかぎり v1.2 は使わないで行きたいところではある。

チュートリアルを動かす

チュートリアルめっちゃ沢山あるのでガンガンすすめてく。

sample リポジトリは上述の通りインストールスクリプトを実行した場所に clone されている。

以降は tags/v1.4.1(6c0203a) での勉強結果。

Building Your First Application チュートリアル

チュートリアルの目次を見ると Writing Your First Application を先にやるべきっぽいのだが、動かしかた知る前に書きかたから入るのってどうなのと思ったので先にこっち。

./byfn.sh generate

出力を見ればなんとなくわかるけど、以下のことをやってる。(自力で分析した内容も多分に含まれるため、正確かどうかは怪しい)

  1. cryptogencrypto-config.yaml の設定通りに証明書を発行して ./crypto-config を生成
    • cryptogen は以下を生成して、各ノード、ユーザの設定となるようディレクトリツリーをつくり配置する
      • orderer ドメイン(example.com) の CA、全ユーザ(Admin)、全ノード(orderer〜orderer5) それぞれに対する証明書と鍵
        • 証明書はそれぞれ交互に配布しあう
      • org1.example.com ドメインの CA、全ユーザ(Admin, User1)、全ノード(peer0, peer1) それぞれに対する証明書と鍵
        • 証明書はそれぞれ交互に配布しあう (ユーザ同士は交換しない)
      • org2.example.com ドメインの CA、全ユーザ(Admin, User1)、全ノード(peer0, peer1) それぞれに対する証明書と鍵
        • 証明書はそれぞれ交互に配布しあう (ユーザ同士は交換しない)
  2. 上記で生成した鍵内容を docker-compose-e2e-template.yaml に適用して docker-compose-e2e.yaml を生成
    • この docker-compose-e2e.yaml なんだけど、以降どこでも使われてない
    • これは別のテスト用のものなので今回は無視する。
  3. configtxgenconfigtx.yaml の設定通りに Orderer の設定を生成して ./channel-artifacts/genesis.block を生成
  4. configtxgenconfigtx.yaml の設定通りに Channel の設定を生成して ./channel-artifacts/channel.tx を生成
    • configtx.yaml から channel の構成について抜粋したみたいなバイナリファイルを作っている。
      • 以降の手順で channel を作成する際に設定ファイルとして渡されている
  5. configtxgenconfigtx.yaml の設定通りに Peer1 の設定を生成して ./channel-artifacts/Org1MSPanchors.tx を生成
  6. configtxgenconfigtx.yaml の設定通りに Peer2 の設定を生成して ./channel-artifacts/Org2MSPanchors.tx を生成
    • configtx.yaml から organization の構成について抜粋したみたいなバイナリファイルを作っている。
      • 以降の手順で anchor peer を channel に登録する際に設定ファイルとして渡されている
./byfn.sh up

オプションで chaincode を Go 実装じゃなくて Node 実装や Java 実装に切り替えられたり、デフォルトで 1 こしか起動させない orderer を Kafka ないし Raft で並列に動かさせることもできる。StateDB を CouchDB (デフォルトは LevelDB) にすることもできるらしい。

今回は既にわりとおなかいっぱいなのでデフォルトオプションにて実行した。

以降、やはり自力で分析した内容も多分に含まれるため、正確かどうかは怪しい

  1. docker-compose で各ノードを起動する
    • オプション等をつけなかった場合、 docker-compose-cli.yaml だけが使用される。
      • ここに orderer2 〜 orderer5 までの 4 つの orderer は含まれていない
      • 各ノードは cryptogen で作ったディレクトリツリーの自身に対応する部分を適宜マウントするようになっている
    • 起動するのは以下。なおすべて byfn ネットワークに属する。
      • orderer.example.com
      • peer0.org1.example.com
      • peer1.org1.example.com
      • peer0.org2.example.com
      • peer1.org2.example.com
      • cli
        • 突然現れたけど、これはクライアントノード。
          • docker exec cli peer ... のように呼ぶことで peer0.org1.example.com を対象に(環境変数のセット等をせずとも)簡単に peer コマンドが呼べるようになってる
      • CA サーバは起動してない。
        • (あとで調べる)
  2. 作った cliscripts/script.sh を実行させる
    1. peer channel create
      • orderer に対して実行している
        • TLS を有効にし、crypto-config/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pemTLS CA 証明書として付加したうえで、
        • configtxgen で作成した channel.tx の設定で、
        • mychannel という名前の channel を作成させる
      • ここで mychannel.blockcli の working directory に作成される
    2. peer channel join
      • 全 peer ノード(4つ)それぞれに対して実行してる。
        • 上で作成された mychannel.block を渡して、対象 peer ノードを mychannel に参加させる
    3. peer channel update
      • orderer に対して実行している
        • Anchor Peer となる 2 つの peer0 ノードそれぞれに対して、
        • TLS を有効にし、crypto-config/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pemTLS CA 証明書として付加したうえで、
        • configtxgen で作成した Org*MSPanchors.tx の設定で、
        • mychannel を更新させる
      • これで Org* のアンカーピアとして peer0.org*.example.com が設定される
        • 設定内容は channel 内の全 peer に伝達される
    4. peer chaincode install
      • Anchor Peer である 2つの peer0.org*.example.comノードに対して実行されている
        • 文字通り chaincode をインストールしている
        • パス は ../chaincode/chaincode_example02/go/
          • ビルドとかはせず、そのまんま渡しているっぽい
          • chaincode の内容は次のチュートリアルで学ぶのでとりあえず無視。
        • chaincode 名は mycc、 バージョン 1.0、実装言語は golang、とそれぞれ指定している。
    5. peer chaincode instantiate
      • peer0.org2.example.com ノード 1 つのみに対して実行されている
        • orderer orderer.example.com に対し、
          • TLS を有効にし、crypto-config/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pemTLS CA 証明書として付加したうえで、
        • mychannel において、
        • 初期化メッセージ {"Args":["init","a","100","b","200"]} を渡し、
          • "a" に "100" を、 "b" に "200" をそれぞれセットしているっぽい
        • ポリシー AND ('Org1MSP.peer','Org2MSP.peer') も渡して、
          • Org1 の承認、および Org2 の承認の 2 つが必要ということ
        • mycc のバージョン 1.0インスタンス化する
      • どうもこのタイミングでソースコードのビルドが行われているらしい
      • インスタンス化の操作は channel 内の全 peer に伝達される
        • インストールされているのは peer0.org* の 2 ノードだけなので、実際に query, invoke ができるのはこれら 2 ノードだけとなる
    6. peer chaincode query
      • peer0.org1 ノードに対する query の動作確認
        • "a" の値を問い合わせて "100" であることを確認しているっぽい
        • chaincode の内容は次のチュートリアルで学ぶのでとりあえず無視。
    7. peer chaincode invoke
      • peer0.org1 および peer0.org2 ノードに対する invoke の動作確認
        • "a" から "b" に "10" だけ移動しているっぽい
        • chaincode の内容は次のチュートリアルで学ぶのでとりあえず無視。
    8. peer chaincode install
      • peer1.org2.example.com ノードにも chaincode をインストールしている
        • chaincode は既にインスタンス化されているため、peer1.org2.example.commycc は直ちに使えるようになる
        • インストールされているのは peer0.org* を含めた 3 ノードで、実際に query, invoke ができるのもこれら 3 ノードとなる
    9. peer chaincode query
      • peer1.org2 ノードに対する query の動作確認
        • "a" の値を問い合わせて "90" であることを確認しているっぽい
        • chaincode の内容は次のチュートリアルで学ぶのでとりあえず無視。

ここで、Docker コンテナを一覧してみると

$ docker ps --format "table {{.Names}}\t{{.CreatedAt}}\t{{.Status}}\t{{.Ports}}" | sort
NAMES                                 CREATED AT                      STATUS              PORTS
cli                                   2019-04-12 17:04:04 +0900 JST   Up 2 hours
dev-peer0.org1.example.com-mycc-1.0   2019-04-12 17:04:55 +0900 JST   Up 2 hours
dev-peer0.org2.example.com-mycc-1.0   2019-04-12 17:04:38 +0900 JST   Up 2 hours
dev-peer1.org2.example.com-mycc-1.0   2019-04-12 17:05:12 +0900 JST   Up 2 hours
orderer.example.com                   2019-04-12 17:04:03 +0900 JST   Up 2 hours          0.0.0.0:7050->7050/tcp
peer0.org1.example.com                2019-04-12 17:04:03 +0900 JST   Up 2 hours          0.0.0.0:7051->7051/tcp
peer0.org2.example.com                2019-04-12 17:04:03 +0900 JST   Up 2 hours          0.0.0.0:9051->9051/tcp
peer1.org1.example.com                2019-04-12 17:04:03 +0900 JST   Up 2 hours          0.0.0.0:8051->8051/tcp
peer1.org2.example.com                2019-04-12 17:04:03 +0900 JST   Up 2 hours          0.0.0.0:10051->10051/tcp

こんな感じで dev-*-mycc-1.0 というものが出来ている。これが要するにインスタンス化した chaincode って事らしい。

./byfn.sh down

単純なおそうじスクリプト。上記までで作ったものをみんな削除する。

まとめ

まずは起動と動作確認とを実施できた。今回はお勉強項目がやたらと多かったのですっごい疲れた。

Hyperledger Fabric と戯れる part.0

首題について勉強した結果をどこかに纏めておきたかったのだが、適した場所がとくに見当らなかったのでここに残しとく。 あとでより適したどこかに移動するかも。

ブロックチェーンてなーに

ブロックのチェーンである。

ブロックは主に

で構成され、それが一つなぎに続くことでシステム全体における取引履歴などをつくりあげる。

このとき、Block(n-1) のトランザクションを改竄しようとすると、Block(n) にある Block(n-1) のハッシュ値と不整合が起きる。では Block(n) にある Block(n-1) のハッシュ値も改竄しよう、となると Block(n+1) にある Block(n) のハッシュ値と不整合が起きる・・・といったかんじで、改竄がわりと困難になるため、そういった後から改竄とかそういうのが簡単にできないようなもの(それこそ仮想通貨の取引とかね)に使われる。

もちろん上記説明だけだと不十分で、ブロックを作ること自体が膨大な計算コストを要しているため改竄対象以降のブロックを悉く改竄していくのが余計に大変になっているだとか、ブロックチェーンが分散管理されているため一箇所だけ改竄しても意味ないとか、いろいろな理論や仕組みが複雑に絡んで所謂「セキュアな」帳簿を構成することができている。

当然だが俺はその全てを正確に説明できないし知ってもいない。そういうの全部わかってて実際にゼロからそういうのを作れる人は年収2000万とか貰う超一流のブロックチェーンエンジニアなわけで、俺はそうでない年収3桁万の一般的なシステムエンジニアである。ああ、金が欲しい

分散台帳ってなーに

ブロックチェーンで構成した台帳を、分散管理するシステム。実際は分散台帳技術がブロックチェーンの派生らしいのだが、一般には分散台帳技術も含めて「ブロックチェーン技術」て言いがちよね。

分散台帳は、そのネットワークの参加者がそれぞれにトランザクションを検証し、コンセンサスが取れたことを確認して、その後に全参加者の台帳(ブロックチェーン)にトランザクションを追加する。 そうすることによって、各参加者の持つ台帳の整合性が取れ、全参加者が同一の台帳を分散保持していると言うことができるらしい。

ようするにブロックチェーンて何が嬉しいの?

データ構造的に改竄されにくいとか、分散管理による中央集権化の回避だの冗長性だのと色々言われるが、ようするに信頼性が高くなるって事で良いらしい。

ただし、そのために(普通のRDBなんかと比べたら)速度とかは多少なり犠牲になってしまうとのこと。

Hyperledger Fabric てなーに

Linux Foundation が主導するOSSブロックチェーンプラットフォーム 「Hyperledger Project」のうちの 1 つで、コンソーシアム型の分散台帳フレームワーク。 「うちの 1 つ」といってるがコレくらいしか名前聞かない。あとは開発ツール? の Composer はたまに聞くかな程度。

コンソーシアム型てなーに

Bitcoin や Ethereumみたいな(悪意ある奴も含む)不特定多数が参加するもの(パブリック型)に対し、予めお互い信頼しあっている複数の組織だけで利用するものがコンソーシアム型。

特定組織だけの許可制での参加を前提とすることで、パブリック型ほどには膨大な計算を必要としなくて済み、ようするに比較的速いらしい。

また、1 組織だけのプライベート型なるものもあるらしいが、「分散台帳」なのに分散管理しないとはこれいかに? あまり意味なさそうなので興味もなく調べてもいない。

なんで Hyperledger Fabric なの?

仕事で使うと指示されたからである。

もちろん他にもブロックチェーン基盤はたくさんあり、それぞれにメリットデメリット、長所短所、向き不向きなどはあるのだろうが、調べてすらいない。かなしい。

今日はここまで

そう、Hyperledger Fabric とまだ一切戯れてない。

タミヤ BT-42 をつくる その1

ひさしぶりの更新。この季節は湿気がつよくて塗装って感じじゃないね。 それと家の裏にあったアパートが取り壊され一軒家が建つという激しいイベントがあってしばらくはベランダが粉まみれ、サフ吹くどころか窓あけて換気すらままならない状況だったのもある。

たんにGWので燃え尽きてたってのもある。

ということで中途半端に作りかけて放置していた BT-42 をほじくり出して塗装をはじめてみた。 キットの出来がすごく良くて気に入ってる。

改修ポイントはエッチングパーツ手前にある四角い何かのパーツを、マウントしてる何かを取り外して枠だけにしました的な感じにするのと、砲塔向かって左側に穴とか出っぱりを足して左右対象にするの程度。正直この変な枠みたいなのとか出っぱりが何なのかサッパリわからない。穴は視察孔だと思うんだけど・・・

f:id:illness072:20160620105319j:plain

継続仕様の雲っぽい迷彩。暗めのグレーでベースを噴いて、明るいグレーで前後左右遠近ひたすらランダムに動かして何となくパターンをつけていく感じ。アハパン見るともっとパターン細かいんだけど、あんまりマダラマダラしたイメージなかったんでぼかし気味に仕上げた。

とはいえあまり上手くいった感が感じられないのが悔しい。練習あるのみだな

f:id:illness072:20160620105325j:plain

履帯色が手元になかったのでOVMから塗ってる。いっぱいあるので大変だけど、車体から浮いてマウントされてるので車体をブラウンで汚してしまいリタッチ、みたいな作業があんまりなかったのが幸い。金属部分はちょっとテカテカしすぎたな。

ところでこいつ、工作の途中でツールウォッシュをぶちまけてしまいパーツをとろかしてしまうという大失態をおかしてる。幸いなことに模型屋で転がってたBT-7を新たに買い、とろかした車体パーツをひっぺがし置き換え、せっかく取り外しできるように工作してた履帯と転輪はくっついちゃったので癒着部分を適当にモールド掘ってごまかし、BT-7の転輪と差し替えで装輪状態を再現することにした。というわけで転輪は2倍の量塗ることになる。

タコム オブイェークト279をつくる восемь

GW8日め、最終日。今日はクリア噴いて履帯の組付しておしまい。 試作車両だし、実戦とかも経験ないだろうし演習とかもそれほどやってないんじゃないかな、と思ったので、それこそ作ったはいいけどすぐお蔵入りになっちゃった子って感じで殆ど全く汚しは入れてない。

ということで完成品ギャラリーです。

砲塔にかがやくプラウダマーク。尊い。 あんまり汚れてない戦車模型でもガルパンデカールが貼ってあれば何となくそういうもんかなって気がするんじゃないかという打算もある。

f:id:illness072:20160808164535j:plain

左右。こうして見ると砲身がほんとに長い。撮影でしぬほど苦労した。 よーく見ると背景に継ぎ目が見えるけど、気にしない。

f:id:illness072:20160808161604j:plain f:id:illness072:20160808162713j:plain

前後。砲塔の上にゴチャゴチャ色々と載ってて、近代の戦車って感じがいいね。 ポロリが多かったので今後保存や引越しなどでも気をつけねばならない

f:id:illness072:20160808162946j:plain f:id:illness072:20160808162855j:plain

短砲身バージョンも砲身差し替えで再現。バランスはいいけど、長砲身を見慣れちゃうと何か弱そう・・・

f:id:illness072:20160808165538j:plain

パッケ絵みたいなアングルで。パッケは逆光でそれはもうディストピア感あってすげえカッコいいんだけど、撮影環境的にはこれくらいが限界。 とはいえ4本履帯がすごく目立って、車体の異形さも際立つのでこのアングルで見るとやはりインパクトはあるね。

f:id:illness072:20160808163919j:plain

せっかくなので兵士とツーショット。ああこれスゴい、ほんと核戦争とか起きないで良かったね・・・

f:id:illness072:20160808165309j:plain

ということでタコムのオブイエークト279でした。履帯が死ぬほど辛いこと以外は良いキットだったと思います。オススメは・・・しないけど

作業時間は2h、合計で50h。途中もうだめかと思ったけど、どうにかGW中に完成させることができて良かった。良いゴールデンウィークでした。