はじめに
今回はHyperledger Fabricのサンプルアプリケーションを動かしてみます。本エントリは次のページで紹介されている手順に従って進めていきます。
Writing Your First Application — hyperledger-fabricdocs master documentation
実行環境
- Max OS High Sierra Version 10.13
- Docker version 17.09.0-ce
- Docker Compose version 1.16.1
- Go version 1.9
- Node.js version 8.6
Hyperledger Fabricのダウンロード
次のコマンドを実行します。
$ mkdir ~/fabric $ cd ~/fabric $ curl -sSL https://goo.gl/Q3YRTi | bash
これによりブロックチェーンネットワークを構築するために必要な次のバイナリを入手します。
- cryptogen
- configtxgen
- configtxlator
- peer
$ ls bin configtxgen configtxlator cryptogen get-docker-images.sh orderer peer
同スクリプトはHyperledger FabricのdockerイメージをDocker Hubよりダウンロードします。
$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE hyperledger/fabric-ca latest 2736904862db 10 days ago 218MB hyperledger/fabric-ca x86_64-1.1.0-preview 2736904862db 10 days ago 218MB hyperledger/fabric-tools latest c584c20ac82b 10 days ago 1.42GB hyperledger/fabric-tools x86_64-1.1.0-preview c584c20ac82b 10 days ago 1.42GB hyperledger/fabric-couchdb latest 5b8a15e6e972 10 days ago 1.57GB hyperledger/fabric-couchdb x86_64-1.1.0-preview 5b8a15e6e972 10 days ago 1.57GB hyperledger/fabric-kafka latest cf09c5534ef9 10 days ago 1.37GB hyperledger/fabric-kafka x86_64-1.1.0-preview cf09c5534ef9 10 days ago 1.37GB hyperledger/fabric-zookeeper latest ac127485fdc7 10 days ago 1.37GB hyperledger/fabric-zookeeper x86_64-1.1.0-preview ac127485fdc7 10 days ago 1.37GB hyperledger/fabric-orderer latest 2fccc91736df 10 days ago 159MB hyperledger/fabric-orderer x86_64-1.1.0-preview 2fccc91736df 10 days ago 159MB hyperledger/fabric-peer latest 337f3d90b452 10 days ago 165MB hyperledger/fabric-peer x86_64-1.1.0-preview 337f3d90b452 10 days ago 165MB hyperledger/fabric-javaenv latest cd459b218651 10 days ago 1.49GB hyperledger/fabric-javaenv x86_64-1.1.0-preview cd459b218651 10 days ago 1.49GB hyperledger/fabric-ccenv latest 82489d1c11e8 10 days ago 1.35GB hyperledger/fabric-ccenv x86_64-1.1.0-preview 82489d1c11e8 10 days ago 1.35GB
開発環境のセットアップ
Hyperledger Fabricのサンプルをgitでcloneします。
$ git clone https://github.com/hyperledger/fabric-samples.git $ cd fabric-samples
以降では次のfabcarディレクトリで作業します。
$ cd fabcar $ ls enrollAdmin.js invoke.js package.json query.js registerUser.js startFabric.sh
念のためdockerコンテナとネットワークを削除しておきます。
$ docker rm -f $(docker ps -aq) $ docker network prune
すでに以降の作業を実施済みの場合には次のコマンドでfabcarチェインコード用のdockerイメージも削除します。
$ docker rmi dev-peer0.org1.example.com-fabcar-1.0-5c906e402ed29f20260ae42283216aa75549c571e2e380f3615826365d8269ba
アプリケーションの実行に必要なライブラリをインストールするため次のコマンドを実行します。 以降ではCAサーバにアクセスするためにnode_modules/fabric-ca-client、 peerやordering serviceと対話するためにnode_modules/fabric-clientを使用していきます。
$ npm install
続けて次のスクリプトを実行することでネットワークを起動します。このコマンドはFabricの各コンテナを用意します。
fabcarネットワークの詳細はこちらに説明があります。
Understanding the Fabcar Network — hyperledger-fabricdocs master documentation
$ ./startFabric.sh $ docker images REPOSITORY TAG IMAGE ID CREATED SIZE dev-peer0.org1.example.com-fabcar-1.0-5c906e402ed29f20260ae42283216aa75549c571e2e380f3615826365d8269ba latest bf75bac8b3f9 2 minutes ago 151MB ... $ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES b4b2e2be6dc7 dev-peer0.org1.example.com-fabcar-1.0-5c906e402ed29f20260ae42283216aa75549c571e2e380f3615826365d8269ba "chaincode -peer.a..." 4 minutes ago Up 4 minutes dev-peer0.org1.example.com-fabcar-1.0 a4f01226a050 hyperledger/fabric-tools "/bin/bash" 6 minutes ago Up 6 minutes cli dbce2a81cb36 hyperledger/fabric-peer "peer node start" 7 minutes ago Up 7 minutes 0.0.0.0:7051->7051/tcp, 0.0.0.0:7053->7053/tcp peer0.org1.example.com c83fd30320e2 hyperledger/fabric-couchdb "tini -- /docker-e..." 7 minutes ago Up 7 minutes 4369/tcp, 9100/tcp, 0.0.0.0:5984->5984/tcp couchdb 0dd907f8cce3 hyperledger/fabric-orderer "orderer" 7 minutes ago Up 7 minutes 0.0.0.0:7050->7050/tcp orderer.example.com 86ef00f4705d hyperledger/fabric-ca "sh -c 'fabric-ca-..." 7 minutes ago Up 7 minutes 0.0.0.0:7054->7054/tcp ca.example.com
ユーザの登録
前述のネットワーク立ち上げ時にadminユーザが認証局(CA)に登録されています。
enrollAdmin.jsでadminの電子証明書(eCert)を取得します。
このプログラムは公開鍵と秘密鍵をhfc-key-storeに作成し、証明書署名要求(CSR)で公開鍵証明書を発行します。
続けて、registerUser.jsではadminユーザでCAと通信しLedgerにアクセスするuser1ユーザを登録します。このプログラムもまた、CSRを実行し証明書と鍵をhfc-key-storeに出力します。
$ node enrollAdmin.js $ node registerUser.js $ ls hfc-key-store/ admin ...-pub ...-priv user1 ...-pub ...-priv
Ledgerの参照
query.jsを使用し、fabcarチェインコードのqueryAllCarsを呼び出します。
fabric-samples/fabcar/query.js
const request = { chaincodeId: 'fabcar', fcn: 'queryAllCars', args: [''] };
$ node query.js Store path:.../fabric-samples/fabcar/hfc-key-store Successfully loaded user1 from persistence Query has completed, checking results Response is [{"Key":"CAR0", "Record":{"colour":"blue","make":"Toyota","model":"Prius","owner":"Tomoko"}}, {"Key":"CAR1", "Record":{"colour":"red","make":"Ford","model":"Mustang","owner":"Brad"}}, {"Key":"CAR2", "Record":{"colour":"green","make":"Hyundai","model":"Tucson","owner":"Jin Soo"}}, {"Key":"CAR3", "Record":{"colour":"yellow","make":"Volkswagen","model":"Passat","owner":"Max"}}, {"Key":"CAR4", "Record":{"colour":"black","make":"Tesla","model":"S","owner":"Adriana"}}, {"Key":"CAR5", "Record":{"colour":"purple","make":"Peugeot","model":"205","owner":"Michel"}}, {"Key":"CAR6", "Record":{"colour":"white","make":"Chery","model":"S22L","owner":"Aarav"}}, {"Key":"CAR7", "Record":{"colour":"violet","make":"Fiat","model":"Punto","owner":"Pari"}}, {"Key":"CAR8", "Record":{"colour":"indigo","make":"Tata","model":"Nano","owner":"Valeria"}}, {"Key":"CAR9", "Record":{"colour":"brown","make":"Holden","model":"Barina","owner":"Shotaro"}}]
実行したチェインコードの関数は次の通りです。
fabric-samples/chaincode/fabcar/fabcar.go
func (s *SmartContract) queryAllCars(APIstub shim.ChaincodeStubInterface) sc.Response { startKey := "CAR0" endKey := "CAR999" resultsIterator, err := APIstub.GetStateByRange(startKey, endKey)
LedgerにアクセスするAPIの仕様はこちらにあります。 godoc.org github.com
Ledgerの更新
fabcarチェインコードのcreateCarで新たなCARをLedgerに追加します。
fabric-samples/fabcar/invoke.js
var request = { chaincodeId: 'fabcar', fcn: 'createCar', args: ['CAR10', 'Chevy', 'Volt', 'Red', 'Nick'], chainId: 'mychannel', txId: tx_id };
fabric-samples/chaincode/fabcar/fabcar.go
func (s *SmartContract) createCar(APIstub shim.ChaincodeStubInterface, args []string) sc.Response { if len(args) != 5 { return shim.Error("Incorrect number of arguments. Expecting 5") } var car = Car{Make: args[1], Model: args[2], Colour: args[3], Owner: args[4]} carAsBytes, _ := json.Marshal(car) APIstub.PutState(args[0], carAsBytes) return shim.Success(nil) }
$ node invoke.js Store path:.../fabric-samples/fabcar/hfc-key-store Successfully loaded user1 from persistence Assigning transaction_id: 97ae720f071443b8f73b5ab1e8ed1a87d8a04ba3904479f24cdb146486edcbfa Transaction proposal was good Successfully sent Proposal and received ProposalResponse: Status - 200, message - "OK" info: [EventHub.js]: _connect - options {} The transaction has been committed on peer localhost:7053 Send transaction promise and event listener promise have completed Successfully sent transaction to the orderer. Successfully committed the change to the ledger by the peer
最後にCAR10が正しく追加されているかを確認します。 fabcarのqueryCarに引数CAR10を渡し、query.jsを実行します。
query.js
const request = { chaincodeId: 'fabcar', fcn: 'queryCar', args: ['CAR10'] };
fabric-samples/chaincode/fabcar/fabcar.go
func (s *SmartContract) queryCar(APIstub shim.ChaincodeStubInterface, args []string) sc.Response { if len(args) != 1 { return shim.Error("Incorrect number of arguments. Expecting 1") } carAsBytes, _ := APIstub.GetState(args[0]) return shim.Success(carAsBytes) }
$ node query.js Store path:.../fabric-samples/fabcar/hfc-key-store Successfully loaded user1 from persistence Query has completed, checking results Response is {"colour":"Red","make":"Chevy","model":"Volt","owner":"Nick"}
期待通りの結果が得られました。
さいごに
本エントリではサンプルアプリケーションfabcarを動かしてみました。
Ledgerにアクセスするアプリケーションの実装イメージが少し湧いた気がします。
次回はまだ未定ですが、JavaアプリケーションからHyperledger Fabric SDKを使用してみたいと考えてます。